mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-31 21:41:33 +00:00
#1575 (include a subscribe to site page on the share sheet)
- Now uses NewsBlur icons. - Now posts a user notification indicating success or failure.
This commit is contained in:
parent
0c54797839
commit
06af724619
6 changed files with 173 additions and 58 deletions
|
@ -178,6 +178,10 @@
|
|||
17F39EBA26478538004B46D1 /* content_preview_small@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 17F39EB726478538004B46D1 /* content_preview_small@2x.png */; };
|
||||
17F39EBB26478538004B46D1 /* content_preview_large@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 17F39EB826478538004B46D1 /* content_preview_large@2x.png */; };
|
||||
17FB51D723AC81C500F5D5BF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 17FB51D923AC81C500F5D5BF /* InfoPlist.strings */; };
|
||||
17FF4F7D27DA9645000526E6 /* ShareAddSiteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17FF4F7C27DA9645000526E6 /* ShareAddSiteCell.swift */; };
|
||||
17FF4F7E27DAAA6E000526E6 /* ak-icon-allstories.png in Resources */ = {isa = PBXBuildFile; fileRef = FF85BF7216D6A972002D334D /* ak-icon-allstories.png */; };
|
||||
17FF4F7F27DAAA78000526E6 /* g_icn_folder.png in Resources */ = {isa = PBXBuildFile; fileRef = FFDD847216E887D3000AA0A2 /* g_icn_folder.png */; };
|
||||
17FF4F8027DAAA78000526E6 /* g_icn_folder@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFDD847316E887D3000AA0A2 /* g_icn_folder@2x.png */; };
|
||||
1D3623260D0F684500981E51 /* NewsBlurAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* NewsBlurAppDelegate.m */; };
|
||||
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
|
||||
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
|
||||
|
@ -902,6 +906,7 @@
|
|||
17F39EB726478538004B46D1 /* content_preview_small@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "content_preview_small@2x.png"; sourceTree = "<group>"; };
|
||||
17F39EB826478538004B46D1 /* content_preview_large@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "content_preview_large@2x.png"; sourceTree = "<group>"; };
|
||||
17FB51D823AC81C500F5D5BF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
17FF4F7C27DA9645000526E6 /* ShareAddSiteCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAddSiteCell.swift; sourceTree = "<group>"; };
|
||||
1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
1D3623240D0F684500981E51 /* NewsBlurAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = NewsBlurAppDelegate.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
1D3623250D0F684500981E51 /* NewsBlurAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = NewsBlurAppDelegate.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
|
||||
|
@ -1694,6 +1699,7 @@
|
|||
17DC7CCD26A5212000B0E747 /* ShareSaveTagCell.swift */,
|
||||
17DC7CCF26A5218000B0E747 /* ShareSaveNewCell.swift */,
|
||||
17DC7CD126A521A300B0E747 /* ShareCommentCell.swift */,
|
||||
17FF4F7C27DA9645000526E6 /* ShareAddSiteCell.swift */,
|
||||
174939151C251BFE003D98AA /* MainInterface.storyboard */,
|
||||
174939211C251E43003D98AA /* Share Extension.entitlements */,
|
||||
174939181C251BFE003D98AA /* Info.plist */,
|
||||
|
@ -3080,7 +3086,10 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
17FF4F7F27DAAA78000526E6 /* g_icn_folder.png in Resources */,
|
||||
17FF4F7E27DAAA6E000526E6 /* ak-icon-allstories.png in Resources */,
|
||||
174939171C251BFE003D98AA /* MainInterface.storyboard in Resources */,
|
||||
17FF4F8027DAAA78000526E6 /* g_icn_folder@2x.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -3563,6 +3572,7 @@
|
|||
files = (
|
||||
17DC7CD026A5218000B0E747 /* ShareSaveNewCell.swift in Sources */,
|
||||
17DC7CCA26A51BB600B0E747 /* ShareViewController.swift in Sources */,
|
||||
17FF4F7D27DA9645000526E6 /* ShareAddSiteCell.swift in Sources */,
|
||||
17DC7CCE26A5212000B0E747 /* ShareSaveTagCell.swift in Sources */,
|
||||
17DC7CCC26A51E6300B0E747 /* ShareViewDelegate.swift in Sources */,
|
||||
17DC7CD226A521A300B0E747 /* ShareCommentCell.swift in Sources */,
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<objects>
|
||||
<viewController storyboardIdentifier="DetailViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="djW-7k-haK" customClass="DetailViewController" customModule="NewsBlur" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jTZ-4O-xyT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1194" height="834"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="818.5" height="834"/>
|
||||
<subviews>
|
||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bPa-u1-Aml">
|
||||
<rect key="frame" x="0.0" y="74" width="1194" height="580"/>
|
||||
|
|
|
@ -154,6 +154,41 @@
|
|||
<outlet property="commentTextView" destination="mfP-7f-Dq0" id="AoJ-DT-f8q"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="ShareAddSiteCell" id="Sdh-Hi-VKN" customClass="ShareAddSiteCell" customModule="Share_Extension" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="383.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="Sdh-Hi-VKN" id="gap-sb-A4d">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="87l-vo-Aqu">
|
||||
<rect key="frame" x="20" y="9.5" width="25" height="25"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="25" id="PdC-PQ-ClF"/>
|
||||
<constraint firstAttribute="height" constant="25" id="VdN-R3-r0z"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="enG-2W-uUc">
|
||||
<rect key="frame" x="53" y="11.5" width="41.5" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="enG-2W-uUc" secondAttribute="trailing" constant="20" symbolic="YES" id="6iv-Qq-MBb"/>
|
||||
<constraint firstItem="87l-vo-Aqu" firstAttribute="centerY" secondItem="gap-sb-A4d" secondAttribute="centerY" id="PxG-wV-eFZ"/>
|
||||
<constraint firstItem="enG-2W-uUc" firstAttribute="leading" secondItem="87l-vo-Aqu" secondAttribute="trailing" constant="8" symbolic="YES" id="ZId-aw-V6W"/>
|
||||
<constraint firstItem="87l-vo-Aqu" firstAttribute="leading" secondItem="gap-sb-A4d" secondAttribute="leading" constant="20" symbolic="YES" id="emx-Ou-ppO"/>
|
||||
<constraint firstItem="enG-2W-uUc" firstAttribute="centerY" secondItem="gap-sb-A4d" secondAttribute="centerY" id="vq0-II-4Lp"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="folderImageLeadingConstraint" destination="emx-Ou-ppO" id="1cu-W4-kwz"/>
|
||||
<outlet property="folderImageView" destination="87l-vo-Aqu" id="fg6-9H-E5C"/>
|
||||
<outlet property="folderLabel" destination="enG-2W-uUc" id="O4Y-ka-c1D"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="96H-cS-CLZ" id="puZ-kH-xg9"/>
|
||||
|
|
20
clients/ios/Share Extension/ShareAddSiteCell.swift
Normal file
20
clients/ios/Share Extension/ShareAddSiteCell.swift
Normal file
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// ShareAddSiteCell.swift
|
||||
// Share Extension
|
||||
//
|
||||
// Created by David Sinclair on 2022-03-10.
|
||||
// Copyright © 2022 NewsBlur. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ShareAddSiteCell: UITableViewCell {
|
||||
@IBOutlet weak var folderImageView: UIImageView!
|
||||
|
||||
@IBOutlet weak var folderLabel: UILabel!
|
||||
|
||||
@IBOutlet weak var folderImageLeadingConstraint: NSLayoutConstraint!
|
||||
|
||||
/// The reuse identifier for this table view cell.
|
||||
static let reuseIdentifier = "ShareAddSiteCell"
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
import MobileCoreServices
|
||||
import UserNotifications
|
||||
|
||||
class ShareViewController: UIViewController {
|
||||
@IBOutlet var delegate: ShareViewDelegate!
|
||||
|
@ -98,7 +99,7 @@ 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) }
|
||||
folders.removeAll { ["river_global", "river_blurblogs", "infrequent", "widget_stories", "read_stories", "saved_searches", "saved_stories"].contains($0) }
|
||||
}
|
||||
|
||||
updateSaveButtonState()
|
||||
|
@ -351,10 +352,46 @@ private extension ShareViewController {
|
|||
|
||||
extension ShareViewController: URLSessionTaskDelegate {
|
||||
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||
let content = UNMutableNotificationContent()
|
||||
|
||||
content.title = "NewsBlur"
|
||||
|
||||
if let error = error {
|
||||
print("task completed with error: \(error)")
|
||||
|
||||
switch mode {
|
||||
case .save:
|
||||
content.body = "Unable to save this story"
|
||||
case .share:
|
||||
content.body = "Unable to share this story"
|
||||
case .add:
|
||||
content.body = "Unable to add this site"
|
||||
}
|
||||
} else {
|
||||
print("task completed successfully")
|
||||
print("task completed successfully: \(String(describing: task.response))")
|
||||
|
||||
NSLog("⚾️ share: \(String(describing: task.response))")
|
||||
|
||||
switch mode {
|
||||
case .save:
|
||||
content.body = "Saved this story"
|
||||
case .share:
|
||||
content.body = "Shared this story"
|
||||
case .add:
|
||||
content.body = "Added this site"
|
||||
}
|
||||
}
|
||||
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
|
||||
let uuidString = UUID().uuidString
|
||||
let request = UNNotificationRequest(identifier: uuidString,
|
||||
content: content, trigger: trigger)
|
||||
let notificationCenter = UNUserNotificationCenter.current()
|
||||
|
||||
notificationCenter.add(request) { (error) in
|
||||
if let error = error {
|
||||
print("notification error: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,72 +62,85 @@ extension ShareViewDelegate: UITableViewDataSource {
|
|||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
if viewController.mode == .save {
|
||||
if indexPath.item < viewController.tags.count {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveTagCell.reuseIdentifier, for: indexPath) as? ShareSaveTagCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareSaveTagCell")
|
||||
}
|
||||
|
||||
let tag = viewController.tags[indexPath.item]
|
||||
|
||||
cell.tagLabel.text = tag.name
|
||||
cell.countLabel.text = "\(tag.count)"
|
||||
|
||||
return cell
|
||||
return makeSaveTagCell(for: tableView, indexPath: indexPath)
|
||||
} else {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveNewCell.reuseIdentifier, for: indexPath) as? ShareSaveNewCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareSaveNewCell")
|
||||
}
|
||||
|
||||
cell.tagField.text = ""
|
||||
cell.tagField.placeholder = "new tag"
|
||||
|
||||
return cell
|
||||
return makeSaveNewCell(for: tableView, indexPath: indexPath, name: "", placeholder: "new tag")
|
||||
}
|
||||
} 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: " ▸ ")
|
||||
|
||||
cell.countLabel.text = ""
|
||||
|
||||
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
|
||||
return makeAddSiteCell(for: tableView, indexPath: indexPath)
|
||||
} 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
|
||||
return makeSaveNewCell(for: tableView, indexPath: indexPath, name: viewController.newFolder, placeholder: "new tag")
|
||||
}
|
||||
} else {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareCommentCell.reuseIdentifier, for: indexPath) as? ShareCommentCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareCommentCell")
|
||||
}
|
||||
|
||||
cell.commentTextView.text = ""
|
||||
cell.commentTextView.delegate = self
|
||||
|
||||
DispatchQueue.main.async {
|
||||
cell.commentTextView.becomeFirstResponder()
|
||||
}
|
||||
|
||||
return cell
|
||||
return makeShareCommentCell(for: tableView, indexPath: indexPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension ShareViewDelegate {
|
||||
func makeSaveTagCell(for tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveTagCell.reuseIdentifier, for: indexPath) as? ShareSaveTagCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareSaveTagCell")
|
||||
}
|
||||
|
||||
let tag = viewController.tags[indexPath.item]
|
||||
|
||||
cell.tagLabel.text = tag.name
|
||||
cell.countLabel.text = "\(tag.count)"
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
func makeSaveNewCell(for tableView: UITableView, indexPath: IndexPath, name: String, placeholder: String) -> UITableViewCell {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveNewCell.reuseIdentifier, for: indexPath) as? ShareSaveNewCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareSaveNewCell")
|
||||
}
|
||||
|
||||
cell.tagField.text = name
|
||||
cell.tagField.placeholder = placeholder
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
func makeAddSiteCell(for tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareAddSiteCell.reuseIdentifier, for: indexPath) as? ShareAddSiteCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareAddSiteCell")
|
||||
}
|
||||
|
||||
let components = viewController.folders[indexPath.item].components(separatedBy: " ▸ ")
|
||||
|
||||
if components.first == "everything" {
|
||||
cell.folderImageView.image = UIImage(named: "ak-icon-allstories.png")
|
||||
cell.folderLabel.text = "Top Level"
|
||||
cell.folderImageLeadingConstraint.constant = 20
|
||||
} else {
|
||||
cell.folderImageView.image = UIImage(named: "g_icn_folder.png")
|
||||
cell.folderLabel.text = components.last ?? "?"
|
||||
cell.folderImageLeadingConstraint.constant = 20 + CGFloat(components.count * 35)
|
||||
}
|
||||
|
||||
cell.accessoryType = indexPath == viewController.selectedFolderIndexPath ? .checkmark : .none
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
func makeShareCommentCell(for tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareCommentCell.reuseIdentifier, for: indexPath) as? ShareCommentCell else {
|
||||
preconditionFailure("Expected to dequeue a ShareCommentCell")
|
||||
}
|
||||
|
||||
cell.commentTextView.text = ""
|
||||
cell.commentTextView.delegate = self
|
||||
|
||||
DispatchQueue.main.async {
|
||||
cell.commentTextView.becomeFirstResponder()
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
extension ShareViewDelegate: UITextViewDelegate {
|
||||
func textViewDidChange(_ textView: UITextView) {
|
||||
viewController.comments = textView.text
|
||||
|
|
Loading…
Add table
Reference in a new issue