Tip jar + New display name

This commit is contained in:
Thomas Ricouard 2023-01-07 13:44:13 +01:00
parent b30610538f
commit 75fda4b709
9 changed files with 210 additions and 3 deletions

View file

@ -9,6 +9,9 @@
/* Begin PBXBuildFile section */
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F24EEB729360C330042359D /* Preview Assets.xcassets */; };
9F295540292B6C3400E0E81B /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F29553F292B6C3400E0E81B /* Timeline */; };
9F2A540729699698009B2D7C /* SupportAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A540629699698009B2D7C /* SupportAppView.swift */; };
9F2A540A29699705009B2D7C /* ReceiptParser in Frameworks */ = {isa = PBXBuildFile; productRef = 9F2A540929699705009B2D7C /* ReceiptParser */; };
9F2A540C29699705009B2D7C /* RevenueCat in Frameworks */ = {isa = PBXBuildFile; productRef = 9F2A540B29699705009B2D7C /* RevenueCat */; };
9F2B92F6295AE04800DE16D0 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B92F5295AE04800DE16D0 /* Tabs.swift */; };
9F2B92FA295DA7D700DE16D0 /* AddAccountsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */; };
9F2B92FC295DA94500DE16D0 /* InstanceInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */; };
@ -46,6 +49,8 @@
9F24EEB729360C330042359D /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
9F29553D292B67B600E0E81B /* Network */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Network; path = Packages/Network; sourceTree = "<group>"; };
9F29553E292B6AF600E0E81B /* Timeline */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Timeline; path = Packages/Timeline; sourceTree = "<group>"; };
9F2A5404296995FB009B2D7C /* QuickLookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLookUI.framework; path = System/Library/Frameworks/QuickLookUI.framework; sourceTree = SDKROOT; };
9F2A540629699698009B2D7C /* SupportAppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportAppView.swift; sourceTree = "<group>"; };
9F2B92F5295AE04800DE16D0 /* Tabs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; };
9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountsView.swift; sourceTree = "<group>"; };
9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceInfoView.swift; sourceTree = "<group>"; };
@ -88,6 +93,7 @@
files = (
9F7335EF29674F7100AFF0BA /* QuickLook.framework in Frameworks */,
9F7335ED2967463400AFF0BA /* AVKit.framework in Frameworks */,
9F2A540C29699705009B2D7C /* RevenueCat in Frameworks */,
9F55C6902955993C00F94077 /* Explore in Frameworks */,
9FAE4ACE29379A5A00772766 /* KeychainSwift in Frameworks */,
9F7335EA2966B3F800AFF0BA /* Conversations in Frameworks */,
@ -96,6 +102,7 @@
9FD542E72962D2FF0045321A /* Lists in Frameworks */,
9F398AAB2935FFDB00A889F2 /* Models in Frameworks */,
9F5E581929545BE700A53960 /* Env in Frameworks */,
9F2A540A29699705009B2D7C /* ReceiptParser in Frameworks */,
9F35DB44294F9A7D00B3281A /* Status in Frameworks */,
9F295540292B6C3400E0E81B /* Timeline in Frameworks */,
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */,
@ -201,6 +208,7 @@
9FBFE64C292A72BD00C250E9 /* Frameworks */ = {
isa = PBXGroup;
children = (
9F2A5404296995FB009B2D7C /* QuickLookUI.framework */,
9F7335EE29674F7100AFF0BA /* QuickLook.framework */,
9F7335EB2967461B00AFF0BA /* AVKit.framework */,
);
@ -215,6 +223,7 @@
9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */,
9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */,
9F7335F82968576500AFF0BA /* DisplaySettingsView.swift */,
9F2A540629699698009B2D7C /* SupportAppView.swift */,
);
path = Settings;
sourceTree = "<group>";
@ -247,6 +256,8 @@
9F55C68F2955993C00F94077 /* Explore */,
9FD542E62962D2FF0045321A /* Lists */,
9F7335E92966B3F800AFF0BA /* Conversations */,
9F2A540929699705009B2D7C /* ReceiptParser */,
9F2A540B29699705009B2D7C /* RevenueCat */,
);
productName = IceCubesApp;
productReference = 9FBFE639292A715500C250E9 /* IceCubesApp.app */;
@ -278,6 +289,7 @@
mainGroup = 9FBFE630292A715500C250E9;
packageReferences = (
9FAE4ACC29379A5A00772766 /* XCRemoteSwiftPackageReference "keychain-swift" */,
9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */,
);
productRefGroup = 9FBFE63A292A715500C250E9 /* Products */;
projectDirPath = "";
@ -312,6 +324,7 @@
9F7335F92968576500AFF0BA /* DisplaySettingsView.swift in Sources */,
9FAE4AD32937A0C600772766 /* AppAccountsManager.swift in Sources */,
9F2B92FF295EB87100DE16D0 /* AppAccountView.swift in Sources */,
9F2A540729699698009B2D7C /* SupportAppView.swift in Sources */,
9F2B92F6295AE04800DE16D0 /* Tabs.swift in Sources */,
9F398AB329360A4C00A889F2 /* TimelineTab.swift in Sources */,
9F398AA62935FE8A00A889F2 /* AppRouteur.swift in Sources */,
@ -459,6 +472,7 @@
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = IceCubesApp/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Ice Cubes";
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to Mastodon";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
@ -507,6 +521,7 @@
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = IceCubesApp/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Ice Cubes";
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to Mastodon";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
@ -560,6 +575,14 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/RevenueCat/purchases-ios.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.0.0;
};
};
9FAE4ACC29379A5A00772766 /* XCRemoteSwiftPackageReference "keychain-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/evgenyneu/keychain-swift";
@ -575,6 +598,16 @@
isa = XCSwiftPackageProductDependency;
productName = Timeline;
};
9F2A540929699705009B2D7C /* ReceiptParser */ = {
isa = XCSwiftPackageProductDependency;
package = 9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */;
productName = ReceiptParser;
};
9F2A540B29699705009B2D7C /* RevenueCat */ = {
isa = XCSwiftPackageProductDependency;
package = 9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */;
productName = RevenueCat;
};
9F35DB43294F9A7D00B3281A /* Status */ = {
isa = XCSwiftPackageProductDependency;
productName = Status;

View file

@ -27,6 +27,15 @@
"version" : "11.5.1"
}
},
{
"identity" : "purchases-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/RevenueCat/purchases-ios.git",
"state" : {
"revision" : "9cfb6adb41dc40d80c104b2ef6e9a84bca03ea48",
"version" : "4.16.0"
}
},
{
"identity" : "swiftsoup",
"kind" : "remoteSourceControl",

View file

@ -4,6 +4,8 @@ import Network
import KeychainSwift
import Env
import DesignSystem
import QuickLook
import RevenueCat
@main
struct IceCubesApp: App {
@ -33,6 +35,7 @@ struct IceCubesApp: App {
.onAppear {
setNewClientsInEnv(client: appAccountsManager.currentClient)
setBarsColor(color: theme.primaryBackgroundColor)
setupRevenueCat()
}
.preferredColorScheme(theme.selectedScheme == ColorScheme.dark ? .dark : .light)
.environmentObject(appAccountsManager)
@ -140,4 +143,9 @@ struct IceCubesApp: App {
UINavigationBar.appearance().isTranslucent = true
UINavigationBar.appearance().barTintColor = UIColor(color)
}
private func setupRevenueCat() {
Purchases.logLevel = .error
Purchases.configure(withAPIKey: "appl_JXmiRckOzXXTsHKitQiicXCvMQi")
}
}

View file

@ -97,8 +97,14 @@ struct SettingsTabs: View {
}
}
}
Link(destination: URL(string: "https://github.com/Dimillian/IceCubesApp")!) {
Label("Source (Github link)", systemImage: "link")
Label("Source (Github link)", systemImage: "link")
.onTapGesture {
UIApplication.shared.open(URL(string: "https://github.com/Dimillian/IceCubesApp")!)
}
NavigationLink(destination: SupportAppView()) {
Label("Support the app", systemImage: "wand.and.stars")
}
}
.listRowBackground(theme.primaryBackgroundColor)

