mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-31 21:41:33 +00:00
#1575 (subscribe to site in share sheet)
This commit is contained in:
parent
738bdda220
commit
10c405c44e
4 changed files with 183 additions and 56 deletions
|
@ -579,6 +579,7 @@ static NSArray<NSString *> *NewsBlurTopSectionNames;
|
|||
[defaults setObject:[results objectForKey:@"share_ext_token"] forKey:@"share:token"];
|
||||
[defaults setObject:self.appDelegate.url forKey:@"share:host"];
|
||||
[defaults setObject:appDelegate.dictSavedStoryTags forKey:@"share:tags"];
|
||||
[defaults setObject:appDelegate.dictFoldersArray forKey:@"share:folders"];
|
||||
[self validateWidgetFeedsForGroupDefaults:defaults usingResults:results];
|
||||
[defaults synchronize];
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Jka-P1-QHB">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Jka-P1-QHB">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
@ -36,10 +37,11 @@
|
|||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="nek-0G-qOK">
|
||||
<rect key="frame" x="66" y="64" width="243" height="32"/>
|
||||
<rect key="frame" x="5" y="64" width="365" height="32"/>
|
||||
<segments>
|
||||
<segment title="Save This Story"/>
|
||||
<segment title="Share This Story"/>
|
||||
<segment title="Add This Site"/>
|
||||
</segments>
|
||||
<connections>
|
||||
<action selector="changedMode:" destination="j1y-V4-xli" eventType="valueChanged" id="UPm-xD-bxX"/>
|
||||
|
@ -52,7 +54,7 @@
|
|||
<viewLayoutGuide key="frameLayoutGuide" id="PCs-SD-lDm"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="ShareSaveTagCell" id="QfW-wS-4rz" customClass="ShareSaveTagCell" customModule="Share_Extension" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="24.5" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="44.5" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="QfW-wS-4rz" id="FUw-X2-Tgd">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
|
@ -76,14 +78,14 @@
|
|||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="ShareSaveNewCell" id="efQ-d6-znU" customClass="ShareSaveNewCell" customModule="Share_Extension" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="68" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="88" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="efQ-d6-znU" id="74T-Fj-bga">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="new tag" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="qAx-nx-hOD">
|
||||
<rect key="frame" x="20" y="11" width="335" height="22"/>
|
||||
<rect key="frame" x="20" y="11.5" width="335" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="words"/>
|
||||
<connections>
|
||||
|
@ -105,7 +107,7 @@
|
|||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="ShareCommentCell" rowHeight="252" id="Y1T-la-hCi" customClass="ShareCommentCell" customModule="Share_Extension" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="111.5" width="375" height="252"/>
|
||||
<rect key="frame" x="0.0" y="131.5" width="375" height="252"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Y1T-la-hCi" id="F3X-7c-ujj">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="252"/>
|
||||
|
|
|
@ -28,9 +28,12 @@ class ShareViewController: UIViewController {
|
|||
|
||||
/// Share publicly.
|
||||
case share
|
||||
|
||||
/// Add site.
|
||||
case add
|
||||
}
|
||||
|
||||
/// Whether we are saving the story privately or sharing publicly.
|
||||
/// Whether we are saving the story privately, sharing publicly, or adding a site.
|
||||
var mode: Mode = .save
|
||||
|
||||
/// Dictionary representation of a tag.
|
||||
|
@ -60,6 +63,15 @@ class ShareViewController: UIViewController {
|
|||
/// User-entered comments, only used when sharing.
|
||||
var comments = ""
|
||||
|
||||
/// An array of folders, from the main app.
|
||||
var folders = [String]()
|
||||
|
||||
/// New folder name, only used when adding.
|
||||
var newFolder = ""
|
||||
|
||||
/// Index path of the selected folder.
|
||||
var selectedFolderIndexPath = IndexPath(item: 0, section: 0)
|
||||
|
||||
/// Title of the item being shared.
|
||||
var itemTitle: String? = nil
|
||||
|
||||
|
@ -83,6 +95,12 @@ class ShareViewController: UIViewController {
|
|||
}
|
||||
}
|
||||
|
||||
if let foldersArray = prefs.object(forKey: "share:folders") as? [String] {
|
||||
folders = foldersArray
|
||||
|
||||
folders.removeAll { ["river_global", "river_blurblogs", "infrequent", "read_stories", "saved_searches", "saved_stories"].contains($0) }
|
||||
}
|
||||
|
||||
updateSaveButtonState()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)
|
||||
|
@ -90,13 +108,14 @@ class ShareViewController: UIViewController {
|
|||
}
|
||||
|
||||
func updateSaveButtonState() {
|
||||
if mode == .save {
|
||||
switch mode {
|
||||
case .save:
|
||||
if let rows = tableView.indexPathsForSelectedRows {
|
||||
navigationItem.rightBarButtonItem?.isEnabled = !rows.isEmpty
|
||||
} else {
|
||||
navigationItem.rightBarButtonItem?.isEnabled = false
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
navigationItem.rightBarButtonItem?.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +131,7 @@ class ShareViewController: UIViewController {
|
|||
}
|
||||
|
||||
@IBAction func newTagFieldChanged(_ sender: UITextField) {
|
||||
if mode == .save {
|
||||
newTag = sender.text ?? ""
|
||||
|
||||
if newTag.isEmpty {
|
||||
|
@ -119,6 +139,9 @@ class ShareViewController: UIViewController {
|
|||
} else {
|
||||
tableView.selectRow(at: indexPathForNewTag, animated: false, scrollPosition: .none)
|
||||
}
|
||||
} else if mode == .add {
|
||||
newFolder = sender.text ?? ""
|
||||
}
|
||||
|
||||
updateSaveButtonState()
|
||||
}
|
||||
|
@ -154,9 +177,17 @@ class ShareViewController: UIViewController {
|
|||
}
|
||||
|
||||
@IBAction func changedMode(_ sender: Any) {
|
||||
mode = modeSegmentedControl.selectedSegmentIndex == 0 ? .save : .share
|
||||
|
||||
navigationItem.rightBarButtonItem?.title = mode == .save ? "Save" : "Share"
|
||||
switch modeSegmentedControl.selectedSegmentIndex {
|
||||
case 1:
|
||||
mode = .share
|
||||
navigationItem.rightBarButtonItem?.title = "Share"
|
||||
case 2:
|
||||
mode = .add
|
||||
navigationItem.rightBarButtonItem?.title = "Add"
|
||||
default:
|
||||
mode = .save
|
||||
navigationItem.rightBarButtonItem?.title = "Save"
|
||||
}
|
||||
|
||||
tableView.isEditing = mode == .save
|
||||
tableView.reloadData()
|
||||
|
@ -231,20 +262,26 @@ private extension ShareViewController {
|
|||
}
|
||||
|
||||
var requestPath: String {
|
||||
return mode == .save ? "api/save_story" : "api/share_story"
|
||||
switch mode {
|
||||
case .share:
|
||||
return "api/share_story"
|
||||
case .save:
|
||||
return "api/save_story"
|
||||
case .add:
|
||||
return "reader/add_url"
|
||||
}
|
||||
}
|
||||
|
||||
func encoded(_ string: String?) -> String {
|
||||
return string?.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? ""
|
||||
}
|
||||
|
||||
func postBody(url: URL?, text: String?) -> String {
|
||||
func postSave(url: URL?, text: String?) -> String {
|
||||
let title = itemTitle
|
||||
let encodedURL = encoded(url?.absoluteString)
|
||||
let encodedTitle = encoded(title)
|
||||
let encodedContent = encoded(text)
|
||||
|
||||
if mode == .save {
|
||||
let indexPaths = tableView.indexPathsForSelectedRows ?? []
|
||||
var selectedTagsArray = [String]()
|
||||
|
||||
|
@ -260,7 +297,14 @@ private extension ShareViewController {
|
|||
let postBody = "story_url=\(encodedURL)&title=\(encodedTitle)&content=\(encodedContent)&user_tags=\(selectedTags)&add_user_tag=\(encodedNewTag)"
|
||||
|
||||
return postBody
|
||||
} else {
|
||||
}
|
||||
|
||||
func postShare(url: URL?, text: String?) -> String {
|
||||
let title = itemTitle
|
||||
let encodedURL = encoded(url?.absoluteString)
|
||||
let encodedTitle = encoded(title)
|
||||
let encodedContent = encoded(text)
|
||||
|
||||
var comments = comments
|
||||
|
||||
// Don't really need this stuff if I don't populate the comments from the title or text; leave for now just in case that is wanted.
|
||||
|
@ -278,6 +322,30 @@ private extension ShareViewController {
|
|||
|
||||
return postBody
|
||||
}
|
||||
|
||||
func postAdd(url: URL?, text: String?) -> String {
|
||||
let folder = folders[selectedFolderIndexPath.row]
|
||||
let encodedFolder = encoded(folder)
|
||||
let encodedURL = encoded(url?.absoluteString)
|
||||
|
||||
var postBody = "folder=\(encodedFolder)&url=\(encodedURL)"
|
||||
|
||||
if newFolder != "" {
|
||||
postBody += "&new_folder=\(encoded(newFolder))"
|
||||
}
|
||||
|
||||
return postBody
|
||||
}
|
||||
|
||||
func postBody(url: URL?, text: String?) -> String {
|
||||
switch mode {
|
||||
case .save:
|
||||
return postSave(url: url, text: text)
|
||||
case .share:
|
||||
return postShare(url: url, text: text)
|
||||
case .add:
|
||||
return postAdd(url: url, text: text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,11 @@ class ShareViewDelegate: NSObject {
|
|||
|
||||
extension ShareViewDelegate: UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
if viewController.mode == .add, indexPath.section == 0 {
|
||||
viewController.selectedFolderIndexPath = indexPath
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
viewController.updateSaveButtonState()
|
||||
}
|
||||
|
||||
|
@ -23,14 +28,37 @@ extension ShareViewDelegate: UITableViewDelegate {
|
|||
}
|
||||
|
||||
extension ShareViewDelegate: UITableViewDataSource {
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if viewController.mode == .save {
|
||||
return viewController.tags.count + 1
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
if viewController.mode == .add {
|
||||
return 2
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
if viewController.mode == .add, section == 1 {
|
||||
return "Add new sub-folder:"
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
switch viewController.mode {
|
||||
case .save:
|
||||
return viewController.tags.count + 1
|
||||
case .share:
|
||||
return 1
|
||||
case .add:
|
||||
if section == 0 {
|
||||
return viewController.folders.count
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
if viewController.mode == .save {
|
||||
if indexPath.item < viewController.tags.count {
|
||||
|
@ -47,6 +75,34 @@ extension ShareViewDelegate: UITableViewDataSource {
|
|||
}
|
||||
|
||||
cell.tagField.text = ""
|
||||
cell.tagField.placeholder = "new tag"
|
||||
|
||||
return cell
|
||||
}
|
||||
} else if viewController.mode == .add {
|
||||
if indexPath.section == 0 {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveTagCell.reuseIdentifier, for: indexPath) as? ShareSaveTagCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareSaveTagCell")
|
||||
}
|
||||
|
||||
let components = viewController.folders[indexPath.item].components(separatedBy: " ▸ ")
|
||||
|
||||
if components.first == "everything" {
|
||||
cell.tagLabel.text = "🗃 Top Level"
|
||||
} else {
|
||||
cell.tagLabel.text = "\(String(repeating: " ", count: components.count))📁 \(components.last ?? "?")"
|
||||
}
|
||||
|
||||
cell.accessoryType = indexPath == viewController.selectedFolderIndexPath ? .checkmark : .none
|
||||
|
||||
return cell
|
||||
} else {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveNewCell.reuseIdentifier, for: indexPath) as? ShareSaveNewCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareSaveNewCell")
|
||||
}
|
||||
|
||||
cell.tagField.text = viewController.newFolder
|
||||
cell.tagField.placeholder = "new folder title"
|
||||
|
||||
return cell
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue