mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Rough out the new share extension for iOS
This commit is contained in:
24
iOS/ShareExtension/Base.lproj/MainInterface.storyboard
Normal file
24
iOS/ShareExtension/Base.lproj/MainInterface.storyboard
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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="j1y-V4-xli">
|
||||
<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>
|
||||
<!--Share View Controller-->
|
||||
<scene sceneID="ceB-am-kn3">
|
||||
<objects>
|
||||
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
41
iOS/ShareExtension/Info.plist
Normal file
41
iOS/ShareExtension/Info.plist
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$(PRODUCT_NAME)</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>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationRule</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
<key>NSExtensionJavaScriptPreprocessingFile</key>
|
||||
<string>SafariExt</string>
|
||||
</dict>
|
||||
<key>NSExtensionMainStoryboard</key>
|
||||
<string>MainInterface</string>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.share-services</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
12
iOS/ShareExtension/SafariExt.js
Normal file
12
iOS/ShareExtension/SafariExt.js
Normal file
@@ -0,0 +1,12 @@
|
||||
var SafariExtPreprocessorClass = function() {};
|
||||
|
||||
SafariExtPreprocessorClass.prototype = {
|
||||
|
||||
run: function(arguments) {
|
||||
arguments.completionFunction({ "url": document.URL });
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// The JavaScript file must contain a global object named "ExtensionPreprocessingJS".
|
||||
var ExtensionPreprocessingJS = new SafariExtPreprocessorClass;
|
||||
152
iOS/ShareExtension/ShareViewController.swift
Normal file
152
iOS/ShareExtension/ShareViewController.swift
Normal file
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// ShareViewController.swift
|
||||
// NetNewsWire iOS Share Extension
|
||||
//
|
||||
// Created by Maurice Parker on 9/8/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import MobileCoreServices
|
||||
import Social
|
||||
import Account
|
||||
import Articles
|
||||
import RSCore
|
||||
import RSTree
|
||||
|
||||
class ShareViewController: SLComposeServiceViewController {
|
||||
|
||||
private var url: URL?
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
title = "NetNewsWire"
|
||||
placeholder = "Feed Name (Optional)"
|
||||
if let button = navigationController?.navigationBar.topItem?.rightBarButtonItem {
|
||||
button.title = "Add Feed"
|
||||
button.isEnabled = true
|
||||
}
|
||||
|
||||
// Hack the bottom table rows to be smaller since the controller itself doesn't have enough sense to size itself correctly
|
||||
if let nav = self.children.first as? UINavigationController, let tableView = nav.children.first?.view.subviews.first as? UITableView {
|
||||
tableView.rowHeight = 38
|
||||
}
|
||||
|
||||
var provider: NSItemProvider? = nil
|
||||
|
||||
// Try to get any HTML that is maybe passed in
|
||||
for item in self.extensionContext!.inputItems as! [NSExtensionItem] {
|
||||
for itemProvider in item.attachments! {
|
||||
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypePropertyList as String) {
|
||||
provider = itemProvider
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if provider != nil {
|
||||
provider!.loadItem(forTypeIdentifier: kUTTypePropertyList as String, options: nil, completionHandler: { [weak self] (pList, error) in
|
||||
if error != nil {
|
||||
return
|
||||
}
|
||||
guard let dataGraph = pList as? NSDictionary else {
|
||||
return
|
||||
}
|
||||
guard let results = dataGraph["NSExtensionJavaScriptPreprocessingResultsKey"] as? NSDictionary else {
|
||||
return
|
||||
}
|
||||
if let url = URL(string: results["url"] as! String) {
|
||||
self?.url = url
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Try to get the URL if it is passed in
|
||||
for item in self.extensionContext!.inputItems as! [NSExtensionItem] {
|
||||
for itemProvider in item.attachments! {
|
||||
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
|
||||
provider = itemProvider
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if provider != nil {
|
||||
provider!.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil, completionHandler: { [weak self] (urlCoded, error) in
|
||||
if error != nil {
|
||||
return
|
||||
}
|
||||
guard let url = urlCoded as? URL else {
|
||||
return
|
||||
}
|
||||
self?.url = url
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override func isContentValid() -> Bool {
|
||||
return url != nil
|
||||
}
|
||||
|
||||
override func didSelectPost() {
|
||||
|
||||
// Temporarily hardcoded
|
||||
let account = AccountManager.shared.activeAccounts.first
|
||||
let container = account!
|
||||
|
||||
let feedName = contentText.isEmpty ? nil : contentText
|
||||
|
||||
account!.createFeed(url: url!.absoluteString, name: feedName, container: container) { result in
|
||||
|
||||
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
|
||||
|
||||
switch result {
|
||||
case .success(let feed):
|
||||
break
|
||||
case .failure(let error):
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
|
||||
|
||||
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
|
||||
}
|
||||
|
||||
override func configurationItems() -> [Any]! {
|
||||
|
||||
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
|
||||
guard let urlItem = SLComposeSheetConfigurationItem() else { return nil }
|
||||
urlItem.title = "URL"
|
||||
urlItem.value = url?.absoluteString ?? ""
|
||||
|
||||
guard let folderItem = SLComposeSheetConfigurationItem() else { return nil }
|
||||
folderItem.title = "Folder"
|
||||
folderItem.value = "On My iPhone"
|
||||
folderItem.tapHandler = {
|
||||
print("Tapped that!")
|
||||
}
|
||||
|
||||
// Example how you might navigate to a UIViewController with an edit field...
|
||||
// aliasConfigItem.tapHandler = {
|
||||
//
|
||||
// let aliasEditViewController = UIViewController()
|
||||
// aliasEditViewController.navigationController?.title = "Alias"
|
||||
//
|
||||
// let textField = UITextField(frame: CGRectMake(10,10,self.view.frame.width - 50,50))
|
||||
// textField.borderStyle = UITextBorderStyle.RoundedRect;
|
||||
// textField.placeholder = "enter your alias";
|
||||
// textField.keyboardType = UIKeyboardType.Default;
|
||||
// textField.returnKeyType = UIReturnKeyType.Done;
|
||||
// aliasEditViewController.view.addSubview(textField)
|
||||
//
|
||||
// self.pushConfigurationViewController(aliasEditViewController)
|
||||
// }
|
||||
|
||||
return [folderItem, urlItem]
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user