diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index f544e74..f39b2ef 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -1,139 +1,139 @@ import SwiftUI #if os(macOS) import Sparkle #endif @main struct CheckForDebugModifier { static func main() { #if os(macOS) if NSEvent.modifierFlags.contains(.shift) { print("Debug launch detected") // Run debug-mode launch code here } else { print("Normal launch detected") // Don't do anything } #endif WriteFreely_MultiPlatformApp.main() } } struct WriteFreely_MultiPlatformApp: App { @StateObject private var model = WriteFreelyModel() #if os(macOS) // swiftlint:disable:next weak_delegate @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @State private var selectedTab = 0 #endif var body: some Scene { WindowGroup { ContentView() .onAppear(perform: { if let lastDraft = model.editor.fetchLastDraftFromUserDefaults() { self.model.selectedPost = lastDraft } else { createNewLocalPost() } }) .environmentObject(model) .environment(\.managedObjectContext, LocalStorageManager.persistentContainer.viewContext) // .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info. } .commands { #if os(macOS) CommandGroup(after: .appInfo, addition: { Button("Check For Updates") { SUUpdater.shared()?.checkForUpdates(self) } }) #endif CommandGroup(replacing: .newItem, addition: { Button("New Post") { createNewLocalPost() } .keyboardShortcut("n", modifiers: [.command]) }) CommandGroup(after: .newItem) { Button("Refresh Posts") { DispatchQueue.main.async { model.fetchUserCollections() model.fetchUserPosts() } } .disabled(!model.account.isLoggedIn) .keyboardShortcut("r", modifiers: [.command]) } SidebarCommands() PostCommands(model: model) CommandGroup(after: .help) { Button("Visit Support Forum") { #if os(macOS) NSWorkspace().open(model.helpURL) #else UIApplication.shared.open(model.helpURL) #endif } } } #if os(macOS) Settings { TabView(selection: $selectedTab) { MacAccountView() .environmentObject(model) .tabItem { Image(systemName: "person.crop.circle") Text("Account") } .tag(0) MacPreferencesView(preferences: model.preferences) .tabItem { Image(systemName: "gear") Text("Preferences") } .tag(1) MacUpdatesView() .tabItem { Image(systemName: "arrow.down.circle") Text("Updates") } .tag(2) } - .frame(minWidth: 300, maxWidth: 300, minHeight: 200, maxHeight: 200) + .frame(minWidth: 500, maxWidth: 500, minHeight: 200) .padding() // .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info. } #endif } private func createNewLocalPost() { 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 { self.model.selectedPost = managedPost } } } diff --git a/macOS/Settings/MacAccountView.swift b/macOS/Settings/MacAccountView.swift index e51dfd7..f0d4c30 100644 --- a/macOS/Settings/MacAccountView.swift +++ b/macOS/Settings/MacAccountView.swift @@ -1,20 +1,18 @@ import SwiftUI struct MacAccountView: View { @EnvironmentObject var model: WriteFreelyModel var body: some View { Form { - Section(header: Text("Login Details")) { AccountView() - } } } } struct MacAccountView_Previews: PreviewProvider { static var previews: some View { MacAccountView() .environmentObject(WriteFreelyModel()) } } diff --git a/macOS/Settings/MacUpdatesView.swift b/macOS/Settings/MacUpdatesView.swift index b94122d..deee83b 100644 --- a/macOS/Settings/MacUpdatesView.swift +++ b/macOS/Settings/MacUpdatesView.swift @@ -1,74 +1,93 @@ import SwiftUI import Sparkle +private enum AppcastFeedUrl: String { + case release = "https://files.writefreely.org/apps/mac/appcast.xml" + case beta = "https://files.writefreely.org/apps/mac/appcast-beta.xml" +} + struct MacUpdatesView: View { - @AppStorage("downloadUpdatesAutomatically") var downloadUpdatesAutomatically: Bool = false + @AppStorage("automaticallyChecksForUpdates") var automaticallyChecksForUpdates: Bool = false @AppStorage("subscribeToBetaUpdates") var subscribeToBetaUpdates: Bool = false @State private var lastUpdateCheck: Date? private let betaWarningString = """ -Choose release versions to update to the next stable version of WriteFreely. \ -Test versions may have bugs that can cause crashes and data loss. +To get brand new features before each official release, choose "Test versions." Note that test versions may have bugs \ +that can cause crashes and data loss. """ static let lastUpdateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .short formatter.timeStyle = .short formatter.doesRelativeDateFormatting = true return formatter }() var body: some View { - VStack(spacing: 32) { - VStack { - Text(betaWarningString) - .frame(width: 400) - .foregroundColor(Color(NSColor.placeholderTextColor)) - - Picker(selection: $subscribeToBetaUpdates, label: Text("Download:"), content: { - Text("Release versions").tag(false) - Text("Test versions").tag(true) - }) - .pickerStyle(RadioGroupPickerStyle()) - } - - Button(action: { - SUUpdater.shared()?.checkForUpdates(self) - DispatchQueue.main.async { - lastUpdateCheck = SUUpdater.shared()?.lastUpdateCheckDate - } - }, label: { - Text("Check For Updates") + VStack(spacing: 24) { + Toggle(isOn: $automaticallyChecksForUpdates, label: { + Text("Check for updates automatically") }) VStack { - Toggle(isOn: $downloadUpdatesAutomatically, label: { - Text("Check for updates automatically") + Button(action: { + SUUpdater.shared()?.checkForUpdates(self) + DispatchQueue.main.async { + lastUpdateCheck = SUUpdater.shared()?.lastUpdateCheckDate + } + }, label: { + Text("Check For Updates") }) - HStack { - Text("Last check for updates:") - .font(.caption) - if let lastUpdateCheck = lastUpdateCheck { - Text(lastUpdateCheck, formatter: Self.lastUpdateFormatter) - .font(.caption) - } else { - Text("Never") + HStack { + Text("Last checked:") .font(.caption) + if let lastUpdateCheck = lastUpdateCheck { + Text(lastUpdateCheck, formatter: Self.lastUpdateFormatter) + .font(.caption) + } else { + Text("Never") + .font(.caption) + } } } + + VStack(spacing: 16) { + HStack(alignment: .top) { + Text("Download:") + Picker(selection: $subscribeToBetaUpdates, label: Text("Download:"), content: { + Text("Release versions").tag(false) + Text("Test versions").tag(true) + }) + .pickerStyle(RadioGroupPickerStyle()) + .labelsHidden() + } + + Text(betaWarningString) + .frame(width: 350) + .foregroundColor(.secondary) } } .padding() .onAppear { lastUpdateCheck = SUUpdater.shared()?.lastUpdateCheckDate } + .onChange(of: automaticallyChecksForUpdates) { value in + SUUpdater.shared()?.automaticallyChecksForUpdates = value + } + .onChange(of: subscribeToBetaUpdates) { value in + if value { + SUUpdater.shared()?.feedURL = URL(string: AppcastFeedUrl.beta.rawValue) + } else { + SUUpdater.shared()?.feedURL = URL(string: AppcastFeedUrl.release.rawValue) + } + } } } struct MacUpdatesView_Previews: PreviewProvider { static var previews: some View { MacUpdatesView() } }