mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
Add action extension
This commit is contained in:
parent
2dccaf7196
commit
3752b85414
@ -11,7 +11,8 @@ run: function(parameters) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
finalize: function(parameters) {
|
finalize: function(parameters) {
|
||||||
|
var customJavaScript = parameters["customJavaScript"];
|
||||||
|
eval(customJavaScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
10
ActionExtension-iOS/ActionExtension-iOS.entitlements
Normal file
10
ActionExtension-iOS/ActionExtension-iOS.entitlements
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.com.abunchtell.writefreely</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -1,30 +1,21 @@
|
|||||||
import UIKit
|
import SwiftUI
|
||||||
import MobileCoreServices
|
|
||||||
import UniformTypeIdentifiers
|
|
||||||
|
|
||||||
class ActionViewController: UIViewController {
|
class ActionViewController: UIViewController {
|
||||||
|
|
||||||
@IBOutlet weak var imageView: UIImageView!
|
let moc = LocalStorageManager.standard.container.viewContext
|
||||||
|
|
||||||
|
override var prefersStatusBarHidden: Bool { true }
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
// Get the item[s] we're handling from the extension context.
|
let contentView = ContentView()
|
||||||
if let inputItem = extensionContext?.inputItems.first as? NSExtensionItem {
|
.environment(\.extensionContext, extensionContext)
|
||||||
if let itemProvider = inputItem.attachments?.first {
|
.environment(\.managedObjectContext, moc)
|
||||||
itemProvider.loadItem(forTypeIdentifier: kUTTypePropertyList as String) { [weak self] dict, error in
|
|
||||||
guard let itemDictionary = dict as? NSDictionary else { return }
|
|
||||||
guard let javaScriptValues = itemDictionary[NSExtensionJavaScriptPreprocessingResultsKey] as? NSDictionary else { return }
|
|
||||||
print(javaScriptValues)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@IBAction func done() {
|
view = UIHostingView(rootView: contentView)
|
||||||
// Return any edited content to the host app.
|
view.isOpaque = true
|
||||||
// This template doesn't do anything, so we just echo the passed in items.
|
view.backgroundColor = .systemBackground
|
||||||
self.extensionContext!.completeRequest(returningItems: self.extensionContext!.inputItems, completionHandler: nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ObA-dk-sSI">
|
|
||||||
<dependencies>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
|
||||||
<scenes>
|
|
||||||
<!--Image-->
|
|
||||||
<scene sceneID="7MM-of-jgj">
|
|
||||||
<objects>
|
|
||||||
<viewController title="Image" id="ObA-dk-sSI" customClass="ActionViewController" customModuleProvider="target" sceneMemberID="viewController">
|
|
||||||
<view key="view" contentMode="scaleToFill" id="zMn-AG-sqS">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="528"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<navigationBar contentMode="scaleToFill" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" translatesAutoresizingMaskIntoConstraints="NO" id="NOA-Dm-cuz">
|
|
||||||
<items>
|
|
||||||
<navigationItem id="3HJ-uW-3hn">
|
|
||||||
<barButtonItem key="leftBarButtonItem" title="Done" style="done" id="WYi-yp-eM6">
|
|
||||||
<connections>
|
|
||||||
<action selector="done" destination="ObA-dk-sSI" id="Qdu-qn-U6V"/>
|
|
||||||
</connections>
|
|
||||||
</barButtonItem>
|
|
||||||
</navigationItem>
|
|
||||||
</items>
|
|
||||||
</navigationBar>
|
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="9ga-4F-77Z"/>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="VVe-Uw-JpX" firstAttribute="trailing" secondItem="NOA-Dm-cuz" secondAttribute="trailing" id="A05-Pj-hrr"/>
|
|
||||||
<constraint firstItem="9ga-4F-77Z" firstAttribute="top" secondItem="NOA-Dm-cuz" secondAttribute="bottom" id="Fps-3D-QQW"/>
|
|
||||||
<constraint firstItem="NOA-Dm-cuz" firstAttribute="leading" secondItem="VVe-Uw-JpX" secondAttribute="leading" id="HxO-8t-aoh"/>
|
|
||||||
<constraint firstItem="VVe-Uw-JpX" firstAttribute="trailing" secondItem="9ga-4F-77Z" secondAttribute="trailing" id="Ozw-Hg-0yh"/>
|
|
||||||
<constraint firstItem="9ga-4F-77Z" firstAttribute="leading" secondItem="VVe-Uw-JpX" secondAttribute="leading" id="XH5-ld-ONA"/>
|
|
||||||
<constraint firstItem="VVe-Uw-JpX" firstAttribute="bottom" secondItem="9ga-4F-77Z" secondAttribute="bottom" id="eQg-nn-Zy4"/>
|
|
||||||
<constraint firstItem="NOA-Dm-cuz" firstAttribute="top" secondItem="VVe-Uw-JpX" secondAttribute="top" id="we0-1t-bgp"/>
|
|
||||||
</constraints>
|
|
||||||
<viewLayoutGuide key="safeArea" id="VVe-Uw-JpX"/>
|
|
||||||
</view>
|
|
||||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
|
||||||
<size key="freeformSize" width="320" height="528"/>
|
|
||||||
<connections>
|
|
||||||
<outlet property="imageView" destination="9ga-4F-77Z" id="5y6-5w-9QO"/>
|
|
||||||
<outlet property="view" destination="zMn-AG-sqS" id="Qma-de-2ek"/>
|
|
||||||
</connections>
|
|
||||||
</viewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="X47-rx-isc" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
</scene>
|
|
||||||
</scenes>
|
|
||||||
</document>
|
|
198
ActionExtension-iOS/ContentView.swift
Normal file
198
ActionExtension-iOS/ContentView.swift
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import SwiftUI
|
||||||
|
import MobileCoreServices
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
import WriteFreely
|
||||||
|
|
||||||
|
enum WFActionExtensionError: Error {
|
||||||
|
case userCancelledRequest
|
||||||
|
case couldNotParseInputItems
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ContentView: View {
|
||||||
|
@Environment(\.extensionContext) private var extensionContext: NSExtensionContext!
|
||||||
|
@Environment(\.managedObjectContext) private var managedObjectContext
|
||||||
|
|
||||||
|
@AppStorage(WFDefaults.defaultFontIntegerKey, store: UserDefaults.shared) var fontIndex: Int = 0
|
||||||
|
|
||||||
|
@FetchRequest(
|
||||||
|
entity: WFACollection.entity(),
|
||||||
|
sortDescriptors: [NSSortDescriptor(keyPath: \WFACollection.title, ascending: true)]
|
||||||
|
) var collections: FetchedResults<WFACollection>
|
||||||
|
|
||||||
|
@State private var draftTitle: String = ""
|
||||||
|
@State private var draftText: String = ""
|
||||||
|
@State private var isShowingAlert: Bool = false
|
||||||
|
@State private var selectedBlog: WFACollection?
|
||||||
|
|
||||||
|
private var draftsCollectionName: String {
|
||||||
|
guard UserDefaults.shared.string(forKey: WFDefaults.serverStringKey) == "https://write.as" else {
|
||||||
|
return "Drafts"
|
||||||
|
}
|
||||||
|
return "Anonymous"
|
||||||
|
}
|
||||||
|
|
||||||
|
private var controls: some View {
|
||||||
|
HStack {
|
||||||
|
Group {
|
||||||
|
Button(
|
||||||
|
action: { extensionContext.cancelRequest(withError: WFActionExtensionError.userCancelledRequest) },
|
||||||
|
label: { Image(systemName: "xmark.circle").imageScale(.large) }
|
||||||
|
)
|
||||||
|
.accessibilityLabel(Text("Cancel"))
|
||||||
|
Spacer()
|
||||||
|
Button(
|
||||||
|
action: {
|
||||||
|
savePostToCollection(collection: selectedBlog, title: draftTitle, body: draftText)
|
||||||
|
extensionContext.completeRequest(returningItems: nil, completionHandler: nil)
|
||||||
|
},
|
||||||
|
label: { Image(systemName: "square.and.arrow.down").imageScale(.large) }
|
||||||
|
)
|
||||||
|
.accessibilityLabel(Text("Create new draft"))
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
controls
|
||||||
|
Form {
|
||||||
|
Section(header: Text("Title")) {
|
||||||
|
switch fontIndex {
|
||||||
|
case 1:
|
||||||
|
TextField("Draft Title", text: $draftTitle).font(.custom("OpenSans-Regular", size: 26))
|
||||||
|
case 2:
|
||||||
|
TextField("Draft Title", text: $draftTitle).font(.custom("Hack-Regular", size: 26))
|
||||||
|
default:
|
||||||
|
TextField("Draft Title", text: $draftTitle).font(.custom("Lora", size: 26))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Section(header: Text("Content")) {
|
||||||
|
switch fontIndex {
|
||||||
|
case 1:
|
||||||
|
TextEditor(text: $draftText).font(.custom("OpenSans-Regular", size: 17))
|
||||||
|
case 2:
|
||||||
|
TextEditor(text: $draftText).font(.custom("Hack-Regular", size: 17))
|
||||||
|
default:
|
||||||
|
TextEditor(text: $draftText).font(.custom("Lora", size: 17))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Section(header: Text("Save To")) {
|
||||||
|
Button(action: {
|
||||||
|
self.selectedBlog = nil
|
||||||
|
}, label: {
|
||||||
|
HStack {
|
||||||
|
Text(draftsCollectionName)
|
||||||
|
.foregroundColor(selectedBlog == nil ? .primary : .secondary)
|
||||||
|
Spacer()
|
||||||
|
if selectedBlog == nil {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ForEach(collections, id: \.self) { collection in
|
||||||
|
Button(action: {
|
||||||
|
self.selectedBlog = collection
|
||||||
|
}, label: {
|
||||||
|
HStack {
|
||||||
|
Text(collection.title)
|
||||||
|
.foregroundColor(selectedBlog == collection ? .primary : .secondary)
|
||||||
|
Spacer()
|
||||||
|
if selectedBlog == collection {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alert(isPresented: $isShowingAlert, content: {
|
||||||
|
Alert(
|
||||||
|
title: Text("Something Went Wrong"),
|
||||||
|
message: Text("WriteFreely can't create a draft with the data received."),
|
||||||
|
dismissButton: .default(Text("OK"), action: {
|
||||||
|
extensionContext.cancelRequest(withError: WFActionExtensionError.couldNotParseInputItems)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.onAppear {
|
||||||
|
do {
|
||||||
|
try getPageDataFromExtensionContext()
|
||||||
|
} catch {
|
||||||
|
self.isShowingAlert = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func savePostToCollection(collection: WFACollection?, title: String, body: String) {
|
||||||
|
let post = WFAPost(context: managedObjectContext)
|
||||||
|
post.createdDate = Date()
|
||||||
|
post.title = title
|
||||||
|
post.body = body
|
||||||
|
post.status = PostStatus.local.rawValue
|
||||||
|
post.collectionAlias = collection?.alias
|
||||||
|
switch fontIndex {
|
||||||
|
case 1:
|
||||||
|
post.appearance = "sans"
|
||||||
|
case 2:
|
||||||
|
post.appearance = "wrap"
|
||||||
|
default:
|
||||||
|
post.appearance = "serif"
|
||||||
|
}
|
||||||
|
if let languageCode = Locale.current.languageCode {
|
||||||
|
post.language = languageCode
|
||||||
|
post.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft
|
||||||
|
}
|
||||||
|
LocalStorageManager.standard.saveContext()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getPageDataFromExtensionContext() throws {
|
||||||
|
if let inputItem = extensionContext.inputItems.first as? NSExtensionItem {
|
||||||
|
if let itemProvider = inputItem.attachments?.first {
|
||||||
|
|
||||||
|
let typeIdentifier: String
|
||||||
|
|
||||||
|
if #available(iOS 15, *) {
|
||||||
|
typeIdentifier = UTType.propertyList.identifier
|
||||||
|
} else {
|
||||||
|
typeIdentifier = kUTTypePropertyList as String
|
||||||
|
}
|
||||||
|
|
||||||
|
itemProvider.loadItem(forTypeIdentifier: typeIdentifier) { (dict, error) in
|
||||||
|
if let error = error {
|
||||||
|
print("⚠️", error)
|
||||||
|
self.isShowingAlert = true
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let itemDict = dict as? NSDictionary else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let jsValues = itemDict[NSExtensionJavaScriptPreprocessingResultsKey] as? NSDictionary else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let pageTitle = jsValues["title"] as? String ?? ""
|
||||||
|
let pageURL = jsValues["URL"] as? String ?? ""
|
||||||
|
let pageSelectedText = jsValues["selection"] as? String ?? ""
|
||||||
|
|
||||||
|
if pageSelectedText.isEmpty {
|
||||||
|
// If there's no selected text, create a Markdown link to the webpage.
|
||||||
|
self.draftText = "[\(pageTitle)](\(pageURL))"
|
||||||
|
} else {
|
||||||
|
// If there is selected text, create a Markdown blockquote with the selection
|
||||||
|
// and add a Markdown link to the webpage.
|
||||||
|
self.draftText = """
|
||||||
|
> \(pageSelectedText)
|
||||||
|
|
||||||
|
Via: [\(pageTitle)](\(pageURL))
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw WFActionExtensionError.couldNotParseInputItems
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw WFActionExtensionError.couldNotParseInputItems
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,30 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>UIAppFonts</key>
|
||||||
|
<array>
|
||||||
|
<string>LoraGX.ttf</string>
|
||||||
|
<string>OpenSans-Regular.ttf</string>
|
||||||
|
<string>Hack-Regular.ttf</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Create WriteFreely draft</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSExtensionAttributes</key>
|
<key>NSExtensionAttributes</key>
|
||||||
@ -24,8 +48,8 @@
|
|||||||
<key>NSExtensionServiceTouchBarIconName</key>
|
<key>NSExtensionServiceTouchBarIconName</key>
|
||||||
<string>NSActionTemplate</string>
|
<string>NSActionTemplate</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSExtensionMainStoryboard</key>
|
<key>NSExtensionPrincipalClass</key>
|
||||||
<string>MainInterface</string>
|
<string>$(PRODUCT_MODULE_NAME).ActionViewController</string>
|
||||||
<key>NSExtensionPointIdentifier</key>
|
<key>NSExtensionPointIdentifier</key>
|
||||||
<string>com.apple.ui-services</string>
|
<string>com.apple.ui-services</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "AppIconExtension@2x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "AppIconExtension@3x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "83.5x83.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
@ -56,8 +56,6 @@ extension AccountError: LocalizedError {
|
|||||||
struct AccountModel {
|
struct AccountModel {
|
||||||
@AppStorage(WFDefaults.isLoggedIn, store: UserDefaults.shared) var isLoggedIn: Bool = false
|
@AppStorage(WFDefaults.isLoggedIn, store: UserDefaults.shared) var isLoggedIn: Bool = false
|
||||||
private let defaults = UserDefaults.shared
|
private let defaults = UserDefaults.shared
|
||||||
let usernameStringKey = "usernameStringKey"
|
|
||||||
let serverStringKey = "serverStringKey"
|
|
||||||
|
|
||||||
var server: String = ""
|
var server: String = ""
|
||||||
var username: String = ""
|
var username: String = ""
|
||||||
@ -68,19 +66,19 @@ struct AccountModel {
|
|||||||
self.user = user
|
self.user = user
|
||||||
self.username = user.username ?? ""
|
self.username = user.username ?? ""
|
||||||
self.isLoggedIn = true
|
self.isLoggedIn = true
|
||||||
defaults.set(user.username, forKey: usernameStringKey)
|
defaults.set(user.username, forKey: WFDefaults.usernameStringKey)
|
||||||
defaults.set(server, forKey: serverStringKey)
|
defaults.set(server, forKey: WFDefaults.serverStringKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func logout() {
|
mutating func logout() {
|
||||||
self.user = nil
|
self.user = nil
|
||||||
self.isLoggedIn = false
|
self.isLoggedIn = false
|
||||||
defaults.removeObject(forKey: usernameStringKey)
|
defaults.removeObject(forKey: WFDefaults.usernameStringKey)
|
||||||
defaults.removeObject(forKey: serverStringKey)
|
defaults.removeObject(forKey: WFDefaults.serverStringKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func restoreState() {
|
mutating func restoreState() {
|
||||||
server = defaults.string(forKey: serverStringKey) ?? ""
|
server = defaults.string(forKey: WFDefaults.serverStringKey) ?? ""
|
||||||
username = defaults.string(forKey: usernameStringKey) ?? ""
|
username = defaults.string(forKey: WFDefaults.usernameStringKey) ?? ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@ enum WFDefaults {
|
|||||||
static let showAllPostsFlag = "showAllPostsFlag"
|
static let showAllPostsFlag = "showAllPostsFlag"
|
||||||
static let selectedCollectionURL = "selectedCollectionURL"
|
static let selectedCollectionURL = "selectedCollectionURL"
|
||||||
static let lastDraftURL = "lastDraftURL"
|
static let lastDraftURL = "lastDraftURL"
|
||||||
|
static let colorSchemeIntegerKey = "colorSchemeIntegerKey"
|
||||||
|
static let defaultFontIntegerKey = "defaultFontIntegerKey"
|
||||||
|
static let usernameStringKey = "usernameStringKey"
|
||||||
|
static let serverStringKey = "serverStringKey"
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
static let automaticallyChecksForUpdates = "automaticallyChecksForUpdates"
|
static let automaticallyChecksForUpdates = "automaticallyChecksForUpdates"
|
||||||
static let subscribeToBetaUpdates = "subscribeToBetaUpdates"
|
static let subscribeToBetaUpdates = "subscribeToBetaUpdates"
|
||||||
|
@ -43,8 +43,8 @@ final class WriteFreelyModel: ObservableObject {
|
|||||||
|
|
||||||
init() {
|
init() {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.preferences.appearance = self.defaults.integer(forKey: self.preferences.colorSchemeIntegerKey)
|
self.preferences.appearance = self.defaults.integer(forKey: WFDefaults.colorSchemeIntegerKey)
|
||||||
self.preferences.font = self.defaults.integer(forKey: self.preferences.defaultFontIntegerKey)
|
self.preferences.font = self.defaults.integer(forKey: WFDefaults.defaultFontIntegerKey)
|
||||||
self.account.restoreState()
|
self.account.restoreState()
|
||||||
if self.account.isLoggedIn {
|
if self.account.isLoggedIn {
|
||||||
guard let serverURL = URL(string: self.account.server) else {
|
guard let serverURL = URL(string: self.account.server) else {
|
||||||
|
@ -2,8 +2,6 @@ import SwiftUI
|
|||||||
|
|
||||||
class PreferencesModel: ObservableObject {
|
class PreferencesModel: ObservableObject {
|
||||||
private let defaults = UserDefaults.shared
|
private let defaults = UserDefaults.shared
|
||||||
let colorSchemeIntegerKey = "colorSchemeIntegerKey"
|
|
||||||
let defaultFontIntegerKey = "defaultFontIntegerKey"
|
|
||||||
|
|
||||||
/* We're stuck dropping into AppKit/UIKit to set light/dark schemes for now,
|
/* We're stuck dropping into AppKit/UIKit to set light/dark schemes for now,
|
||||||
* because setting the .preferredColorScheme modifier on views in SwiftUI is
|
* because setting the .preferredColorScheme modifier on views in SwiftUI is
|
||||||
@ -17,6 +15,7 @@ class PreferencesModel: ObservableObject {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
|
@available(iOSApplicationExtension, unavailable)
|
||||||
var window: UIWindow? {
|
var window: UIWindow? {
|
||||||
guard let scene = UIApplication.shared.connectedScenes.first,
|
guard let scene = UIApplication.shared.connectedScenes.first,
|
||||||
let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
|
let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
|
||||||
@ -27,7 +26,10 @@ class PreferencesModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@available(iOSApplicationExtension, unavailable)
|
||||||
@Published var selectedColorScheme: ColorScheme?
|
@Published var selectedColorScheme: ColorScheme?
|
||||||
|
|
||||||
|
@available(iOSApplicationExtension, unavailable)
|
||||||
@Published var appearance: Int = 0 {
|
@Published var appearance: Int = 0 {
|
||||||
didSet {
|
didSet {
|
||||||
switch appearance {
|
switch appearance {
|
||||||
@ -54,12 +56,12 @@ class PreferencesModel: ObservableObject {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults.set(appearance, forKey: colorSchemeIntegerKey)
|
defaults.set(appearance, forKey: WFDefaults.colorSchemeIntegerKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Published var font: Int = 0 {
|
@Published var font: Int = 0 {
|
||||||
didSet {
|
didSet {
|
||||||
defaults.set(font, forKey: defaultFontIntegerKey)
|
defaults.set(font, forKey: WFDefaults.defaultFontIntegerKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,21 @@
|
|||||||
172E10012735B83E00061372 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 172E10002735B83E00061372 /* UniformTypeIdentifiers.framework */; platformFilter = maccatalyst; };
|
172E10012735B83E00061372 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 172E10002735B83E00061372 /* UniformTypeIdentifiers.framework */; platformFilter = maccatalyst; };
|
||||||
172E10042735B83E00061372 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 172E10032735B83E00061372 /* Media.xcassets */; };
|
172E10042735B83E00061372 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 172E10032735B83E00061372 /* Media.xcassets */; };
|
||||||
172E10062735B83E00061372 /* ActionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10052735B83E00061372 /* ActionViewController.swift */; };
|
172E10062735B83E00061372 /* ActionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10052735B83E00061372 /* ActionViewController.swift */; };
|
||||||
172E10092735B83E00061372 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 172E10072735B83E00061372 /* MainInterface.storyboard */; };
|
|
||||||
172E100D2735B83E00061372 /* ActionExtension-iOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 172E0FFF2735B83E00061372 /* ActionExtension-iOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
172E100D2735B83E00061372 /* ActionExtension-iOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 172E0FFF2735B83E00061372 /* ActionExtension-iOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
172E10132735BB6200061372 /* Action.js in Resources */ = {isa = PBXBuildFile; fileRef = 172E10122735BB6200061372 /* Action.js */; };
|
172E10132735BB6200061372 /* Action.js in Resources */ = {isa = PBXBuildFile; fileRef = 172E10122735BB6200061372 /* Action.js */; };
|
||||||
|
172E10152735C2BD00061372 /* UIHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172E10142735C2BD00061372 /* UIHostingView.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 */; };
|
||||||
|
172E101B2735C54400061372 /* WriteFreely in Frameworks */ = {isa = PBXBuildFile; productRef = 172E101A2735C54400061372 /* WriteFreely */; };
|
||||||
|
172E101C2735C57400061372 /* LocalStorageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1756DBB924FED45500207AB8 /* LocalStorageManager.swift */; };
|
||||||
|
172E101D2735C5AB00061372 /* LocalStorageModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1756DBB524FED3A400207AB8 /* LocalStorageModel.xcdatamodeld */; };
|
||||||
|
172E101E2735C62F00061372 /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E612507D8E600072984 /* PostStatus.swift */; };
|
||||||
|
172E101F2735C64600061372 /* WFAPost+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B996D62502D23E0017B536 /* WFAPost+CoreDataClass.swift */; };
|
||||||
|
172E10202735C64600061372 /* WFACollection+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1756DBFF24FEE18400207AB8 /* WFACollection+CoreDataClass.swift */; };
|
||||||
|
172E10212735C64600061372 /* WFACollection+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1756DC0024FEE18400207AB8 /* WFACollection+CoreDataProperties.swift */; };
|
||||||
|
172E10222735C64600061372 /* WFAPost+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B996D72502D23E0017B536 /* WFAPost+CoreDataProperties.swift */; };
|
||||||
|
172E10232735C6FF00061372 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */; };
|
||||||
|
172E10242735C72500061372 /* PreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D435E724E3128F0036B539 /* PreferencesModel.swift */; };
|
||||||
173E19D1254318F600440F0F /* RemoteChangePromptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173E19D0254318F600440F0F /* RemoteChangePromptView.swift */; };
|
173E19D1254318F600440F0F /* RemoteChangePromptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173E19D0254318F600440F0F /* RemoteChangePromptView.swift */; };
|
||||||
173E19E3254329CC00440F0F /* PostTextEditingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173E19E2254329CC00440F0F /* PostTextEditingView.swift */; };
|
173E19E3254329CC00440F0F /* PostTextEditingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173E19E2254329CC00440F0F /* PostTextEditingView.swift */; };
|
||||||
17466626256C0D0600629997 /* MacEditorTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17466625256C0D0600629997 /* MacEditorTextView.swift */; };
|
17466626256C0D0600629997 /* MacEditorTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17466625256C0D0600629997 /* MacEditorTextView.swift */; };
|
||||||
@ -62,6 +74,10 @@
|
|||||||
1756DC0424FEE18400207AB8 /* WFACollection+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1756DC0024FEE18400207AB8 /* WFACollection+CoreDataProperties.swift */; };
|
1756DC0424FEE18400207AB8 /* WFACollection+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1756DC0024FEE18400207AB8 /* WFACollection+CoreDataProperties.swift */; };
|
||||||
17681E412519410E00D394AE /* UINavigationController+Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17681E402519410E00D394AE /* UINavigationController+Appearance.swift */; };
|
17681E412519410E00D394AE /* UINavigationController+Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17681E402519410E00D394AE /* UINavigationController+Appearance.swift */; };
|
||||||
1780F6EF25895EDB00FE45FF /* PostCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1780F6EE25895EDB00FE45FF /* PostCommands.swift */; };
|
1780F6EF25895EDB00FE45FF /* PostCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1780F6EE25895EDB00FE45FF /* PostCommands.swift */; };
|
||||||
|
17836C14273EFB870047AF61 /* UserDefaults+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171DC676272C7D0B002B9B8A /* UserDefaults+Extensions.swift */; };
|
||||||
|
17836C15273F0FBB0047AF61 /* Hack-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 17D4F3A42514F1E900517CE6 /* Hack-Regular.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 */; };
|
||||||
17A4FEDA25924AF70037E96B /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 17A4FED925924AF70037E96B /* Sparkle */; };
|
17A4FEDA25924AF70037E96B /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 17A4FED925924AF70037E96B /* Sparkle */; };
|
||||||
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 */; };
|
||||||
@ -170,9 +186,11 @@
|
|||||||
172E10002735B83E00061372 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
|
172E10002735B83E00061372 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
|
||||||
172E10032735B83E00061372 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
|
172E10032735B83E00061372 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
|
||||||
172E10052735B83E00061372 /* ActionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionViewController.swift; sourceTree = "<group>"; };
|
172E10052735B83E00061372 /* ActionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionViewController.swift; sourceTree = "<group>"; };
|
||||||
172E10082735B83E00061372 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
|
172E100A2735B83E00061372 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; usesTabs = 1; };
|
||||||
172E100A2735B83E00061372 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
|
||||||
172E10122735BB6200061372 /* Action.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Action.js; sourceTree = "<group>"; };
|
172E10122735BB6200061372 /* Action.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Action.js; sourceTree = "<group>"; };
|
||||||
|
172E10142735C2BD00061372 /* UIHostingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIHostingView.swift; sourceTree = "<group>"; };
|
||||||
|
172E10162735C2DF00061372 /* EnvironmentValues+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
|
172E10182735C3DB00061372 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
173E19D0254318F600440F0F /* RemoteChangePromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteChangePromptView.swift; sourceTree = "<group>"; };
|
173E19D0254318F600440F0F /* RemoteChangePromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteChangePromptView.swift; sourceTree = "<group>"; };
|
||||||
173E19E2254329CC00440F0F /* PostTextEditingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostTextEditingView.swift; sourceTree = "<group>"; };
|
173E19E2254329CC00440F0F /* PostTextEditingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostTextEditingView.swift; sourceTree = "<group>"; };
|
||||||
17466625256C0D0600629997 /* MacEditorTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacEditorTextView.swift; sourceTree = "<group>"; };
|
17466625256C0D0600629997 /* MacEditorTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacEditorTextView.swift; sourceTree = "<group>"; };
|
||||||
@ -192,6 +210,7 @@
|
|||||||
1756DC0024FEE18400207AB8 /* WFACollection+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WFACollection+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; };
|
1756DC0024FEE18400207AB8 /* WFACollection+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WFACollection+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
17681E402519410E00D394AE /* UINavigationController+Appearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Appearance.swift"; sourceTree = "<group>"; };
|
17681E402519410E00D394AE /* UINavigationController+Appearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Appearance.swift"; sourceTree = "<group>"; };
|
||||||
1780F6EE25895EDB00FE45FF /* PostCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCommands.swift; sourceTree = "<group>"; };
|
1780F6EE25895EDB00FE45FF /* PostCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCommands.swift; sourceTree = "<group>"; };
|
||||||
|
17836C18273F10C40047AF61 /* ActionExtension-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "ActionExtension-iOS.entitlements"; sourceTree = "<group>"; };
|
||||||
17A355D3271A052C007C7A47 /* WriteFreely-MultiPlatform (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "WriteFreely-MultiPlatform (iOS).entitlements"; sourceTree = "<group>"; };
|
17A355D3271A052C007C7A47 /* WriteFreely-MultiPlatform (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "WriteFreely-MultiPlatform (iOS).entitlements"; sourceTree = "<group>"; };
|
||||||
17A4FEDF25924E810037E96B /* MacSoftwareUpdater.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = MacSoftwareUpdater.md; sourceTree = "<group>"; };
|
17A4FEDF25924E810037E96B /* MacSoftwareUpdater.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = MacSoftwareUpdater.md; sourceTree = "<group>"; };
|
||||||
17A4FEEC25927E730037E96B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
17A4FEEC25927E730037E96B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
@ -250,6 +269,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
172E10012735B83E00061372 /* UniformTypeIdentifiers.framework in Frameworks */,
|
172E10012735B83E00061372 /* UniformTypeIdentifiers.framework in Frameworks */,
|
||||||
|
172E101B2735C54400061372 /* WriteFreely in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -308,9 +328,10 @@
|
|||||||
172E10022735B83E00061372 /* ActionExtension-iOS */ = {
|
172E10022735B83E00061372 /* ActionExtension-iOS */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
17836C18273F10C40047AF61 /* ActionExtension-iOS.entitlements */,
|
||||||
172E10032735B83E00061372 /* Media.xcassets */,
|
172E10032735B83E00061372 /* Media.xcassets */,
|
||||||
|
172E10182735C3DB00061372 /* ContentView.swift */,
|
||||||
172E10052735B83E00061372 /* ActionViewController.swift */,
|
172E10052735B83E00061372 /* ActionViewController.swift */,
|
||||||
172E10072735B83E00061372 /* MainInterface.storyboard */,
|
|
||||||
172E100A2735B83E00061372 /* Info.plist */,
|
172E100A2735B83E00061372 /* Info.plist */,
|
||||||
172E10122735BB6200061372 /* Action.js */,
|
172E10122735BB6200061372 /* Action.js */,
|
||||||
);
|
);
|
||||||
@ -367,6 +388,8 @@
|
|||||||
children = (
|
children = (
|
||||||
1756AE8024CB844500FD7257 /* View+Keyboard.swift */,
|
1756AE8024CB844500FD7257 /* View+Keyboard.swift */,
|
||||||
17681E402519410E00D394AE /* UINavigationController+Appearance.swift */,
|
17681E402519410E00D394AE /* UINavigationController+Appearance.swift */,
|
||||||
|
172E10142735C2BD00061372 /* UIHostingView.swift */,
|
||||||
|
172E10162735C2DF00061372 /* EnvironmentValues+Extensions.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -595,6 +618,9 @@
|
|||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = "ActionExtension-iOS";
|
name = "ActionExtension-iOS";
|
||||||
|
packageProductDependencies = (
|
||||||
|
172E101A2735C54400061372 /* WriteFreely */,
|
||||||
|
);
|
||||||
productName = "ActionExtension-iOS";
|
productName = "ActionExtension-iOS";
|
||||||
productReference = 172E0FFF2735B83E00061372 /* ActionExtension-iOS.appex */;
|
productReference = 172E0FFF2735B83E00061372 /* ActionExtension-iOS.appex */;
|
||||||
productType = "com.apple.product-type.app-extension";
|
productType = "com.apple.product-type.app-extension";
|
||||||
@ -739,9 +765,11 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
17836C17273F0FBB0047AF61 /* OpenSans-Regular.ttf in Resources */,
|
||||||
172E10132735BB6200061372 /* Action.js in Resources */,
|
172E10132735BB6200061372 /* Action.js in Resources */,
|
||||||
172E10042735B83E00061372 /* Media.xcassets in Resources */,
|
172E10042735B83E00061372 /* Media.xcassets in Resources */,
|
||||||
172E10092735B83E00061372 /* MainInterface.storyboard in Resources */,
|
17836C15273F0FBB0047AF61 /* Hack-Regular.ttf in Resources */,
|
||||||
|
17836C16273F0FBB0047AF61 /* LoraGX.ttf in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -834,6 +862,19 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
172E10062735B83E00061372 /* ActionViewController.swift in Sources */,
|
172E10062735B83E00061372 /* ActionViewController.swift in Sources */,
|
||||||
|
172E10202735C64600061372 /* WFACollection+CoreDataClass.swift in Sources */,
|
||||||
|
172E10222735C64600061372 /* WFAPost+CoreDataProperties.swift in Sources */,
|
||||||
|
172E101D2735C5AB00061372 /* LocalStorageModel.xcdatamodeld in Sources */,
|
||||||
|
17836C14273EFB870047AF61 /* UserDefaults+Extensions.swift in Sources */,
|
||||||
|
172E10242735C72500061372 /* PreferencesModel.swift in Sources */,
|
||||||
|
172E10172735C2DF00061372 /* EnvironmentValues+Extensions.swift in Sources */,
|
||||||
|
172E10212735C64600061372 /* WFACollection+CoreDataProperties.swift in Sources */,
|
||||||
|
172E101C2735C57400061372 /* LocalStorageManager.swift in Sources */,
|
||||||
|
172E10192735C3DB00061372 /* ContentView.swift in Sources */,
|
||||||
|
172E10152735C2BD00061372 /* UIHostingView.swift in Sources */,
|
||||||
|
172E101F2735C64600061372 /* WFAPost+CoreDataClass.swift in Sources */,
|
||||||
|
172E10232735C6FF00061372 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */,
|
||||||
|
172E101E2735C62F00061372 /* PostStatus.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -968,22 +1009,14 @@
|
|||||||
};
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
|
||||||
172E10072735B83E00061372 /* MainInterface.storyboard */ = {
|
|
||||||
isa = PBXVariantGroup;
|
|
||||||
children = (
|
|
||||||
172E10082735B83E00061372 /* Base */,
|
|
||||||
);
|
|
||||||
name = MainInterface.storyboard;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXVariantGroup section */
|
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
172E100F2735B83E00061372 /* Debug */ = {
|
172E100F2735B83E00061372 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "";
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconExtension;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||||
@ -991,7 +1024,7 @@
|
|||||||
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "ActionExtension-iOS";
|
INFOPLIST_KEY_CFBundleDisplayName = "ActionExtension-iOS";
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -1011,7 +1044,10 @@
|
|||||||
172E10102735B83E00061372 /* Release */ = {
|
172E10102735B83E00061372 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "";
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconExtension;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||||
@ -1019,7 +1055,7 @@
|
|||||||
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "ActionExtension-iOS";
|
INFOPLIST_KEY_CFBundleDisplayName = "ActionExtension-iOS";
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -1431,6 +1467,11 @@
|
|||||||
package = 1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
package = 1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
||||||
productName = WriteFreely;
|
productName = WriteFreely;
|
||||||
};
|
};
|
||||||
|
172E101A2735C54400061372 /* WriteFreely */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 1714DD63260BAC14000C0DFF /* XCRemoteSwiftPackageReference "writefreely-swift" */;
|
||||||
|
productName = WriteFreely;
|
||||||
|
};
|
||||||
17A4FED925924AF70037E96B /* Sparkle */ = {
|
17A4FED925924AF70037E96B /* Sparkle */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 17A4FED825924AF70037E96B /* XCRemoteSwiftPackageReference "Sparkle" */;
|
package = 17A4FED825924AF70037E96B /* XCRemoteSwiftPackageReference "Sparkle" */;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<key>ActionExtension-iOS.xcscheme_^#shared#^_</key>
|
<key>ActionExtension-iOS.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>2</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>WriteFreely-MultiPlatform (iOS).xcscheme_^#shared#^_</key>
|
<key>WriteFreely-MultiPlatform (iOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
@ -17,7 +17,7 @@
|
|||||||
<key>WriteFreely-MultiPlatform (macOS).xcscheme_^#shared#^_</key>
|
<key>WriteFreely-MultiPlatform (macOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>1</integer>
|
<integer>2</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
20
iOS/Extensions/EnvironmentValues+Extensions.swift
Normal file
20
iOS/Extensions/EnvironmentValues+Extensions.swift
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Credit:
|
||||||
|
// https://github.com/sindresorhus/Blear/blob/9ce7cd6ad8d6a88f8d0be12b1ef9152baeeacf96/Blear/Utilities.swift#L1052-L1064
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension EnvironmentValues {
|
||||||
|
|
||||||
|
private struct ExtensionContext: EnvironmentKey {
|
||||||
|
static var defaultValue: NSExtensionContext?
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The `.extensionContext` of an app extension view controller.
|
||||||
|
var extensionContext: NSExtensionContext? {
|
||||||
|
get { self[ExtensionContext.self] }
|
||||||
|
set {
|
||||||
|
self[ExtensionContext.self] = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
57
iOS/Extensions/UIHostingView.swift
Normal file
57
iOS/Extensions/UIHostingView.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Credit:
|
||||||
|
// https://github.com/sindresorhus/Blear/blob/9ce7cd6ad8d6a88f8d0be12b1ef9152baeeacf96/Blear/Utilities.swift#L317-L368
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
final class UIHostingView<Content: View>: UIView {
|
||||||
|
private let rootViewHostingController: UIHostingController<Content>
|
||||||
|
|
||||||
|
var rootView: Content {
|
||||||
|
get { rootViewHostingController.rootView }
|
||||||
|
set {
|
||||||
|
rootViewHostingController.rootView = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(rootView: Content) {
|
||||||
|
self.rootViewHostingController = UIHostingController(rootView: rootView)
|
||||||
|
super.init(frame: .zero)
|
||||||
|
rootViewHostingController.view.backgroundColor = .clear
|
||||||
|
addSubview(rootViewHostingController.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, unavailable)
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
rootViewHostingController.view.frame = bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
override func sizeToFit() {
|
||||||
|
guard let superview = superview else {
|
||||||
|
super.sizeToFit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.size = rootViewHostingController.sizeThatFits(in: superview.frame.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||||
|
rootViewHostingController.sizeThatFits(in: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func systemLayoutSizeFitting(_ targetSize: CGSize) -> CGSize {
|
||||||
|
rootViewHostingController.sizeThatFits(in: targetSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func systemLayoutSizeFitting(
|
||||||
|
_ targetSize: CGSize,
|
||||||
|
withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority,
|
||||||
|
verticalFittingPriority: UILayoutPriority
|
||||||
|
) -> CGSize {
|
||||||
|
rootViewHostingController.sizeThatFits(in: targetSize)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user