Skip to content
This repository was archived by the owner on Feb 15, 2022. It is now read-only.

Commit c2f0811

Browse files
committed
2 parents f2aa266 + 6bbb259 commit c2f0811

File tree

18 files changed

+648
-428
lines changed

18 files changed

+648
-428
lines changed

Example/PinpointKitExample.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@
357357
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
358358
INFOPLIST_FILE = PinpointKitExample/Info.plist;
359359
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
360-
MARKETING_VERSION = 1.4.0;
360+
MARKETING_VERSION = 1.5.0;
361361
PRODUCT_BUNDLE_IDENTIFIER = net.Lickability.PinpointKitExample;
362362
PRODUCT_NAME = "$(TARGET_NAME)";
363363
};
@@ -370,7 +370,7 @@
370370
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
371371
INFOPLIST_FILE = PinpointKitExample/Info.plist;
372372
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
373-
MARKETING_VERSION = 1.4.0;
373+
MARKETING_VERSION = 1.5.0;
374374
PRODUCT_BUNDLE_IDENTIFIER = net.Lickability.PinpointKitExample;
375375
PRODUCT_NAME = "$(TARGET_NAME)";
376376
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";

Example/PinpointKitExample/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
<string>UIInterfaceOrientationLandscapeLeft</string>
3737
<string>UIInterfaceOrientationLandscapeRight</string>
3838
</array>
39+
<key>NSPhotoLibraryUsageDescription</key>
40+
<string>The example application accesses your photo library.</string>
3941
<key>UISupportedInterfaceOrientations~ipad</key>
4042
<array>
4143
<string>UIInterfaceOrientationPortrait</string>

Example/Podfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PODS:
2-
- PinpointKit (1.4.0):
3-
- PinpointKit/Core (= 1.4.0)
4-
- PinpointKit/Core (1.4.0)
2+
- PinpointKit (1.5.0):
3+
- PinpointKit/Core (= 1.5.0)
4+
- PinpointKit/Core (1.5.0)
55
- SwiftLint (0.25.1)
66

77
DEPENDENCIES:
@@ -17,7 +17,7 @@ EXTERNAL SOURCES:
1717
:path: "../"
1818

1919
SPEC CHECKSUMS:
20-
PinpointKit: a33c929c2e9c3b7d9a1a343fd309161b71c02d06
20+
PinpointKit: a513c4623502581067f3f8b60b9cffef6c8e1025
2121
SwiftLint: ce933681be10c3266e82576dad676fa815a602e9
2222

2323
PODFILE CHECKSUM: 24af8a2ca63352a72ca1cd13fc8977477eae3a12

Example/Pods/Local Podspecs/PinpointKit.podspec.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Example/Pods/Manifest.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Example/Pods/Pods.xcodeproj/project.pbxproj

Lines changed: 381 additions & 377 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Example/Pods/Target Support Files/PinpointKit/Info.plist

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

PinpointKit.podspec.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "PinpointKit",
3-
"version": "1.4.0",
3+
"version": "1.5.0",
44
"homepage": "https://github.com/Lickability/PinpointKit",
55
"source": {
66
"git": "https://github.com/Lickability/PinpointKit.git",
7-
"tag": "1.4.0"
7+
"tag": "1.5.0"
88
},
99
"summary": "A library that makes bug reporting simple for your users by allowing them to send feedback with annotated screenshots and logs.",
1010
"authors" : {

PinpointKit/PinpointKit.xcodeproj/project.pbxproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
DA0DA60D1C53049B0012ADBE /* PinpointKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0DA6021C53049B0012ADBE /* PinpointKit.framework */; };
7171
F24381121D54CBAB004CC87F /* SystemLogCollectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24381111D54CBAB004CC87F /* SystemLogCollectorTests.swift */; };
7272
F24381151D54ECD2004CC87F /* XCTestCaseExpectationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24381141D54ECD2004CC87F /* XCTestCaseExpectationExtensions.swift */; };
73+
F2619BA32512C6100083286C /* RequestScreenshotCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2619BA22512C6100083286C /* RequestScreenshotCell.swift */; };
7374
/* End PBXBuildFile section */
7475