View file

@ -0,0 +1,129 @@
import SwiftUI
import Env
import DesignSystem
import RevenueCat
struct SupportAppView: View {
enum Tips: String, CaseIterable {
case one, two, three
init(productId: String) {
self = .init(rawValue: String(productId.split(separator: ".")[2]))!
}
var productId: String {
"icecubes.tipjar.\(rawValue)"
}
var title: String {
switch self {
case .one:
return "🍬 Small Tip"
case .two:
return "☕️ Nice Tip"
case .three:
return "🤯 Generous Tip"
}
}
var subtitle: String {
switch self {
case .one:
return "Small, but cute, and it taste good!"
case .two:
return "I love the taste of a fancy coffee ❤️"
case .three:
return "You're insane, thank you so much!"
}
}
}
@EnvironmentObject private var theme: Theme
@State private var loadingProducts: Bool = false
@State private var products: [StoreProduct] = []
@State private var isProcessingPurchase: Bool = false
@State private var purchaseSuccessDisplayed: Bool = false
@State private var purchaseErrorDisplayed: Bool = false
var body: some View {
Form {
Section {
HStack(alignment: .top, spacing: 12) {
VStack(spacing: 18) {
Image("avatar")
.resizable()
.frame(width: 50, height: 50)
.cornerRadius(4)
Image("icon0")
.resizable()
.frame(width: 50, height: 50)
.cornerRadius(4)
}
Text("Hi there! My name is Thomas and I absolutely love creating open source apps. Ice Cubes is definitely one of my proudest projects to date - and let's be real, it's also the one that requires the most maintenance due to the ever-changing world of Mastodon and social media. If you're having a blast using Ice Cubes, consider tossing a little tip my way. It'll make my day (and help keep the app running smoothly for you). 🚀")
}
}
.listRowBackground(theme.primaryBackgroundColor)
Section {
if loadingProducts {
ProgressView()
} else {
ForEach(products, id: \.productIdentifier) { product in
let tip = Tips(productId: product.productIdentifier)
HStack {
VStack(alignment: .leading) {
Text(tip.title)
.font(.subheadline)
Text(tip.subtitle)
.font(.footnote)
.foregroundColor(.gray)
}
Spacer()
Button {
isProcessingPurchase = true
Purchases.shared.purchase(product: product) { _, _, _, success in
if success {
purchaseSuccessDisplayed = true
} else {
purchaseErrorDisplayed = true
}
isProcessingPurchase = false
}
} label: {
if isProcessingPurchase {
ProgressView()
} else {
Text(product.localizedPriceString)
}
}
.buttonStyle(.bordered)
}
.padding(.vertical, 8)
}
}
}
.listRowBackground(theme.primaryBackgroundColor)
}
.navigationTitle("Support Ice Cubes")
.scrollContentBackground(.hidden)
.background(theme.secondaryBackgroundColor)
.alert("Thanks!", isPresented: $purchaseSuccessDisplayed, actions: {
Button { purchaseSuccessDisplayed = false } label: { Text("Ok") }
}, message: {
Text("Thanks you so much for your tip! It's greatly appreciated!")
})
.alert("Error!", isPresented: $purchaseErrorDisplayed, actions: {
Button { purchaseErrorDisplayed = false } label: { Text("Ok") }
}, message: {
Text("Error processing your in app purchase, please try again.")
})
.onAppear {
loadingProducts = true
Purchases.shared.getProducts(Tips.allCases.map{ $0.productId }) { products in
self.products = products.sorted(by: { $0.price < $1.price })
loadingProducts = false
}
}
}
}

View file

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "avatar.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View file

@ -5,4 +5,5 @@ public struct AppInfo {
public static let scheme = "icecubesapp://"
public static let scopes = "read write follow push"
public static let weblink = "https://github.com/Dimillian/IceCubesApp"
public static let revenueCatKey = "appl_JXmiRckOzXXTsHKitQiicXCvMQi"
}

View file

@ -124,7 +124,7 @@ public struct TimelineView: View {
viewModel.dequeuePendingStatuses()
}
} label: {
Image(systemName: "play.square.stack")
Image(systemName: "text.insert")
}
.buttonStyle(.bordered)
.background(.thinMaterial)