gabek / gityourfeedback Goto Github PK
View Code? Open in Web Editor NEWLet users submit feedback, with screenshots, directly from your iOS app to Github Issues
License: MIT License
Let users submit feedback, with screenshots, directly from your iOS app to Github Issues
License: MIT License
Right now we have three icons for add, close and save. They are a single resolution, and they don't look great as they don't have a style that matches. Plus I stole them from Google images.
These are the three icons:
https://github.com/gabek/GitYourFeedback/tree/master/GitYourFeedback/Assets
If anybody has any resources or artistic skills feel free to reply with any suggestions and then a PR can be created to replace them.
Anybody have any API suggestions before it gets locked in? Currently there's a FeedbackManagerDatasource
protocol that has
func uploadUrl(_ completionHandler: (String) -> Void)
func additionalData() -> String?
The init for FeedbackManager is
init(githubApiToken: String, githubUser: String, repo: String, feedbackRemoteStorageDelegate: FeedbackManagerDatasource, issueLabels: [String]?)
And to manually display the feedback interface it's
feedbackManager.display()
with an optional view controller to display it from.
Is this clear and optimal?
This makes error handling a little more shaky. If we dismiss the UI and something fails we could alert the user that it failed, but the interface would be gone. Do we re-show it? Or maybe ask them if they want to re-submit?
This should bubble up an error in some way. Probably a simple popup stating that the feedback could not be submitted.
I've never used Carthage so I dunno.
If a screenshot is not auto-attached the button should indicate to the user they can hit it in order to attach a screenshot.
No need to have both screens when you can view the screenshot in the editor.
Some useful datapoints that could be provided with this:
The FeedbackManager knows how the UI's ViewController was presented, so it shouldn't try and populate the screenshot unless it was presented due to a screenshot being taken. The image button should instead default to an "Add Screenshot" state.
So a completely empty piece of feedback cannot be submitted. I guess the title and email should be required, but the body and screenshot are optional.
Used Luminous as an inspiration for some additional data points that would be useful to send along with an issue. Pointed to their implementations where it makes sense.
https://github.com/gabek/GitYourFeedback/blob/master/GitYourFeedback/Classes/Helpers.swift#L29
The feedback UI just will not get displayed.
When uploading photo to Firebase Bucket, URL Error 401 is shown. Seems like it has some authorization issue. What to do, non of this two url does not work?
let url = "https://storage.googleapis.com/upload/storage/v1/b/\(Config.googleStorageBucket)/o?name=\(filename)"
let url = "https://www.googleapis.com/upload/storage/v1/b/\(Config.googleStorageBucket)/o?name=\(filename)"
@erinstandley reports:
Feedback gets cut off and typing behaves oddly when you fill in more than 6lines
Since it's required this should be passed in.
This protocol should be used for all user-supplied data, not for just supplying a URL to upload the screenshot to.
This seems to be an iOS bug. If you present
a VC from a UIAlertController
it actually repositions the alert controller, breaking it. When you leave the feedback UI you find the last screen you were on in a broken state.
Why are we presenting from a UIAlertController
at all, you ask? We present from whatever the topmost view controller is, in order for the Feedback UI to get displayed. It doesn't know, nor care, that it's an alert controller specifically.
I wonder if there's a presentation context tweak that can be done to fix this, or something?
To support
Probably use this? https://github.com/yackle/CLImageEditor
The Readme and web page (docs directory) needs to reflect the current state of v0.1.0 just before release. This is mostly to make sure the installation/usage instructions are correct.
This should bubble up an error in some way. Probably a simple popup stating that the upload could not complete, but the feedback was still sent successfully, just without a screenshot.
We should be able to use S3 or Google Cloud for storage.
We could just make it completely storage agnostic, but that would remove some of the convenience of this tool.
If a screenshot is attached tapping the button should give users options of what to do:
For v0.1.1
There are a lot of details included in every feedback entry. We should be able to collapse them
And put all the content inside it.
It's not closable once it's opened currently, you're forced to perform one of the actions.
Feedback from user:
after I added an attachment, and was typing a longer report, it wrapped and unwrapped text awkwardly trying to resize the text box.
it resized as I typed, growing and shrinking. erratically.
Since this is required, we need to force its usage.
So it doesn't have to be created by the user if they don't want something special.
@erinstandley reports
if you take a screenshot, it opens the feedback screen. then take a screenshot of that, it opens a new instance. and so on.
assuming it should not open a new instance
And this is a good catch! It should not be able to be opened multiple times times.
It was reported that image permissions were disabled for the app and they didn't get a permissions popup.
I think it's a timing issue. The screenshot is probably not saved to the image library before handleScreenshot
is fired. Hopefully there's some callback or notification that can let us know that the screenshot has not just been taken, but also successfully saved.
Throw some screenshots, features, and installation directions on there.
Here's what Apple's TestFlight supplies:
App Information:
App Name: Appname
App Version: 1.0 (105)
Installed App Version: 1.0 (105)
Device Information:
Device: iPhone9,3
iOS Version: 10.0.1
Language: en-US (English (United States))
Carrier: AT&T
Timezone: PDT
Architecture: N/A
Connection Status: WiFi
Paired Apple Watch: Apple Watch - Watch OS 3.0 (14S326)
-;function signature specialization of GitYourFeedback.FeedbackInterfaceViewController.((handleScreenshot in _761961F56A18DE3F18D6C8C18AA32A2D) () -> ()).(closure #1);FeedbackViewController.swift;0 -;partial apply forwarder for GitYourFeedback.FeedbackInterfaceViewController.((handleScreenshot in _761961F56A18DE3F18D6C8C18AA32A2D) () -> ()).(closure #1);FeedbackViewController.swift;0
objc_msgSend() selector name: configureAnimation:forLayer:forKey:
Application Specific Information:
objc_msgSend() selector name: configureAnimation:forLayer:forKey:
Thread 0:
0 libsystem_kernel.dylib 0x000000018af0e8e8 __ulock_wait + 8
1 QuartzCore 0x000000018f2461f8 -[CALayer frame] + 40
2 UIKit 0x0000000191d80e74 -[UIView(Geometry) frame] + 120
3 UIKit 0x0000000191d81db0 -[UIView(Geometry) setFrame:] + 656
4 UIKit 0x0000000191d95acc -[UIImageView _setViewGeometry:forMetric:] + 176
5 UIKit 0x0000000191dddba0 -[UIButton layoutSubviews] + 204
6 UIKit 0x0000000191e49308 -[UINavigationButton layoutSubviews] + 64
7 UIKit 0x0000000191d85738 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1192
8 QuartzCore 0x000000018f24e40c -[CALayer layoutSublayers] + 144
9 QuartzCore 0x000000018f2430e8 CA::Layer::layout_if_needed(CA::Transaction*) + 288
10 UIKit 0x0000000191d9a1a8 -[UIView(Hierarchy) layoutBelowIfNeeded] + 1016
11 UIKit 0x0000000191e1d8c4 -[UINavigationBar setCenter:] + 108
12 UIKit 0x0000000191e1d4bc -[UINavigationController _positionTopBar:hidden:edge:center:offset:] + 236
13 UIKit 0x0000000191e1d0ac -[UINavigationController _positionNavigationBarHidden:edge:initialOffset:] + 572
14 UIKit 0x0000000191e1cddc -[UINavigationController _positionNavigationBarHidden:edge:] + 392
15 UIKit 0x0000000191e3eb58 -[UINavigationController _updateBarsForCurrentInterfaceOrientation] + 40
16 UIKit 0x0000000191e04f44 -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] + 936
17 UIKit 0x0000000191e3e928 -[UINavigationController viewDidMoveToWindow:shouldAppearOrDisappear:] + 92
18 UIKit 0x0000000191d84d48 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1348
19 UIKit 0x0000000191d83f7c __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 152
20 Foundation 0x000000018c96c510 -[NSISEngine withBehaviors:performModifications:] + 164
21 UIKit 0x0000000191d83df0 -[UIView(Hierarchy) _postMovedFromSuperview:] + 816
22 UIKit 0x0000000191d8fcbc -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1784
23 UIKit 0x0000000191d8f5a8 -[UIView(Hierarchy) addSubview:] + 824
24 UIKit 0x0000000191e81a80 -[UITransitionView transition:fromView:toView:removeFromView:] + 1468
25 UIKit 0x0000000191e80fa4 -[UIViewControllerBuiltinTransitionViewAnimator animateTransition:] + 1628
26 UIKit 0x00000001920d6ed0 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 2468
27 UIKit 0x000000019201a264 _runAfterCACommitDeferredBlocks + 288
28 UIKit 0x000000019200c018 _cleanUpAfterCAFlushAndRunDeferredBlocks + 556
29 UIKit 0x0000000191d7ad6c _afterCACommitHandler + 164
30 CoreFoundation 0x000000018beed7dc __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 28
31 CoreFoundation 0x000000018beeb40c __CFRunLoopDoObservers + 368
32 CoreFoundation 0x000000018beeb89c __CFRunLoopRun + 1020
33 CoreFoundation 0x000000018be1a048 CFRunLoopRunSpecific + 440
34 GraphicsServices 0x000000018d89d198 GSEventRunModal + 176
It doesn't need to be a 1:1 representation of the screen. It's a little too big.
Before cutting our first release I'd love to see a couple people try it in their own apps! This way any issues can be surfaced and the Readme can be polished up with real integration steps.
How can you help?
To install it, simply add the following line to your Podfile:
pod 'GitYourFeedback', :git => 'https://github.com/gabek/GitYourFeedback'
Or, if you’re using Carthage, add GitYourFeedback to your Cartfile:
github "gabek/GitYourFeedback"
Info.plist
add a key of NSPhotoLibraryUsageDescription
with a string explaining that your use of the photo library is for submitting screenshots. This is user-facing so use your own judgement.Create a struct that adheres to the FeedbackOptions
protocol. You can put whatever you want in here, but really it should be as simple as:
struct MyFeedbackReportingOptions: FeedbackOptions {
// The GitHub personal access token for the below user
var token: String = "abc123"
/// The user that generated the above Personal Access Token and has access to the repository.
var user: String = "repoMan"
/// The Github repository in username/repo format where the issue will be saved.
var repo: String = "repoman/myRepository"
}
And then you can use it in the FeedbackReporter
let feedbackReporter = FeedbackReporter(options: MyFeedbackReportingOptions())
You also need to implement FeedbackManagerDatasource
in order to tell the FeedbackManager where to upload screenshots. The simplest implementation would be something like:
func uploadUrl(_ completionHandler: (String) -> Void) {
let filename = String(Date().timeIntervalSince1970) + ".jpg"
let url = "https://www.googleapis.com/upload/storage/v1/b/mybucketname.appspot.com/o?name=\(filename)"
completionHandler(url)
}
With iOS 11 when you take a screenshot, a thumbnail of the image pops up in the lower left corner. Tap it to open the editor. (You can also swipe it away to save the image directly to your camera roll.)
Can the built in editor replace our bundled instance of CLImageEditor? What about < iOS 11? Just not support editing?
https://github.com/gabek/GitYourFeedback/blob/master/GitYourFeedback/Classes/Helpers.swift#L29
Maybe using an external markdown text file or something? There is some options for templating in Swift, but I don't know if it's worth being that heavy handed about it. https://github.com/kylef/Stencil
This should include moving the metadata pieces of the template to a markdown formatted table so it's easier to read.
Something along the lines of:
Thing | Value |
---|---|
Thing 1 | It's value |
Thing 2 | Some other value |
Screen Resolution | 867 x 309 |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.