7576
/* Begin PBXContainerItemProxy section */
@@ -147,6 +148,7 @@
147148
DA0DA6131C53049B0012ADBE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
148149
F24381111D54CBAB004CC87F /* SystemLogCollectorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemLogCollectorTests.swift; sourceTree = "<group>"; };
149150
F24381141D54ECD2004CC87F /* XCTestCaseExpectationExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestCaseExpectationExtensions.swift; sourceTree = "<group>"; };
151+
F2619BA22512C6100083286C /* RequestScreenshotCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RequestScreenshotCell.swift; path = Core/RequestScreenshotCell.swift; sourceTree = "<group>"; };
150152
/* End PBXFileReference section */
151153

152154
/* Begin PBXFrameworksBuildPhase section */
@@ -206,6 +208,7 @@
206208
4C4037F11D9EB01800305A6E /* FeedbackViewController.swift */,
207209
4C4037EF1D9EB01800305A6E /* FeedbackNavigationController.swift */,
208210
4C4037FC1D9EB04400305A6E /* Screenshotter.swift */,
211+
F2619BA22512C6100083286C /* RequestScreenshotCell.swift */,
209212
4C4037F91D9EB02300305A6E /* ScreenshotCell.swift */,
210213
4C4037EE1D9EB01800305A6E /* FeedbackConfiguration.swift */,
211214
4C4037F01D9EB01800305A6E /* FeedbackTableViewDataSource.swift */,
@@ -490,6 +493,7 @@
490493
4C4038091D9EB0CB00305A6E /* UIView+PinpointKit.swift in Sources */,
491494
4CFB58801E29464B00B64D0D /* EditImageViewControllerBarButtonItemProviding.swift in Sources */,
492495
4C40382C1D9EB7A800305A6E /* ScreenshotDetector.swift in Sources */,
496+
F2619BA32512C6100083286C /* RequestScreenshotCell.swift in Sources */,
493497
4C4038011D9EB07000305A6E /* LogViewer.swift in Sources */,
494498
4C4037FF1D9EB06900305A6E /* BasicLogViewController.swift in Sources */,
495499
4C4037D51D9EAF0D00305A6E /* Editor.swift in Sources */,
@@ -686,7 +690,7 @@
686690
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
687691
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
688692
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
689-
MARKETING_VERSION = 1.4.0;
693+
MARKETING_VERSION = 1.5.0;
690694
PRODUCT_BUNDLE_IDENTIFIER = net.Lickability.PinpointKit;
691695
PRODUCT_NAME = "$(TARGET_NAME)";
692696
SKIP_INSTALL = YES;
@@ -709,7 +713,7 @@
709713
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
710714
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
711715
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
712-
MARKETING_VERSION = 1.4.0;
716+
MARKETING_VERSION = 1.5.0;
713717
PRODUCT_BUNDLE_IDENTIFIER = net.Lickability.PinpointKit;
714718
PRODUCT_NAME = "$(TARGET_NAME)";
715719
SKIP_INSTALL = YES;

PinpointKit/PinpointKit/Sources/Core/FeedbackCollector.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ public protocol FeedbackCollector: class, LogSupporting, InterfaceCustomizable {
2424
/**
2525
Begins feedback collection about a screenshot from a view controller.
2626

27-
- parameter screenshot: The screenshot the user will be providing feedback on.
27+
- parameter screenshot: The screenshot the user will be providing feedback on. If the screenshot is nil, the user will be presented with a button to select a screenshot from their photo library.
2828
- parameter viewController: The view controller from which to present.
2929
*/
30-
func collectFeedback(with screenshot: UIImage, from viewController: UIViewController)
30+
func collectFeedback(with screenshot: UIImage?, from viewController: UIViewController)
3131
}
3232

