Clean up project warnings (#199)
* Set "recommended project settings" for Mac app
* Add default fallback for font typingAttribute
* Clean up linter errors
* Update extension iconset
* Fix spm errors and upgrade sparkle (#203)
* Switch WriteFreely package import from ssh to https
* Sign macOS project target for Development
This fixes a crash-on-launch bug when running Product > Run from Xcode (Product > Archive should work correctly). See https://github.com/sparkle-project/Sparkle/issues/2056 for more details.
Bug introduced by commit:
671b0540ac
* Update Sparkle to v2.0 from official repo
Previously, we forked the repo to the WriteFreely org because Sparkle didn't support tag-based SPM updates. We therefore had to pull from the `master` branch, so forking insulated us from unexpected changes.
As of 2.x Sparkle now allows for tag-based updating via SPM; we'll allow patch updates but stop short of 2.1 until we can vet changes.
* Add MacUpdatesViewModel ObservableObject
* Use MacUpdatesViewModel to handle Sparkle update logic
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 7.3 KiB |
@ -1,93 +1,109 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
|
"filename" : "notification-icon@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "notification-icon@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-small@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-small@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-40@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-40@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "AppIconExtension@2x.png",
|
"filename" : "icon-60@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "AppIconExtension@3x.png",
|
"filename" : "icon-60@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "notification-icon~ipad.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "notification-icon~ipad@2x.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-small.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-small@2x-1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-40.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-40@2x-1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-76.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "76x76"
|
"size" : "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-76@2x.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "76x76"
|
"size" : "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "icon-83.5@2x.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "83.5x83.5"
|
"size" : "83.5x83.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "ios-marketing.png",
|
||||||
"idiom" : "ios-marketing",
|
"idiom" : "ios-marketing",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 763 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 524 B |
After Width: | Height: | Size: 1.0 KiB |
@ -147,17 +147,8 @@ extension WriteFreelyModel {
|
|||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let managedPost = WFAPost(context: LocalStorageManager.standard.container.viewContext)
|
let managedPost = WFAPost(context: LocalStorageManager.standard.container.viewContext)
|
||||||
managedPost.postId = fetchedPost.postId
|
self.importData(from: fetchedPost, into: managedPost)
|
||||||
managedPost.slug = fetchedPost.slug
|
|
||||||
managedPost.appearance = fetchedPost.appearance
|
|
||||||
managedPost.language = fetchedPost.language
|
|
||||||
managedPost.rtl = fetchedPost.rtl ?? false
|
|
||||||
managedPost.createdDate = fetchedPost.createdDate
|
|
||||||
managedPost.updatedDate = fetchedPost.updatedDate
|
|
||||||
managedPost.title = fetchedPost.title ?? ""
|
|
||||||
managedPost.body = fetchedPost.body
|
|
||||||
managedPost.collectionAlias = fetchedPost.collectionAlias
|
managedPost.collectionAlias = fetchedPost.collectionAlias
|
||||||
managedPost.status = PostStatus.published.rawValue
|
|
||||||
managedPost.wasDeletedFromServer = false
|
managedPost.wasDeletedFromServer = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,16 +184,7 @@ extension WriteFreelyModel {
|
|||||||
let fetchedPost = try result.get()
|
let fetchedPost = try result.get()
|
||||||
// If this is an updated post, check it against postToUpdate.
|
// If this is an updated post, check it against postToUpdate.
|
||||||
if let updatingPost = self.postToUpdate {
|
if let updatingPost = self.postToUpdate {
|
||||||
updatingPost.appearance = fetchedPost.appearance
|
importData(from: fetchedPost, into: updatingPost)
|
||||||
updatingPost.body = fetchedPost.body
|
|
||||||
updatingPost.createdDate = fetchedPost.createdDate
|
|
||||||
updatingPost.language = fetchedPost.language
|
|
||||||
updatingPost.postId = fetchedPost.postId
|
|
||||||
updatingPost.rtl = fetchedPost.rtl ?? false
|
|
||||||
updatingPost.slug = fetchedPost.slug
|
|
||||||
updatingPost.status = PostStatus.published.rawValue
|
|
||||||
updatingPost.title = fetchedPost.title ?? ""
|
|
||||||
updatingPost.updatedDate = fetchedPost.updatedDate
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
LocalStorageManager.standard.saveContext()
|
LocalStorageManager.standard.saveContext()
|
||||||
}
|
}
|
||||||
@ -224,16 +206,7 @@ extension WriteFreelyModel {
|
|||||||
do {
|
do {
|
||||||
let cachedPostsResults = try LocalStorageManager.standard.container.viewContext.fetch(request)
|
let cachedPostsResults = try LocalStorageManager.standard.container.viewContext.fetch(request)
|
||||||
guard let cachedPost = cachedPostsResults.first else { return }
|
guard let cachedPost = cachedPostsResults.first else { return }
|
||||||
cachedPost.appearance = fetchedPost.appearance
|
importData(from: fetchedPost, into: cachedPost)
|
||||||
cachedPost.body = fetchedPost.body
|
|
||||||
cachedPost.createdDate = fetchedPost.createdDate
|
|
||||||
cachedPost.language = fetchedPost.language
|
|
||||||
cachedPost.postId = fetchedPost.postId
|
|
||||||
cachedPost.rtl = fetchedPost.rtl ?? false
|
|
||||||
cachedPost.slug = fetchedPost.slug
|
|
||||||
cachedPost.status = PostStatus.published.rawValue
|
|
||||||
cachedPost.title = fetchedPost.title ?? ""
|
|
||||||
cachedPost.updatedDate = fetchedPost.updatedDate
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
LocalStorageManager.standard.saveContext()
|
LocalStorageManager.standard.saveContext()
|
||||||
}
|
}
|
||||||
@ -258,16 +231,7 @@ extension WriteFreelyModel {
|
|||||||
do {
|
do {
|
||||||
let fetchedPost = try result.get()
|
let fetchedPost = try result.get()
|
||||||
guard let cachedPost = self.selectedPost else { return }
|
guard let cachedPost = self.selectedPost else { return }
|
||||||
cachedPost.appearance = fetchedPost.appearance
|
importData(from: fetchedPost, into: cachedPost)
|
||||||
cachedPost.body = fetchedPost.body
|
|
||||||
cachedPost.createdDate = fetchedPost.createdDate
|
|
||||||
cachedPost.language = fetchedPost.language
|
|
||||||
cachedPost.postId = fetchedPost.postId
|
|
||||||
cachedPost.rtl = fetchedPost.rtl ?? false
|
|
||||||
cachedPost.slug = fetchedPost.slug
|
|
||||||
cachedPost.status = PostStatus.published.rawValue
|
|
||||||
cachedPost.title = fetchedPost.title ?? ""
|
|
||||||
cachedPost.updatedDate = fetchedPost.updatedDate
|
|
||||||
cachedPost.hasNewerRemoteCopy = false
|
cachedPost.hasNewerRemoteCopy = false
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
LocalStorageManager.standard.saveContext()
|
LocalStorageManager.standard.saveContext()
|
||||||
@ -298,4 +262,17 @@ extension WriteFreelyModel {
|
|||||||
print(error)
|
print(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func importData(from fetchedPost: WFPost, into cachedPost: WFAPost) {
|
||||||
|
cachedPost.appearance = fetchedPost.appearance
|
||||||
|
cachedPost.body = fetchedPost.body
|
||||||
|
cachedPost.createdDate = fetchedPost.createdDate
|
||||||
|
cachedPost.language = fetchedPost.language
|
||||||
|
cachedPost.postId = fetchedPost.postId
|
||||||
|
cachedPost.rtl = fetchedPost.rtl ?? false
|
||||||
|
cachedPost.slug = fetchedPost.slug
|
||||||
|
cachedPost.status = PostStatus.published.rawValue
|
||||||
|
cachedPost.title = fetchedPost.title ?? ""
|
||||||
|
cachedPost.updatedDate = fetchedPost.updatedDate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ private extension LocalStorageManager {
|
|||||||
container.persistentStoreDescriptions.first!.url = sharedStoreURL
|
container.persistentStoreDescriptions.first!.url = sharedStoreURL
|
||||||
}
|
}
|
||||||
|
|
||||||
container.loadPersistentStores { description, error in
|
container.loadPersistentStores { _, error in
|
||||||
if let error = error {
|
if let error = error {
|
||||||
fatalError("Core Data store failed to load with error: \(error)")
|
fatalError("Core Data store failed to load with error: \(error)")
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ struct WriteFreely_MultiPlatformApp: App {
|
|||||||
@StateObject private var model = WriteFreelyModel.shared
|
@StateObject private var model = WriteFreelyModel.shared
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
// swiftlint:disable:next weak_delegate
|
|
||||||
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||||
|
@StateObject var updaterViewModel = MacUpdatesViewModel()
|
||||||
@State private var selectedTab = 0
|
@State private var selectedTab = 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -47,13 +47,6 @@ struct WriteFreely_MultiPlatformApp: App {
|
|||||||
showLastDraftOrCreateNewLocalPost()
|
showLastDraftOrCreateNewLocalPost()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
||||||
// if model.editor.lastDraftURL != nil {
|
|
||||||
// self.model.selectedPost = model.editor.fetchLastDraftFromAppStorage()
|
|
||||||
// } else {
|
|
||||||
// createNewLocalPost()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
})
|
})
|
||||||
.environmentObject(model)
|
.environmentObject(model)
|
||||||
.environment(\.managedObjectContext, LocalStorageManager.standard.container.viewContext)
|
.environment(\.managedObjectContext, LocalStorageManager.standard.container.viewContext)
|
||||||
@ -61,11 +54,9 @@ struct WriteFreely_MultiPlatformApp: App {
|
|||||||
}
|
}
|
||||||
.commands {
|
.commands {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
CommandGroup(after: .appInfo, addition: {
|
CommandGroup(after: .appInfo) {
|
||||||
Button("Check For Updates") {
|
CheckForUpdatesView(updaterViewModel: updaterViewModel)
|
||||||
SUUpdater.shared()?.checkForUpdates(self)
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
#endif
|
#endif
|
||||||
CommandGroup(replacing: .newItem, addition: {
|
CommandGroup(replacing: .newItem, addition: {
|
||||||
Button("New Post") {
|
Button("New Post") {
|
||||||
@ -116,7 +107,7 @@ struct WriteFreely_MultiPlatformApp: App {
|
|||||||
Text("Preferences")
|
Text("Preferences")
|
||||||
}
|
}
|
||||||
.tag(1)
|
.tag(1)
|
||||||
MacUpdatesView()
|
MacUpdatesView(updaterViewModel: updaterViewModel)
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Image(systemName: "arrow.down.circle")
|
Image(systemName: "arrow.down.circle")
|
||||||
Text("Updates")
|
Text("Updates")
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
17120DAC24E1B99F002B9F6C /* AccountLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17120DAB24E1B99F002B9F6C /* AccountLoginView.swift */; };
|
17120DAC24E1B99F002B9F6C /* AccountLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17120DAB24E1B99F002B9F6C /* AccountLoginView.swift */; };
|
||||||
17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17120DAB24E1B99F002B9F6C /* AccountLoginView.swift */; };
|
17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17120DAB24E1B99F002B9F6C /* AccountLoginView.swift */; };
|
||||||
17120DB224E1E19C002B9F6C /* SettingsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17120DB124E1E19C002B9F6C /* SettingsHeaderView.swift */; };
|
17120DB224E1E19C002B9F6C /* SettingsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17120DB124E1E19C002B9F6C /* SettingsHeaderView.swift */; };
|
||||||
1714DD65260BAC14000C0DFF /* WriteFreely in Frameworks */ = {isa = PBXBuildFile; productRef = 1714DD64260BAC14000C0DFF /* WriteFreely */; };
|
|
||||||
1714DD6B260BAC2C000C0DFF /* WriteFreely in Frameworks */ = {isa = PBXBuildFile; productRef = 1714DD6A260BAC2C000C0DFF /* WriteFreely */; };
|
|
||||||
171BFDFA24D4AF8300888236 /* CollectionListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171BFDF924D4AF8300888236 /* CollectionListView.swift */; };
|
171BFDFA24D4AF8300888236 /* CollectionListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171BFDF924D4AF8300888236 /* CollectionListView.swift */; };
|
||||||
171BFDFB24D4AF8300888236 /* CollectionListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171BFDF924D4AF8300888236 /* CollectionListView.swift */; };
|
171BFDFB24D4AF8300888236 /* CollectionListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171BFDF924D4AF8300888236 /* CollectionListView.swift */; };
|
||||||
171DC677272C7D0B002B9B8A /* UserDefaults+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171DC676272C7D0B002B9B8A /* UserDefaults+Extensions.swift */; };
|
171DC677272C7D0B002B9B8A /* UserDefaults+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171DC676272C7D0B002B9B8A /* UserDefaults+Extensions.swift */; };
|
||||||
@ -35,7 +33,6 @@
|
|||||||
172E10152735C2BD00061372 /* UIHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10142735C2BD00061372 /* UIHostingView.swift */; };
|
172E10152735C2BD00061372 /* UIHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10142735C2BD00061372 /* UIHostingView.swift */; };
|
||||||
172E10172735C2DF00061372 /* EnvironmentValues+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10162735C2DF00061372 /* EnvironmentValues+Extensions.swift */; };
|
172E10172735C2DF00061372 /* EnvironmentValues+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10162735C2DF00061372 /* EnvironmentValues+Extensions.swift */; };
|
||||||
172E10192735C3DB00061372 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10182735C3DB00061372 /* ContentView.swift */; };
|
172E10192735C3DB00061372 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10182735C3DB00061372 /* ContentView.swift */; };
|
||||||
172E101B2735C54400061372 /* WriteFreely in Frameworks */ = {isa = PBXBuildFile; productRef = 172E101A2735C54400061372 /* WriteFreely */; };
|
|
||||||
172E101C2735C57400061372 /* LocalStorageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1756DBB924FED45500207AB8 /* LocalStorageManager.swift */; };
|
172E101C2735C57400061372 /* LocalStorageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1756DBB924FED45500207AB8 /* LocalStorageManager.swift */; };
|
||||||
172E101D2735C5AB00061372 /* LocalStorageModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1756DBB524FED3A400207AB8 /* LocalStorageModel.xcdatamodeld */; };
|
172E101D2735C5AB00061372 /* LocalStorageModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1756DBB524FED3A400207AB8 /* LocalStorageModel.xcdatamodeld */; };
|
||||||
172E101E2735C62F00061372 /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E612507D8E600072984 /* PostStatus.swift */; };
|
172E101E2735C62F00061372 /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E612507D8E600072984 /* PostStatus.swift */; };
|
||||||
@ -78,7 +75,9 @@
|
|||||||
17836C15273F0FBB0047AF61 /* Hack-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F3A42514F1E900517CE6 /* Hack-Regular.ttf */; };
|
17836C15273F0FBB0047AF61 /* Hack-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F3A42514F1E900517CE6 /* Hack-Regular.ttf */; };
|
||||||
17836C16273F0FBB0047AF61 /* LoraGX.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */; };
|
17836C16273F0FBB0047AF61 /* LoraGX.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */; };
|
||||||
17836C17273F0FBB0047AF61 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F39D2514F0E500517CE6 /* OpenSans-Regular.ttf */; };
|
17836C17273F0FBB0047AF61 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F39D2514F0E500517CE6 /* OpenSans-Regular.ttf */; };
|
||||||
17A4FEDA25924AF70037E96B /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 17A4FED925924AF70037E96B /* Sparkle */; };
|
1784D2ED27946D880033E72E /* WriteFreely in Frameworks */ = {isa = PBXBuildFile; productRef = 1784D2EC27946D880033E72E /* WriteFreely */; };
|
||||||
|
1784D2EF27946D9A0033E72E /* WriteFreely in Frameworks */ = {isa = PBXBuildFile; productRef = 1784D2EE27946D9A0033E72E /* WriteFreely */; };
|
||||||
|
1784D2F127946DA10033E72E /* WriteFreely in Frameworks */ = {isa = PBXBuildFile; productRef = 1784D2F027946DA10033E72E /* WriteFreely */; };
|
||||||
17A4FEED25927E730037E96B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A4FEEC25927E730037E96B /* AppDelegate.swift */; };
|
17A4FEED25927E730037E96B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A4FEEC25927E730037E96B /* AppDelegate.swift */; };
|
||||||
17A5388824DDA31F00DEFF9A /* MacAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A5388724DDA31F00DEFF9A /* MacAccountView.swift */; };
|
17A5388824DDA31F00DEFF9A /* MacAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A5388724DDA31F00DEFF9A /* MacAccountView.swift */; };
|
||||||
17A5388C24DDC83F00DEFF9A /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A5388B24DDC83F00DEFF9A /* AccountModel.swift */; };
|
17A5388C24DDC83F00DEFF9A /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A5388B24DDC83F00DEFF9A /* AccountModel.swift */; };
|
||||||
@ -108,6 +107,8 @@
|
|||||||
17C42E71250AAFD500072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */; };
|
17C42E71250AAFD500072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */; };
|
||||||
17D435E824E3128F0036B539 /* PreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D435E724E3128F0036B539 /* PreferencesModel.swift */; };
|
17D435E824E3128F0036B539 /* PreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D435E724E3128F0036B539 /* PreferencesModel.swift */; };
|
||||||
17D435E924E3128F0036B539 /* PreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D435E724E3128F0036B539 /* PreferencesModel.swift */; };
|
17D435E924E3128F0036B539 /* PreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D435E724E3128F0036B539 /* PreferencesModel.swift */; };
|
||||||
|
17D4926527947B4D0035BD7E /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 17D4926427947B4D0035BD7E /* Sparkle */; };
|
||||||
|
17D4926727947D780035BD7E /* MacUpdatesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4926627947D780035BD7E /* MacUpdatesViewModel.swift */; };
|
||||||
17D4F36C2514EE2F00517CE6 /* LoraGX.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */; };
|
17D4F36C2514EE2F00517CE6 /* LoraGX.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */; };
|
||||||
17D4F36D2514EE2F00517CE6 /* LoraGX.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */; };
|
17D4F36D2514EE2F00517CE6 /* LoraGX.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */; };
|
||||||
17D4F39E2514F0E500517CE6 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F39D2514F0E500517CE6 /* OpenSans-Regular.ttf */; };
|
17D4F39E2514F0E500517CE6 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F39D2514F0E500517CE6 /* OpenSans-Regular.ttf */; };
|
||||||
@ -234,6 +235,7 @@
|
|||||||
17C42E642509237800072984 /* PostListFilteredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostListFilteredView.swift; sourceTree = "<group>"; };
|
17C42E642509237800072984 /* PostListFilteredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostListFilteredView.swift; sourceTree = "<group>"; };
|
||||||
17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+ExecuteAndMergeChanges.swift"; sourceTree = "<group>"; };
|
17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+ExecuteAndMergeChanges.swift"; sourceTree = "<group>"; };
|
||||||
17D435E724E3128F0036B539 /* PreferencesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesModel.swift; sourceTree = "<group>"; };
|
17D435E724E3128F0036B539 /* PreferencesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesModel.swift; sourceTree = "<group>"; };
|
||||||
|
17D4926627947D780035BD7E /* MacUpdatesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacUpdatesViewModel.swift; sourceTree = "<group>"; };
|
||||||
17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = LoraGX.ttf; sourceTree = "<group>"; };
|
17D4F36B2514EE2F00517CE6 /* LoraGX.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = LoraGX.ttf; sourceTree = "<group>"; };
|
||||||
17D4F39D2514F0E500517CE6 /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-Regular.ttf"; sourceTree = "<group>"; };
|
17D4F39D2514F0E500517CE6 /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-Regular.ttf"; sourceTree = "<group>"; };
|
||||||
17D4F3A42514F1E900517CE6 /* Hack-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Hack-Regular.ttf"; sourceTree = "<group>"; };
|
17D4F3A42514F1E900517CE6 /* Hack-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Hack-Regular.ttf"; sourceTree = "<group>"; };
|
||||||
@ -269,7 +271,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
172E10012735B83E00061372 /* UniformTypeIdentifiers.framework in Frameworks */,
|
172E10012735B83E00061372 /* UniformTypeIdentifiers.framework in Frameworks */,
|
||||||
172E101B2735C54400061372 /* WriteFreely in Frameworks */,
|
1784D2F127946DA10033E72E /* WriteFreely in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -277,7 +279,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
1714DD65260BAC14000C0DFF /* WriteFreely in Frameworks */,
|
1784D2ED27946D880033E72E /* WriteFreely in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -285,8 +287,8 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
17A4FEDA25924AF70037E96B /* Sparkle in Frameworks */,
|
1784D2EF27946D9A0033E72E /* WriteFreely in Frameworks */,
|
||||||
1714DD6B260BAC2C000C0DFF /* WriteFreely in Frameworks */,
|
17D4926527947B4D0035BD7E /* Sparkle in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -400,6 +402,7 @@
|
|||||||
17A5388724DDA31F00DEFF9A /* MacAccountView.swift */,
|
17A5388724DDA31F00DEFF9A /* MacAccountView.swift */,
|
||||||
1753F6AB24E431CC00309365 /* MacPreferencesView.swift */,
|
1753F6AB24E431CC00309365 /* MacPreferencesView.swift */,
|
||||||
172C492D2593981900E20ADF /* MacUpdatesView.swift */,
|
172C492D2593981900E20ADF /* MacUpdatesView.swift */,
|
||||||
|
17D4926627947D780035BD7E /* MacUpdatesViewModel.swift */,
|
||||||
);
|
);
|
||||||
path = Settings;
|
path = Settings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -619,7 +622,7 @@
|
|||||||
);
|
);
|
||||||
name = "ActionExtension-iOS";
|
name = "ActionExtension-iOS";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
172E101A2735C54400061372 /* WriteFreely */,
|
1784D2F027946DA10033E72E /* WriteFreely */,
|
||||||
);
|
);
|
||||||
productName = "ActionExtension-iOS";
|
productName = "ActionExtension-iOS";
|
||||||
productReference = 172E0FFF2735B83E00061372 /* ActionExtension-iOS.appex */;
|
productReference = 172E0FFF2735B83E00061372 /* ActionExtension-iOS.appex */;
|
||||||
@ -642,7 +645,7 @@
|
|||||||
);
|
);
|
||||||
name = "WriteFreely-MultiPlatform (iOS)";
|
name = "WriteFreely-MultiPlatform (iOS)";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
1714DD64260BAC14000C0DFF /* WriteFreely */,
|
1784D2EC27946D880033E72E /* WriteFreely */,
|
||||||
);
|
);
|
||||||
productName = "WriteFreely-MultiPlatform (iOS)";
|
productName = "WriteFreely-MultiPlatform (iOS)";
|
||||||
productReference = 17DF328824C87D3500BCE2E3 /* WriteFreely-MultiPlatform.app */;
|
productReference = 17DF328824C87D3500BCE2E3 /* WriteFreely-MultiPlatform.app */;
|
||||||
@ -663,8 +666,8 @@
|
|||||||
);
|
);
|
||||||
name = "WriteFreely-MultiPlatform (macOS)";
|
name = "WriteFreely-MultiPlatform (macOS)";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
17A4FED925924AF70037E96B /* Sparkle */,
|
1784D2EE27946D9A0033E72E /* WriteFreely */,
|
||||||
1714DD6A260BAC2C000C0DFF /* WriteFreely */,
|
17D4926427947B4D0035BD7E /* Sparkle */,
|
||||||
);
|
);
|
||||||
productName = "WriteFreely-MultiPlatform (macOS)";
|
productName = "WriteFreely-MultiPlatform (macOS)";
|
||||||
productReference = 17DF329024C87D3500BCE2E3 /* WriteFreely for Mac.app */;
|
productReference = 17DF329024C87D3500BCE2E3 /* WriteFreely for Mac.app */;
|
||||||
@ -713,7 +716,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 1310;
|
LastSwiftUpdateCheck = 1310;
|
||||||
LastUpgradeCheck = 1200;
|
LastUpgradeCheck = 1320;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
172E0FFE2735B83E00061372 = {
|
172E0FFE2735B83E00061372 = {
|
||||||
CreatedOnToolsVersion = 13.1;
|
CreatedOnToolsVersion = 13.1;
|
||||||
@ -744,8 +747,8 @@
|
|||||||
);
|
);
|
||||||
mainGroup = 17DF327B24C87D3300BCE2E3;
|
mainGroup = 17DF327B24C87D3300BCE2E3;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
17A4FED825924AF70037E96B /* XCRemoteSwiftPackageReference "Sparkle" */,
|
1784D2EB27946D880033E72E /* XCRemoteSwiftPackageReference "writefreely-swift" */,
|
||||||
1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */,
|
17D4926327947B4D0035BD7E /* XCRemoteSwiftPackageReference "Sparkle" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 17DF328924C87D3500BCE2E3 /* Products */;
|
productRefGroup = 17DF328924C87D3500BCE2E3 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@ -942,6 +945,7 @@
|
|||||||
17480CA6251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */,
|
17480CA6251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */,
|
||||||
17C42E662509237800072984 /* PostListFilteredView.swift in Sources */,
|
17C42E662509237800072984 /* PostListFilteredView.swift in Sources */,
|
||||||
17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */,
|
17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */,
|
||||||
|
17D4926727947D780035BD7E /* MacUpdatesViewModel.swift in Sources */,
|
||||||
17466626256C0D0600629997 /* MacEditorTextView.swift in Sources */,
|
17466626256C0D0600629997 /* MacEditorTextView.swift in Sources */,
|
||||||
170A7EC226F5186A00F1CBD4 /* CollectionListModel.swift in Sources */,
|
170A7EC226F5186A00F1CBD4 /* CollectionListModel.swift in Sources */,
|
||||||
17E5DF8A2543610700DCDC9B /* PostTextEditingView.swift in Sources */,
|
17E5DF8A2543610700DCDC9B /* PostTextEditingView.swift in Sources */,
|
||||||
@ -1243,6 +1247,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
|
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 620;
|
CURRENT_PROJECT_VERSION = 620;
|
||||||
@ -1269,6 +1274,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
|
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 620;
|
CURRENT_PROJECT_VERSION = 620;
|
||||||
@ -1438,43 +1444,43 @@
|
|||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */ = {
|
1784D2EB27946D880033E72E /* XCRemoteSwiftPackageReference "writefreely-swift" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "git@github.com:writefreely/writefreely-swift.git";
|
repositoryURL = "https://github.com/writefreely/writefreely-swift";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
kind = upToNextMajorVersion;
|
||||||
minimumVersion = 0.3.2;
|
minimumVersion = 0.3.4;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
17A4FED825924AF70037E96B /* XCRemoteSwiftPackageReference "Sparkle" */ = {
|
17D4926327947B4D0035BD7E /* XCRemoteSwiftPackageReference "Sparkle" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/writefreely/Sparkle";
|
repositoryURL = "https://github.com/sparkle-project/Sparkle";
|
||||||
requirement = {
|
requirement = {
|
||||||
branch = master;
|
kind = upToNextMinorVersion;
|
||||||
kind = branch;
|
minimumVersion = 2.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
1714DD64260BAC14000C0DFF /* WriteFreely */ = {
|
1784D2EC27946D880033E72E /* WriteFreely */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
package = 1784D2EB27946D880033E72E /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
||||||
productName = WriteFreely;
|
productName = WriteFreely;
|
||||||
};
|
};
|
||||||
1714DD6A260BAC2C000C0DFF /* WriteFreely */ = {
|
1784D2EE27946D9A0033E72E /* WriteFreely */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
package = 1784D2EB27946D880033E72E /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
||||||
productName = WriteFreely;
|
productName = WriteFreely;
|
||||||
};
|
};
|
||||||
172E101A2735C54400061372 /* WriteFreely */ = {
|
1784D2F027946DA10033E72E /* WriteFreely */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
package = 1784D2EB27946D880033E72E /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
||||||
productName = WriteFreely;
|
productName = WriteFreely;
|
||||||
};
|
};
|
||||||
17A4FED925924AF70037E96B /* Sparkle */ = {
|
17D4926427947B4D0035BD7E /* Sparkle */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 17A4FED825924AF70037E96B /* XCRemoteSwiftPackageReference "Sparkle" */;
|
package = 17D4926327947B4D0035BD7E /* XCRemoteSwiftPackageReference "Sparkle" */;
|
||||||
productName = Sparkle;
|
productName = Sparkle;
|
||||||
};
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
|
@ -7,17 +7,17 @@
|
|||||||
<key>ActionExtension-iOS.xcscheme_^#shared#^_</key>
|
<key>ActionExtension-iOS.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>0</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>WriteFreely-MultiPlatform (iOS).xcscheme_^#shared#^_</key>
|
<key>WriteFreely-MultiPlatform (iOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>1</integer>
|
<integer>2</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>WriteFreely-MultiPlatform (macOS).xcscheme_^#shared#^_</key>
|
<key>WriteFreely-MultiPlatform (macOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>2</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
@ -3,26 +3,6 @@ import Sparkle
|
|||||||
|
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
func applicationWillFinishLaunching(_ notification: Notification) {
|
|
||||||
// Check UserDefaults for values; if the key doesn't exist (e.g., if MacUpdatesView hasn't ever been shown),
|
|
||||||
// bool(forKey:) returns false, so set SUUpdater.shared() appropriately.
|
|
||||||
let automaticallyChecksForUpdates = UserDefaults.shared.bool(forKey: WFDefaults.automaticallyChecksForUpdates)
|
|
||||||
let subscribeToBetaUpdates = UserDefaults.shared.bool(forKey: WFDefaults.subscribeToBetaUpdates)
|
|
||||||
|
|
||||||
// Set Sparkle properties.
|
|
||||||
SUUpdater.shared()?.automaticallyChecksForUpdates = automaticallyChecksForUpdates
|
|
||||||
if subscribeToBetaUpdates {
|
|
||||||
SUUpdater.shared()?.feedURL = URL(string: AppcastFeedUrl.beta.rawValue)
|
|
||||||
} else {
|
|
||||||
SUUpdater.shared()?.feedURL = URL(string: AppcastFeedUrl.release.rawValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If enabled, check for updates.
|
|
||||||
if automaticallyChecksForUpdates {
|
|
||||||
SUUpdater.shared()?.checkForUpdatesInBackground()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Window handling when miniaturized into app icon on the Dock
|
// MARK: - Window handling when miniaturized into app icon on the Dock
|
||||||
// Credit to Henry Cooper (pillboxer) on GitHub:
|
// Credit to Henry Cooper (pillboxer) on GitHub:
|
||||||
// https://github.com/tact/beta-bugs/issues/31#issuecomment-855914705
|
// https://github.com/tact/beta-bugs/issues/31#issuecomment-855914705
|
||||||
@ -30,7 +10,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
// If the window is currently minimized into the Dock, de-miniaturize it (note that if it's minimized
|
// If the window is currently minimized into the Dock, de-miniaturize it (note that if it's minimized
|
||||||
// and the user uses OPT+TAB to switch to it, it will be de-miniaturized and brought to the foreground).
|
// and the user uses OPT+TAB to switch to it, it will be de-miniaturized and brought to the foreground).
|
||||||
func applicationDidBecomeActive(_ notification: Notification) {
|
func applicationDidBecomeActive(_ notification: Notification) {
|
||||||
print("💬 Fired:", #function)
|
|
||||||
if let window = NSApp.windows.first {
|
if let window = NSApp.windows.first {
|
||||||
window.deminiaturize(nil)
|
window.deminiaturize(nil)
|
||||||
}
|
}
|
||||||
@ -39,7 +18,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
// If we're miniaturizing the window, deactivate it as well by activating Finder.app (note that
|
// If we're miniaturizing the window, deactivate it as well by activating Finder.app (note that
|
||||||
// this will bring any Finder windows that are behind other apps to the foreground).
|
// this will bring any Finder windows that are behind other apps to the foreground).
|
||||||
func applicationDidChangeOcclusionState(_ notification: Notification) {
|
func applicationDidChangeOcclusionState(_ notification: Notification) {
|
||||||
print("💬 Fired:", #function)
|
|
||||||
if let window = NSApp.windows.first, window.isMiniaturized {
|
if let window = NSApp.windows.first, window.isMiniaturized {
|
||||||
NSWorkspace.shared.runningApplications.first(where: {
|
NSWorkspace.shared.runningApplications.first(where: {
|
||||||
$0.activationPolicy == .regular
|
$0.activationPolicy == .regular
|
||||||
@ -49,7 +27,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
|
|
||||||
lazy var windows = NSWindow()
|
lazy var windows = NSWindow()
|
||||||
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||||||
print("💬 Fired:", #function)
|
|
||||||
if !flag {
|
if !flag {
|
||||||
for window in sender.windows {
|
for window in sender.windows {
|
||||||
window.makeKeyAndOrderFront(self)
|
window.makeKeyAndOrderFront(self)
|
||||||
|
@ -163,8 +163,8 @@ final class CustomTextView: NSView {
|
|||||||
textView.isAutomaticDashSubstitutionEnabled = false
|
textView.isAutomaticDashSubstitutionEnabled = false
|
||||||
textView.isRichText = false
|
textView.isRichText = false
|
||||||
textView.typingAttributes = [
|
textView.typingAttributes = [
|
||||||
.paragraphStyle: paragraphStyle, // H/T Daniel Jalkut
|
.paragraphStyle: paragraphStyle, // H/T Daniel Jalkut
|
||||||
.font: font,
|
.font: font ?? NSFont.systemFont(ofSize: 17), // Fall back to system font if we can't unwrap font argument
|
||||||
.foregroundColor: NSColor.labelColor
|
.foregroundColor: NSColor.labelColor
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Sparkle
|
import Sparkle
|
||||||
|
|
||||||
enum AppcastFeedUrl: String {
|
|
||||||
case release = "https://writefreely-files.s3.amazonaws.com/apps/mac/appcast.xml"
|
|
||||||
case beta = "https://writefreely-files.s3.amazonaws.com/apps/mac/appcast-beta.xml"
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MacUpdatesView: View {
|
struct MacUpdatesView: View {
|
||||||
|
@ObservedObject var updaterViewModel: MacUpdatesViewModel
|
||||||
|
|
||||||
@AppStorage(WFDefaults.automaticallyChecksForUpdates, store: UserDefaults.shared)
|
@AppStorage(WFDefaults.automaticallyChecksForUpdates, store: UserDefaults.shared)
|
||||||
var automaticallyChecksForUpdates: Bool = false
|
var automaticallyChecksForUpdates: Bool = false
|
||||||
@AppStorage(WFDefaults.subscribeToBetaUpdates, store: UserDefaults.shared)
|
@AppStorage(WFDefaults.subscribeToBetaUpdates, store: UserDefaults.shared)
|
||||||
var subscribeToBetaUpdates: Bool = false
|
var subscribeToBetaUpdates: Bool = false
|
||||||
|
|
||||||
@State private var lastUpdateCheck: Date?
|
@State private var lastUpdateCheck: Date?
|
||||||
|
|
||||||
private let betaWarningString = """
|
private let betaWarningString = """
|
||||||
@ -34,9 +32,11 @@ that can cause crashes and data loss.
|
|||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
SUUpdater.shared()?.checkForUpdates(self)
|
updaterViewModel.checkForUpdates()
|
||||||
DispatchQueue.main.async {
|
// There's a delay between requesting an update, and the timestamp for that update request being
|
||||||
lastUpdateCheck = SUUpdater.shared()?.lastUpdateCheckDate
|
// written to user defaults; we therefore delay updating the "Last checked" UI for one second.
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
|
lastUpdateCheck = updaterViewModel.getLastUpdateCheckDate()
|
||||||
}
|
}
|
||||||
}, label: {
|
}, label: {
|
||||||
Text("Check For Updates")
|
Text("Check For Updates")
|
||||||
@ -73,23 +73,19 @@ that can cause crashes and data loss.
|
|||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.onAppear {
|
.onAppear {
|
||||||
lastUpdateCheck = SUUpdater.shared()?.lastUpdateCheckDate
|
lastUpdateCheck = updaterViewModel.getLastUpdateCheckDate()
|
||||||
}
|
}
|
||||||
.onChange(of: automaticallyChecksForUpdates) { value in
|
.onChange(of: automaticallyChecksForUpdates) { value in
|
||||||
SUUpdater.shared()?.automaticallyChecksForUpdates = value
|
updaterViewModel.automaticallyCheckForUpdates = value
|
||||||
}
|
}
|
||||||
.onChange(of: subscribeToBetaUpdates) { value in
|
.onChange(of: subscribeToBetaUpdates) { _ in
|
||||||
if value {
|
updaterViewModel.toggleAllowedChannels()
|
||||||
SUUpdater.shared()?.feedURL = URL(string: AppcastFeedUrl.beta.rawValue)
|
|
||||||
} else {
|
|
||||||
SUUpdater.shared()?.feedURL = URL(string: AppcastFeedUrl.release.rawValue)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MacUpdatesView_Previews: PreviewProvider {
|
struct MacUpdatesView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
MacUpdatesView()
|
MacUpdatesView(updaterViewModel: MacUpdatesViewModel())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
73
macOS/Settings/MacUpdatesViewModel.swift
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/// See https://sparkle-project.org/documentation/programmatic-setup#create-an-updater-in-swiftui
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Sparkle
|
||||||
|
|
||||||
|
/// This view model class manages Sparkle's updater and publishes when new updates are allowed to be checked.
|
||||||
|
final class MacUpdatesViewModel: ObservableObject {
|
||||||
|
|
||||||
|
@Published var canCheckForUpdates = false
|
||||||
|
private let updaterController: SPUStandardUpdaterController
|
||||||
|
private let updaterDelegate = MacUpdatesViewModelDelegate()
|
||||||
|
|
||||||
|
var automaticallyCheckForUpdates: Bool {
|
||||||
|
get {
|
||||||
|
return updaterController.updater.automaticallyChecksForUpdates
|
||||||
|
}
|
||||||
|
set(newValue) {
|
||||||
|
updaterController.updater.automaticallyChecksForUpdates = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
updaterController = SPUStandardUpdaterController(startingUpdater: true,
|
||||||
|
updaterDelegate: updaterDelegate,
|
||||||
|
userDriverDelegate: nil)
|
||||||
|
|
||||||
|
updaterController.updater.publisher(for: \.canCheckForUpdates)
|
||||||
|
.assign(to: &$canCheckForUpdates)
|
||||||
|
|
||||||
|
if automaticallyCheckForUpdates {
|
||||||
|
updaterController.updater.checkForUpdatesInBackground()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkForUpdates() {
|
||||||
|
updaterController.checkForUpdates(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLastUpdateCheckDate() -> Date? {
|
||||||
|
return updaterController.updater.lastUpdateCheckDate
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
func toggleAllowedChannels() -> Set<String> {
|
||||||
|
return updaterDelegate.allowedChannels(for: updaterController.updater)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final class MacUpdatesViewModelDelegate: NSObject, SPUUpdaterDelegate {
|
||||||
|
|
||||||
|
@AppStorage(WFDefaults.subscribeToBetaUpdates, store: UserDefaults.shared)
|
||||||
|
var subscribeToBetaUpdates: Bool = false
|
||||||
|
|
||||||
|
func allowedChannels(for updater: SPUUpdater) -> Set<String> {
|
||||||
|
let allowedChannels = Set(subscribeToBetaUpdates ? ["beta"] : [])
|
||||||
|
return allowedChannels
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// This additional view is needed for the disabled state on the menu item to work properly before Monterey.
|
||||||
|
// See https://stackoverflow.com/questions/68553092/menu-not-updating-swiftui-bug for more information
|
||||||
|
struct CheckForUpdatesView: View {
|
||||||
|
|
||||||
|
@ObservedObject var updaterViewModel: MacUpdatesViewModel
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button("Check for Updates…", action: updaterViewModel.checkForUpdates)
|
||||||
|
.disabled(!updaterViewModel.canCheckForUpdates)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|