Skip to content

Commit

Permalink
Add donations UI to the app and wire it up to Obaco
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronbrethorst committed Nov 19, 2023
1 parent e4244e4 commit e383c57
Show file tree
Hide file tree
Showing 25 changed files with 860 additions and 25 deletions.
8 changes: 0 additions & 8 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@ included: # paths to include during linting. `--path` is ignored if present.
excluded: # paths to ignore during linting. Takes precedence over `included`.
- OBAKitCore/Models/Protobuf/gtfs-realtime.pb.swift

force_try:
excluded:
- OBAKitTests

function_body_length:
excluded:
- OBAKitTests

file_length:
warning: 900
error: 1000
Expand Down
21 changes: 21 additions & 0 deletions Apps/OneBusAway/Assets.xcassets/wmata.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "wmata.jpg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions Apps/OneBusAway/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ targets:
- applinks:onebusaway.co
- applinks:www.onebusaway.co
- applinks:alerts.onebusaway.org
com.apple.developer.in-app-payments:
- merchant.org.onebusaway.iphone
info:
path: Apps/OneBusAway/Info.plist
properties:
Expand Down Expand Up @@ -61,12 +63,16 @@ targets:
AppGroup: group.org.onebusaway.iphone
BundledRegionsFileName: regions.json
DeepLinkServerBaseAddress: https://onebusaway.co
DonationsEnabled: true
ExtensionURLScheme: onebusaway
PrivacyPolicyURL: https://onebusaway.org/privacy/
PushNotificationAPIKey: d5d0d28a-6091-46cd-9627-0ce01ffa9f9e
RESTServerAPIKey: org.onebusaway.iphone
RegionsServerBaseAddress: https://regions.onebusaway.org
RegionsServerAPIPath: /regions-v3.json
StripePublishableKeys:
test: pk_test_51O20R8BsTfxG3EeliQswtDI6etwUu6cdYX7AIT2HkyI7iMbI2Ltqz0R06EkM7SmRTYJfOPwum1iTJgrJpoLoB8ii00eUXFwHjT
production: pk_live_51O20R8BsTfxG3EelVtkEOa5zmx9MPoAXi2Jrcx8PvBUwYvKlXEJdL3nYHF7Vmd1UZ6tKyrZrKUx89bwMmSaN5HIr0096SVUJts
settings:
base:
DEVELOPMENT_TEAM: 4ZQCMA634J
Expand Down
3 changes: 3 additions & 0 deletions Apps/Shared/app_shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ packages:
OneSignal:
url: https://github.com/OneSignal/OneSignal-iOS-SDK.git
minorVersion: 3.11.2
stripe-ios-spm:
url: https://github.com/stripe/stripe-ios-spm.git
minorVersion: 23.18.2
SwiftProtobuf:
url: https://github.com/apple/swift-protobuf.git
minorVersion: 1.19.1
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,15 @@
"version" : "2.1.1"
}
},
{
"identity" : "stripe-ios-spm",
"kind" : "remoteSourceControl",
"location" : "https://github.com/stripe/stripe-ios-spm",
"state" : {
"revision" : "d1e98b0acad316d1bf7d30bfdf34ec8ca9ca1e15",
"version" : "23.18.2"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
Expand Down
16 changes: 16 additions & 0 deletions OBAKit/Analytics/Analytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,28 @@ public class AnalyticsLabels: NSObject {

/// Label used when 'show my location' button is tapped.'
@objc public static let mapShowUserLocationButtonTapped = "Clicked My Location Button"

/// Label used when 'Learn More About Donations' screen is displayed
@objc public static let donationLearnMoreShown = "Donation Learn More Shown"

/// Label used when 'Donate button' is tapped
@objc public static let donateButtonTapped = "Donation Button Tapped"

/// Label used when a donation succeeds
@objc public static let donationSuccess = "Donation Success"

/// Label used when a donation fails due to an unrecoverable system error.
@objc public static let donationError = "Donation Error"

/// Label used when a donation fails due to the user canceling it.
@objc public static let donationCanceled = "Donation Canceled"
}

/// Reported analytics events.
@objc(OBAAnalyticsEvent)
public enum AnalyticsEvent: Int {
case userAction
case systemAction
}

/// Implement this protocol for reporting analytics events in order to be able to plug in a custom provider of your choosing.
Expand Down
16 changes: 16 additions & 0 deletions OBAKit/Analytics/AnalyticsModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// AnalyticsModel.swift
// OBAKit
//
// Created by Aaron Brethorst on 11/16/23.
//

import SwiftUI

class AnalyticsModel: ObservableObject {
init(_ analytics: Analytics?) {
self.analytics = analytics
}

let analytics: Analytics?
}
121 changes: 121 additions & 0 deletions OBAKit/Donations/DonationCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// DonationCell.swift
// OBAKit
//
// Created by Aaron Brethorst on 10/30/23.
//

import UIKit
import OBAKitCore

class DonationCell: OBAListViewCell {

var donationRequest: DonationRequest?
var viewModel: DonationListItem?

public override func apply(_ config: OBAContentConfiguration) {
super.apply(config)

guard let config = config as? DonationContentConfiguration else {
fatalError()
}

viewModel = config.viewModel
}

lazy var titleLabel: UILabel = {
let label = UILabel.autolayoutNew()
label.numberOfLines = 0
label.font = .preferredFont(forTextStyle: .title3).bold

label.text = OBALoc("donation_cell.title", value: "🚨 OneBusAway needs your help", comment: "Title of the donation widget that appears on the stop view controller.")
return label
}()

lazy var closeButton = {
let button = UIButton.buildCloseButton()
let action = UIAction { [self] _ in
guard let viewModel = viewModel else { return }
viewModel.onCloseAction?(viewModel)
}
button.addAction(action, for: .touchUpInside)
return button
}()

lazy var closeButtonWrapper: UIView = {
let wrapper = closeButton.embedInWrapperView(setConstraints: false)
NSLayoutConstraint.activate([
closeButton.leadingAnchor.constraint(equalTo: wrapper.leadingAnchor),
closeButton.topAnchor.constraint(equalTo: wrapper.topAnchor),
closeButton.trailingAnchor.constraint(equalTo: wrapper.trailingAnchor),
wrapper.heightAnchor.constraint(greaterThanOrEqualTo: closeButton.heightAnchor)
])

return wrapper
}()

lazy var titleRow = UIStackView.horizontalStack(arrangedSubviews: [titleLabel, closeButtonWrapper])

lazy var messageLabel: UILabel = {
let label = UILabel.autolayoutNew()
label.numberOfLines = 0
label.text = OBALoc("donation_cell.body", value: "This app is currently built with 100% volunteer labor, and we need you to help us fund future development.", comment: "Body of the donation widget that appears on the stop view controller")
return label
}()

lazy var learnMoreButton: UIButton = {
let action = UIAction { [self] _ in
guard let viewModel = viewModel else { return }
viewModel.onLearnMoreAction?(viewModel)
}
let button = UIButton(configuration: .bordered(), primaryAction: action)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(OBALoc("donation_cell.learn_more_button_title", value: "Learn More", comment: "Title of the button that shows the donation explanation UI."), for: .normal)
return button
}()

lazy var donateButton: UIButton = {
let button = UIButton(configuration: .borderedProminent())
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(OBALoc("donation_cell.donate_button_title", value: "Donate Now", comment: "Title of the button that shows the donation UI."), for: .normal)

let action = UIAction { [self] _ in
guard let viewModel = viewModel else { return }
viewModel.onSelectAction?(viewModel)
}
button.addAction(action, for: .touchUpInside)
return button
}()

lazy var buttonStack: UIStackView = {
let stack = UIStackView.horizontalStack(arrangedSubviews: [learnMoreButton, donateButton])
stack.spacing = ThemeMetrics.compactPadding

return stack
}()

lazy var outerStack: UIStackView = {
let stack = UIStackView.verticalStack(arrangedSubviews: [
titleRow,
messageLabel,
UIView.spacerView(height: 4.0),
buttonStack
])
stack.spacing = 4.0
return stack
}()

override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func setupView() {
addSubview(outerStack)
outerStack.pinToSuperview(.edges, insets: NSDirectionalEdgeInsets(top: 8, leading: 8, bottom: -8, trailing: -8))
}
}
Loading

0 comments on commit e383c57

Please sign in to comment.