3333
extension FeedbackCollector where Self: UIViewController {

PinpointKit/PinpointKit/Sources/Core/FeedbackNavigationController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ public final class FeedbackNavigationController: UINavigationController, Feedbac
114114

115115
// MARK: - FeedbackCollector
116116

117-
public func collectFeedback(with screenshot: UIImage, from viewController: UIViewController) {
117+
public func collectFeedback(with screenshot: UIImage?, from viewController: UIViewController) {
118118
guard presentingViewController == nil else {
119-
NSLog("Unable to present FeedbackNavigationController because it is already being presetned")
119+
NSLog("Unable to present FeedbackNavigationController because it is already being presented")
120120
return
121121
}
122122

PinpointKit/PinpointKit/Sources/Core/FeedbackTableViewDataSource.swift

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ final class FeedbackTableViewDataSource: NSObject, UITableViewDataSource {
1818
Initializes the data source with a configuration and a boolean value indicating whether the user has enabled log collection.
1919

2020
- parameter interfaceCustomization: The interface customization used to set up the data source.
21-
- parameter screenshot: The screenshot to display for annotating.
21+
- parameter screenshot: The screenshot to display for annotating. If nil, a button will appear allowing the user to select a screenshot.
2222
- parameter logSupporting: The object the controls the support of logging.
2323
- parameter userEnabledLogCollection: A boolean value indicating whether the user has enabled log collection.
2424
- parameter delegate: The object informed when a screenshot is tapped.
2525
*/
26-
init(interfaceCustomization: InterfaceCustomization, screenshot: UIImage, logSupporting: LogSupporting, userEnabledLogCollection: Bool, delegate: FeedbackTableViewDataSourceDelegate? = nil) {
26+
init(interfaceCustomization: InterfaceCustomization, screenshot: UIImage?, logSupporting: LogSupporting, userEnabledLogCollection: Bool, delegate: FeedbackTableViewDataSourceDelegate? = nil) {
2727
sections = type(of: self).sectionsFromConfiguration(interfaceCustomization, screenshot: screenshot, logSupporting: logSupporting, userEnabledLogCollection: userEnabledLogCollection)
2828
self.delegate = delegate
2929
}
@@ -40,19 +40,28 @@ final class FeedbackTableViewDataSource: NSObject, UITableViewDataSource {
4040
}
4141

4242
private enum Row {
43+
case selectScreenshot(text: String, font: UIFont)
4344
case screenshot(screensot: UIImage, hintText: String?, hintFont: UIFont)
4445
case collectLogs(enabled: Bool, title: String, font: UIFont, canView: Bool)
4546
}
4647

4748
// MARK: - FeedbackTableViewDataSource
4849

49-
private static func sectionsFromConfiguration(_ interfaceCustomization: InterfaceCustomization, screenshot: UIImage, logSupporting: LogSupporting, userEnabledLogCollection: Bool) -> [Section] {
50+
private static func sectionsFromConfiguration(_ interfaceCustomization: InterfaceCustomization, screenshot: UIImage?, logSupporting: LogSupporting, userEnabledLogCollection: Bool) -> [Section] {
5051
var sections: [Section] = []
5152

52-
let screenshotRow = Row.screenshot(screensot: screenshot, hintText: interfaceCustomization.interfaceText.feedbackEditHint, hintFont: interfaceCustomization.appearance.feedbackEditHintFont)
53-
let screenshotSection = Section.feedback(rows: [screenshotRow])
54-
55-
sections.append(screenshotSection)
53+
if let screenshot = screenshot {
54+
let screenshotRow = Row.screenshot(screensot: screenshot, hintText: interfaceCustomization.interfaceText.feedbackEditHint, hintFont: interfaceCustomization.appearance.feedbackEditHintFont)
55+
let screenshotSection = Section.feedback(rows: [screenshotRow])
56+
57+
sections.append(screenshotSection)
58+
} else {
59+
let requestScreenshotRow = Row.selectScreenshot(text: interfaceCustomization.interfaceText.selectScreenshotButtonTitle, font: interfaceCustomization.appearance.selectScreenshotButtonFont)
60+
61+
let screenshotSection = Section.feedback(rows: [requestScreenshotRow])
62+
63+
sections.append(screenshotSection)
64+
}
5665

5766
if logSupporting.logCollector != nil {
5867
let collectLogsRow = Row.collectLogs(enabled: userEnabledLogCollection, title: interfaceCustomization.interfaceText.logCollectionPermissionTitle, font: interfaceCustomization.appearance.logCollectionPermissionFont, canView: logSupporting.logViewer != nil)
@@ -98,6 +107,26 @@ final class FeedbackTableViewDataSource: NSObject, UITableViewDataSource {
98107
return cell
99108
}
100109

110+
private func requestScreenshotCell(for row: Row) -> UITableViewCell {
111+
let cell = RequestScreenshotCell()
112+
113+
guard case let .selectScreenshot(text, font) = row else {
114+
assertionFailure("Found unexpected row type when creating screenshot cell.")
115+
return cell
116+
}
117+
118+
cell.viewModel = RequestScreenshotCell.ViewModel(buttonText: text, buttonFont: font)
119+
cell.screenshotButtonTapHandler = { [weak self] _ in
120+
guard let self = self else { return }
121+
122+
if #available(iOS 14, *) {
123+
self.delegate?.feedbackTableViewDataSourceDidRequestScreenshot(feedbackTableViewDataSource: self)
124+
}
125+
}
126+
127+
return cell
128+
}
129+
101130
// MARK: - UITableViewDataSource
102131

103132
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
@@ -115,6 +144,8 @@ final class FeedbackTableViewDataSource: NSObject, UITableViewDataSource {
115144
case let .feedback(rows):
116145
let row = rows[indexPath.row]
117146
switch row {
147+
case .selectScreenshot:
148+
return requestScreenshotCell(for: row)
118149
case .screenshot:
119150
return screenshotCell(for: row)
120151
case .collectLogs:
@@ -134,4 +165,12 @@ protocol FeedbackTableViewDataSourceDelegate: class {
134165
- parameter screenshot: The screenshot that was tapped.
135166
*/
136167
func feedbackTableViewDataSource(feedbackTableViewDataSource: FeedbackTableViewDataSource, didTapScreenshot screenshot: UIImage)
168+
169+
/**
170+
Notifies the delegate that a screenshot is being requested.
171+
172+
- parameter feedbackTableViewDataSource: The feedback table view data source that sent the message.
173+
*/
174+
@available(iOS 14, *)
175+
func feedbackTableViewDataSourceDidRequestScreenshot(feedbackTableViewDataSource: FeedbackTableViewDataSource)
137176
}

PinpointKit/PinpointKit/Sources/Core/FeedbackViewController.swift

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
import UIKit
10+
import PhotosUI
1011

1112
/// A `UITableViewController` that conforms to `FeedbackCollector` in order to display an interface that allows the user to see, change, and send feedback.
1213
public final class FeedbackViewController: UITableViewController {
@@ -108,7 +109,6 @@ public final class FeedbackViewController: UITableViewController {
108109

109110
private func updateDataSource() {
110111
guard let interfaceCustomization = interfaceCustomization else { assertionFailure(); return }
111-
guard let screenshot = screenshot else { assertionFailure(); return }
112112
let screenshotToDisplay = annotatedScreenshot ?? screenshot
113113

114114
dataSource = FeedbackTableViewDataSource(interfaceCustomization: interfaceCustomization, screenshot: screenshotToDisplay, logSupporting: self, userEnabledLogCollection: userEnabledLogCollection, delegate: self)
@@ -190,7 +190,7 @@ public final class FeedbackViewController: UITableViewController {
190190
// MARK: - FeedbackCollector
191191

192192
extension FeedbackViewController: FeedbackCollector {
193-
public func collectFeedback(with screenshot: UIImage, from viewController: UIViewController) {
193+
public func collectFeedback(with screenshot: UIImage?, from viewController: UIViewController) {
194194
self.screenshot = screenshot
195195
annotatedScreenshot = nil
196196
viewController.showDetailViewController(self, sender: viewController)
@@ -249,4 +249,38 @@ extension FeedbackViewController: FeedbackTableViewDataSourceDelegate {
249249
editImageViewController.modalPresentationStyle = feedbackConfiguration?.presentationStyle ?? .fullScreen
250250
present(editImageViewController, animated: true, completion: nil)
251251
}
252+
253+
@available(iOS 14, *)
254+
func feedbackTableViewDataSourceDidRequestScreenshot(feedbackTableViewDataSource: FeedbackTableViewDataSource) {
255+
var configuration = PHPickerConfiguration(photoLibrary: .shared())
256+
configuration.filter = .images
257+
258+
let pickerController = PHPickerViewController(configuration: configuration)
259+
pickerController.delegate = self
260+
viewController.present(pickerController, animated: true, completion: nil)
261+
}
262+
}
263+
264+
@available(iOS 14, *)
265+
extension FeedbackViewController: PHPickerViewControllerDelegate {
266+
267+
public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
268+
guard let result = results.first else {
269+
picker.presentingViewController?.dismiss(animated: true)
270+
return
271+
}
272+
273+
result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: { image, _ in
274+
OperationQueue.main.addOperation {
275+
defer {
276+
picker.presentingViewController?.dismiss(animated: true)
277+
}
278+
279+
guard let image = image as? UIImage else { return }
280+
self.screenshot = image
281+
282+
self.tableView.reloadData()
283+
}
284+
})
285+
}
252286
}

0 commit comments

Comments
 (0)