Add supporter subscription + supporter badge

This commit is contained in:
Thomas Ricouard 2023-03-01 20:07:40 +01:00
parent a9e935016f
commit 81f3db733b
23 changed files with 382 additions and 84 deletions

View file

@ -28,6 +28,7 @@ struct IceCubesApp: App {
@State private var selectedTab: Tab = .timeline @State private var selectedTab: Tab = .timeline
@State private var popToRootTab: Tab = .other @State private var popToRootTab: Tab = .other
@State private var sideBarLoadedTabs: Set<Tab> = Set() @State private var sideBarLoadedTabs: Set<Tab> = Set()
@State private var isSupporter: Bool = false
private var availableTabs: [Tab] { private var availableTabs: [Tab] {
appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab() appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
@ -51,6 +52,7 @@ struct IceCubesApp: App {
.environmentObject(theme) .environmentObject(theme)
.environmentObject(watcher) .environmentObject(watcher)
.environmentObject(pushNotificationsService) .environmentObject(pushNotificationsService)
.environment(\.isSupporter, isSupporter)
.fullScreenCover(item: $quickLook.url, content: { url in .fullScreenCover(item: $quickLook.url, content: { url in
QuickLookPreview(selectedURL: url, urls: quickLook.urls) QuickLookPreview(selectedURL: url, urls: quickLook.urls)
.edgesIgnoringSafeArea(.bottom) .edgesIgnoringSafeArea(.bottom)
@ -225,6 +227,11 @@ struct IceCubesApp: App {
private func setupRevenueCat() { private func setupRevenueCat() {
Purchases.logLevel = .error Purchases.logLevel = .error
Purchases.configure(withAPIKey: "appl_JXmiRckOzXXTsHKitQiicXCvMQi") Purchases.configure(withAPIKey: "appl_JXmiRckOzXXTsHKitQiicXCvMQi")
Purchases.shared.getCustomerInfo { info, _ in
if info?.entitlements.active.isEmpty == false {
isSupporter = true
}
}
} }
private func refreshPushSubs() { private func refreshPushSubs() {

View file

@ -6,7 +6,7 @@ import SwiftUI
struct SupportAppView: View { struct SupportAppView: View {
enum Tip: String, CaseIterable { enum Tip: String, CaseIterable {
case one, two, three, four case one, two, three, four, supporter
init(productId: String) { init(productId: String) {
self = .init(rawValue: String(productId.split(separator: ".")[2]))! self = .init(rawValue: String(productId.split(separator: ".")[2]))!
@ -26,6 +26,8 @@ struct SupportAppView: View {
return "settings.support.three.title" return "settings.support.three.title"
case .four: case .four:
return "settings.support.four.title" return "settings.support.four.title"
case .supporter:
return "settings.support.supporter.title"
} }
} }
@ -39,92 +41,31 @@ struct SupportAppView: View {
return "settings.support.three.subtitle" return "settings.support.three.subtitle"
case .four: case .four:
return "settings.support.four.subtitle" return "settings.support.four.subtitle"
case .supporter:
return "settings.support.supporter.subtitle"
} }
} }
} }
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@Environment(\.openURL) private var openURL
@State private var loadingProducts: Bool = false @State private var loadingProducts: Bool = false
@State private var products: [StoreProduct] = [] @State private var products: [StoreProduct] = []
@State private var subscription: StoreProduct?
@State private var customerInfo: CustomerInfo?
@State private var isProcessingPurchase: Bool = false @State private var isProcessingPurchase: Bool = false
@State private var purchaseSuccessDisplayed: Bool = false @State private var purchaseSuccessDisplayed: Bool = false
@State private var purchaseErrorDisplayed: Bool = false @State private var purchaseErrorDisplayed: Bool = false
var body: some View { var body: some View {
Form { Form {
Section { aboutSection
HStack(alignment: .top, spacing: 12) { subscriptionSection
VStack(spacing: 18) { tipsSection
Image("avatar") restorePurchase
.resizable() linksSection
.frame(width: 50, height: 50)
.cornerRadius(4)
Image("icon0")
.resizable()
.frame(width: 50, height: 50)
.cornerRadius(4)
}
Text("settings.support.message-from-dev")
}
}
.listRowBackground(theme.primaryBackgroundColor)
Section {
if loadingProducts {
HStack {
VStack(alignment: .leading) {
Text("placeholder.loading.short.")
.font(.scaledSubheadline)
Text("settings.support.placeholder.loading-subtitle")
.font(.scaledFootnote)
.foregroundColor(.gray)
}
.padding(.vertical, 8)
}
.redacted(reason: .placeholder)
.shimmering()
} else {
ForEach(products, id: \.productIdentifier) { product in
let tip = Tip(productId: product.productIdentifier)
HStack {
VStack(alignment: .leading) {
Text(tip.title)
.font(.scaledSubheadline)
Text(tip.subtitle)
.font(.scaledFootnote)
.foregroundColor(.gray)
}
Spacer()
Button {
if !isProcessingPurchase {
isProcessingPurchase = true
Task {
do {
let result = try await Purchases.shared.purchase(product: product)
if !result.userCancelled {
purchaseSuccessDisplayed = true
}
} catch {
purchaseErrorDisplayed = true
}
isProcessingPurchase = false
}
}
} label: {
if isProcessingPurchase {
ProgressView()
} else {
Text(product.localizedPriceString)
}
}
.buttonStyle(.bordered)
}
.padding(.vertical, 8)
}
}
}
.listRowBackground(theme.primaryBackgroundColor)
} }
.navigationTitle("settings.support.navigation-title") .navigationTitle("settings.support.navigation-title")
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)
@ -141,12 +82,191 @@ struct SupportAppView: View {
}) })
.onAppear { .onAppear {
loadingProducts = true loadingProducts = true
Purchases.shared.getProducts(Tip.allCases.map { $0.productId }) { products in fetchStoreProducts()
self.products = products.sorted(by: { $0.price < $1.price }) refreshUserInfo()
withAnimation { }
loadingProducts = false }
private func purchase(product: StoreProduct) async {
if !isProcessingPurchase {
isProcessingPurchase = true
do {
let result = try await Purchases.shared.purchase(product: product)
if !result.userCancelled {
purchaseSuccessDisplayed = true
} }
} catch {
purchaseErrorDisplayed = true
}
isProcessingPurchase = false
}
}
private func fetchStoreProducts() {
Purchases.shared.getProducts(Tip.allCases.map { $0.productId }) { products in
self.subscription = products.first(where: { $0.productIdentifier == Tip.supporter.productId })
self.products = products.filter{ $0.productIdentifier != Tip.supporter.productId}.sorted(by: { $0.price < $1.price })
withAnimation {
loadingProducts = false
} }
} }
} }
private func refreshUserInfo() {
Purchases.shared.getCustomerInfo { info, _ in
self.customerInfo = info
}
}
private func makePurchaseButton(product: StoreProduct) -> some View {
Button {
Task {
await purchase(product: product)
refreshUserInfo()
}
} label: {
if isProcessingPurchase {
ProgressView()
} else {
Text(product.localizedPriceString)
}
}
.buttonStyle(.bordered)
}
private var aboutSection: some View {
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("settings.support.message-from-dev")
}
}
.listRowBackground(theme.primaryBackgroundColor)
}
private var subscriptionSection: some View {
Section {
if loadingProducts {
loadingPlaceholder
} else if let subscription {
HStack {
if customerInfo?.entitlements.active.isEmpty == false {
Text(Image(systemName: "checkmark.seal.fill"))
.foregroundColor(theme.tintColor)
.baselineOffset(-1) +
Text("settings.support.supporter.subscribed")
.font(.scaledSubheadline)
} else {
VStack(alignment: .leading) {
Text(Image(systemName: "checkmark.seal.fill"))
.foregroundColor(theme.tintColor)
.baselineOffset(-1) +
Text(Tip.supporter.title)
.font(.scaledSubheadline)
Text(Tip.supporter.subtitle)
.font(.scaledFootnote)
.foregroundColor(.gray)
}
Spacer()
makePurchaseButton(product: subscription)
}
}
.padding(.vertical, 8)
}
} footer: {
if customerInfo?.entitlements.active.isEmpty == true {
Text("settings.support.supporter.subscription-info")
}
}
.listRowBackground(theme.primaryBackgroundColor)
}
private var tipsSection: some View {
Section {
if loadingProducts {
loadingPlaceholder
} else {
ForEach(products, id: \.productIdentifier) { product in
let tip = Tip(productId: product.productIdentifier)
HStack {
VStack(alignment: .leading) {
Text(tip.title)
.font(.scaledSubheadline)
Text(tip.subtitle)
.font(.scaledFootnote)
.foregroundColor(.gray)
}
Spacer()
makePurchaseButton(product: product)
}
.padding(.vertical, 8)
}
}
}
.listRowBackground(theme.primaryBackgroundColor)
}
private var restorePurchase: some View {
Section {
HStack {
Spacer()
Button {
Purchases.shared.restorePurchases { info, _ in
self.customerInfo = info
}
} label: {
Text("settings.support.restore-purchase.button")
}.buttonStyle(.bordered)
Spacer()
}
} footer: {
Text("settings.support.restore-purchase.explanation")
}
.listRowBackground(theme.secondaryBackgroundColor)
}
private var linksSection: some View {
Section {
VStack(alignment: .leading, spacing: 16) {
Button {
openURL(URL(string: "https://github.com/Dimillian/IceCubesApp/blob/main/PRIVACY.MD")!)
} label: {
Text("settings.support.privacy-policy")
}
.buttonStyle(.borderless)
Button {
openURL(URL(string: "https://github.com/Dimillian/IceCubesApp/blob/main/TERMS.MD")!)
} label: {
Text("settings.support.terms-of-use")
}
.buttonStyle(.borderless)
}
}
.listRowBackground(theme.secondaryBackgroundColor)
}
private var loadingPlaceholder: some View {
HStack {
VStack(alignment: .leading) {
Text("placeholder.loading.short.")
.font(.scaledSubheadline)
Text("settings.support.placeholder.loading-subtitle")
.font(.scaledFootnote)
.foregroundColor(.gray)
}
.padding(.vertical, 8)
}
.redacted(reason: .placeholder)
.shimmering()
}
} }

View file

@ -146,6 +146,14 @@
"settings.support.two.title" = "☕️ Прыемны Гасцінец"; "settings.support.two.title" = "☕️ Прыемны Гасцінец";
"settings.support.four.title" = "👽 Хто ты Гасцінец"; "settings.support.four.title" = "👽 Хто ты Гасцінец";
"settings.support.four.subtitle" = "Гэта вельмі дапаможа Ice Cubes працаваць!"; "settings.support.four.subtitle" = "Гэта вельмі дапаможа Ice Cubes працаваць!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Дадайце мясцовую шкалу часу"; "settings.timeline.add" = "Дадайце мясцовую шкалу часу";
"settings.title" = "Налады"; "settings.title" = "Налады";
"settings.rate" = "Ацаніце Ice Cubes"; "settings.rate" = "Ацаніце Ice Cubes";

View file

@ -141,6 +141,14 @@
"settings.support.two.title" = "☕️ Bona propina"; "settings.support.two.title" = "☕️ Bona propina";
"settings.support.four.title" = "👽 Propina d'un altre món"; "settings.support.four.title" = "👽 Propina d'un altre món";
"settings.support.four.subtitle" = "Ajudarà molt a mantenir Ice Cubes en funcionament!"; "settings.support.four.subtitle" = "Ajudarà molt a mantenir Ice Cubes en funcionament!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Afegeix una línia de temps local"; "settings.timeline.add" = "Afegeix una línia de temps local";
"settings.title" = "Configuració"; "settings.title" = "Configuració";
"settings.rate" = "Valora Ice Cubes"; "settings.rate" = "Valora Ice Cubes";

View file

@ -122,6 +122,14 @@
"settings.support.two.title" = "☕️ Schönes Trinkgeld"; "settings.support.two.title" = "☕️ Schönes Trinkgeld";
"settings.support.four.title" = "👽 Wahnsinns-Trinkgeld"; "settings.support.four.title" = "👽 Wahnsinns-Trinkgeld";
"settings.support.four.subtitle" = "Das wird eine große Hilfe sein, Ice Cubes am Laufen zu halten!"; "settings.support.four.subtitle" = "Das wird eine große Hilfe sein, Ice Cubes am Laufen zu halten!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Lokale Timeline hinzufügen"; "settings.timeline.add" = "Lokale Timeline hinzufügen";
"settings.title" = "Einstellungen"; "settings.title" = "Einstellungen";
"settings.rate" = "Bewerte Ice Cubes"; "settings.rate" = "Bewerte Ice Cubes";

View file

@ -147,6 +147,14 @@
"settings.support.two.title" = "☕️ Nice Tip"; "settings.support.two.title" = "☕️ Nice Tip";
"settings.support.four.title" = "👽 Who are you Tip"; "settings.support.four.title" = "👽 Who are you Tip";
"settings.support.four.subtitle" = "It'll go a long way to keep Ice Cubes running!"; "settings.support.four.subtitle" = "It'll go a long way to keep Ice Cubes running!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Add a Local Timeline"; "settings.timeline.add" = "Add a Local Timeline";
"settings.title" = "Settings"; "settings.title" = "Settings";
"settings.rate" = "Rate Ice Cubes"; "settings.rate" = "Rate Ice Cubes";

View file

@ -146,6 +146,14 @@
"settings.support.two.title" = "☕️ Nice Tip"; "settings.support.two.title" = "☕️ Nice Tip";
"settings.support.four.title" = "👽 Who are you Tip"; "settings.support.four.title" = "👽 Who are you Tip";
"settings.support.four.subtitle" = "It'll go a long way to keep Ice Cubes running!"; "settings.support.four.subtitle" = "It'll go a long way to keep Ice Cubes running!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Add a Local Timeline"; "settings.timeline.add" = "Add a Local Timeline";
"settings.title" = "Settings"; "settings.title" = "Settings";
"settings.rate" = "Rate Ice Cubes"; "settings.rate" = "Rate Ice Cubes";

View file

@ -122,6 +122,14 @@
"settings.support.two.title" = "☕️ Buena propina"; "settings.support.two.title" = "☕️ Buena propina";
"settings.support.four.title" = "👽 Propina de otro mundo"; "settings.support.four.title" = "👽 Propina de otro mundo";
"settings.support.four.subtitle" = "¡Será de gran ayuda para que Ice Cubes siga funcionando!"; "settings.support.four.subtitle" = "¡Será de gran ayuda para que Ice Cubes siga funcionando!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Añadir cronología local"; "settings.timeline.add" = "Añadir cronología local";
"settings.title" = "Ajustes"; "settings.title" = "Ajustes";
"settings.rate" = "Valora Ice Cubes"; "settings.rate" = "Valora Ice Cubes";

View file

@ -122,6 +122,14 @@
"settings.support.two.title" = "☕️ Eskupeko ona"; "settings.support.two.title" = "☕️ Eskupeko ona";
"settings.support.four.title" = "👽 Nor zara zu, Tip"; "settings.support.four.title" = "👽 Nor zara zu, Tip";
"settings.support.four.subtitle" = "Askorako emango du eta Ice Cubes mantentzen lagunduko du!"; "settings.support.four.subtitle" = "Askorako emango du eta Ice Cubes mantentzen lagunduko du!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Gehitu denbora-lerro lokal bat"; "settings.timeline.add" = "Gehitu denbora-lerro lokal bat";
"settings.title" = "Ezarpenak"; "settings.title" = "Ezarpenak";
"settings.rate" = "Baloratu Ice Cubes"; "settings.rate" = "Baloratu Ice Cubes";

View file

@ -142,6 +142,14 @@
"settings.support.two.title" = "☕️ Belle contribution"; "settings.support.two.title" = "☕️ Belle contribution";
"settings.support.four.title" = "👽 Contribution Qui êtes-vous"; "settings.support.four.title" = "👽 Contribution Qui êtes-vous";
"settings.support.four.subtitle" = "Cela ira loin pour maintenir Ice Cubes en marche !"; "settings.support.four.subtitle" = "Cela ira loin pour maintenir Ice Cubes en marche !";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Ajouter une chronologie locale"; "settings.timeline.add" = "Ajouter une chronologie locale";
"settings.title" = "Réglages"; "settings.title" = "Réglages";
"settings.rate" = "Noter Ice Cubes"; "settings.rate" = "Noter Ice Cubes";

View file

@ -122,6 +122,14 @@
"settings.support.two.title" = "☕️ Contributo carino"; "settings.support.two.title" = "☕️ Contributo carino";
"settings.support.four.title" = "👽 Contributo fuori dal mondo"; "settings.support.four.title" = "👽 Contributo fuori dal mondo";
"settings.support.four.subtitle" = "Sarà di grande aiuto per mantenere Ice Cubes in funzione!"; "settings.support.four.subtitle" = "Sarà di grande aiuto per mantenere Ice Cubes in funzione!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Aggiungi una timeline locale"; "settings.timeline.add" = "Aggiungi una timeline locale";
"settings.title" = "Impostazioni"; "settings.title" = "Impostazioni";
"settings.rate" = "Valuta Ice Cubes"; "settings.rate" = "Valuta Ice Cubes";

View file

@ -146,6 +146,14 @@
"settings.support.two.title" = "☕️ ナイスチップ"; "settings.support.two.title" = "☕️ ナイスチップ";
"settings.support.four.title" = "👽 お前は一体誰なんだ"; "settings.support.four.title" = "👽 お前は一体誰なんだ";
"settings.support.four.subtitle" = "Ice Cubesの運営に大きく貢献することでしょう"; "settings.support.four.subtitle" = "Ice Cubesの運営に大きく貢献することでしょう";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "ローカルタイムラインの追加"; "settings.timeline.add" = "ローカルタイムラインの追加";
"settings.title" = "設定"; "settings.title" = "設定";
"settings.rate" = "Ice Cubesを評価する"; "settings.rate" = "Ice Cubesを評価する";

View file

@ -142,6 +142,14 @@
"settings.support.two.title" = "☕️ 기분 좋아지는 기부금"; "settings.support.two.title" = "☕️ 기분 좋아지는 기부금";
"settings.support.four.title" = "👽 엄청난 기부금"; "settings.support.four.title" = "👽 엄청난 기부금";
"settings.support.four.subtitle" = "Ice Cubes가 계속 발전하는 데 정말 많은 도움이 될 거에요!"; "settings.support.four.subtitle" = "Ice Cubes가 계속 발전하는 데 정말 많은 도움이 될 거에요!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "원격 로컬 타임라인 추가"; "settings.timeline.add" = "원격 로컬 타임라인 추가";
"settings.title" = "설정"; "settings.title" = "설정";
"settings.rate" = "Ice Cubes 평가 남기기"; "settings.rate" = "Ice Cubes 평가 남기기";

View file

@ -146,6 +146,14 @@
"settings.support.two.title" = "☕️ Godt tips"; "settings.support.two.title" = "☕️ Godt tips";
"settings.support.four.title" = "👽 Hvem er du tips"; "settings.support.four.title" = "👽 Hvem er du tips";
"settings.support.four.subtitle" = "Det vil gå en lang vei å holde Ice Cubes i gang!"; "settings.support.four.subtitle" = "Det vil gå en lang vei å holde Ice Cubes i gang!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Legg til en lokal tidslinje"; "settings.timeline.add" = "Legg til en lokal tidslinje";
"settings.title" = "Innstillinger"; "settings.title" = "Innstillinger";
"settings.rate" = "Vurder Ice Cubes"; "settings.rate" = "Vurder Ice Cubes";

View file

@ -123,6 +123,14 @@
"settings.support.two.title" = "☕️ Goeie fooi"; "settings.support.two.title" = "☕️ Goeie fooi";
"settings.support.four.title" = "👽 Wie ben jij-fooi"; "settings.support.four.title" = "👽 Wie ben jij-fooi";
"settings.support.four.subtitle" = "Daarmee kan Ice Cubes nog een tijdje vooruit!"; "settings.support.four.subtitle" = "Daarmee kan Ice Cubes nog een tijdje vooruit!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Lokale tijdlijn toevoegen"; "settings.timeline.add" = "Lokale tijdlijn toevoegen";
"settings.title" = "Instellingen"; "settings.title" = "Instellingen";
"settings.section.other" = "Overig"; "settings.section.other" = "Overig";

View file

@ -142,6 +142,14 @@
"settings.support.two.title" = "☕️ Miły napiwek"; "settings.support.two.title" = "☕️ Miły napiwek";
"settings.support.four.title" = "👽 Kim jesteś?"; "settings.support.four.title" = "👽 Kim jesteś?";
"settings.support.four.subtitle" = "To pozwoli na utrzymywanie Ice Cubes w działaniu przez długi czas!"; "settings.support.four.subtitle" = "To pozwoli na utrzymywanie Ice Cubes w działaniu przez długi czas!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Dodaj strumień lokalny"; "settings.timeline.add" = "Dodaj strumień lokalny";
"settings.title" = "Ustawienia"; "settings.title" = "Ustawienia";
"settings.rate" = "Oceń Ice Cubes"; "settings.rate" = "Oceń Ice Cubes";

View file

@ -142,6 +142,14 @@
"settings.support.two.title" = "☕️ Corgeta legal"; "settings.support.two.title" = "☕️ Corgeta legal";
"settings.support.four.title" = "👽 Quem é você Gorgeta"; "settings.support.four.title" = "👽 Quem é você Gorgeta";
"settings.support.four.subtitle" = "Percorrerá um longo caminho para manter o Ice Cubes funcionando!"; "settings.support.four.subtitle" = "Percorrerá um longo caminho para manter o Ice Cubes funcionando!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Adicionar uma timeline local"; "settings.timeline.add" = "Adicionar uma timeline local";
"settings.title" = "Configurações"; "settings.title" = "Configurações";
"settings.rate" = "Avalie o Ice Cubes"; "settings.rate" = "Avalie o Ice Cubes";

View file

@ -142,6 +142,14 @@
"settings.support.two.title" = "☕️ Hoş Bağış"; "settings.support.two.title" = "☕️ Hoş Bağış";
"settings.support.four.title" = "👽 Sen de kimsin Bağışı"; "settings.support.four.title" = "👽 Sen de kimsin Bağışı";
"settings.support.four.subtitle" = "Bu, Ice Cubes'u daha uzun süre devam ettirmemize yardımcı olacak!"; "settings.support.four.subtitle" = "Bu, Ice Cubes'u daha uzun süre devam ettirmemize yardımcı olacak!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Yerel bir zaman dilimi ekleyin"; "settings.timeline.add" = "Yerel bir zaman dilimi ekleyin";
"settings.title" = "Ayarlar"; "settings.title" = "Ayarlar";
"settings.rate" = "Ice Cubes'u puanlayın"; "settings.rate" = "Ice Cubes'u puanlayın";

View file

@ -146,6 +146,14 @@
"settings.support.two.title" = "☕️ Nice Tip"; "settings.support.two.title" = "☕️ Nice Tip";
"settings.support.four.title" = "👽 Who are you Tip"; "settings.support.four.title" = "👽 Who are you Tip";
"settings.support.four.subtitle" = "It'll go a long way to keep Ice Cubes running!"; "settings.support.four.subtitle" = "It'll go a long way to keep Ice Cubes running!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "Додати локальну стрічку"; "settings.timeline.add" = "Додати локальну стрічку";
"settings.title" = "Налаштування"; "settings.title" = "Налаштування";
"settings.rate" = "Оцінити Ice Cubes"; "settings.rate" = "Оцінити Ice Cubes";

View file

@ -122,6 +122,14 @@
"settings.support.two.title" = "☕️ 很不错的捐赠"; "settings.support.two.title" = "☕️ 很不错的捐赠";
"settings.support.four.title" = "👽 神秘人的捐赠"; "settings.support.four.title" = "👽 神秘人的捐赠";
"settings.support.four.subtitle" = "这将大大有助于 Ice Cubes 的持续运行!"; "settings.support.four.subtitle" = "这将大大有助于 Ice Cubes 的持续运行!";
"settings.support.supporter.title" = " Become a supporter!";
"settings.support.supporter.subtitle" = "By giving a monthly tip to Ice Cubes, you become a supporter, you'll even get verified badge on your profile. For your 👀 only.";
"settings.support.supporter.subscribed" = " Thanks for being an Ice Cubes supporter!";
"settings.support.supporter.subscription-info"= "Subscription are automatically renewed unless you cancel them a day before the next renewal cycle.";
"settings.support.restore-purchase.button" = "Restore purchase";
"settings.support.restore-purchase.explanation" = "Restore your supporter subscription if it's haven't been automatically synced.";
"settings.support.privacy-policy" = "Privacy Policy";
"settings.support.terms-of-use" = "Terms";
"settings.timeline.add" = "添加远程时间线"; "settings.timeline.add" = "添加远程时间线";
"settings.title" = "设置"; "settings.title" = "设置";
"settings.rate" = "给 Ice Cubes 评分"; "settings.rate" = "给 Ice Cubes 评分";

View file

@ -16,6 +16,7 @@ struct AccountDetailHeaderView: View {
@EnvironmentObject private var routerPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
@Environment(\.isSupporter) private var isSupporter: Bool
@ObservedObject var viewModel: AccountDetailViewModel @ObservedObject var viewModel: AccountDetailViewModel
let account: Account let account: Account
@ -85,15 +86,24 @@ struct AccountDetailHeaderView: View {
private var accountAvatarView: some View { private var accountAvatarView: some View {
HStack { HStack {
AvatarView(url: account.avatar, size: .account) ZStack(alignment: .topTrailing) {
.onTapGesture { AvatarView(url: account.avatar, size: .account)
guard account.haveAvatar else { .onTapGesture {
return guard account.haveAvatar else {
} return
Task { }
await quickLook.prepareFor(urls: [account.avatar], selectedURL: account.avatar) Task {
await quickLook.prepareFor(urls: [account.avatar], selectedURL: account.avatar)
}
} }
if viewModel.isCurrentUser, isSupporter {
Image(systemName: "checkmark.seal.fill")
.resizable()
.frame(width: 25, height: 25)
.foregroundColor(theme.tintColor)
.offset(x: 10, y: -10)
} }
}
Spacer() Spacer()
Group { Group {
Button { Button {

View file

@ -17,6 +17,10 @@ private struct IsInCaptureMode: EnvironmentKey {
static let defaultValue: Bool = false static let defaultValue: Bool = false
} }
private struct IsSupporter: EnvironmentKey {
static let defaultValue: Bool = false
}
public extension EnvironmentValues { public extension EnvironmentValues {
var isSecondaryColumn: Bool { var isSecondaryColumn: Bool {
get { self[SecondaryColumnKey.self] } get { self[SecondaryColumnKey.self] }
@ -37,4 +41,9 @@ public extension EnvironmentValues {
get { self[IsInCaptureMode.self] } get { self[IsInCaptureMode.self] }
set { self[IsInCaptureMode.self] = newValue } set { self[IsInCaptureMode.self] = newValue }
} }
var isSupporter: Bool {
get { self[IsSupporter.self] }
set { self[IsSupporter.self] = newValue }
}
} }

8
TERMS.MD Normal file
View file

@ -0,0 +1,8 @@
# Terms of Use
Use of Ice Cubes is governed by Apples Standard EULA for apps.
Tips provided in Ice Cubes do no unlock any additional content in the app.
Subscriptions will automatically renew unless canceled within 24-hours before the end of the current period. You can cancel anytime with your iTunes account settings. Any unused portion of a free trial will be forfeited if you purchase a subscription. Auto-renewal may be turned off by the user, by going to the users Account Settings after purchase. The duration and price of each subscription is displayed on the purchase screen, and updated at the time of purchase.
If you have any questions about Ice Cubes Terms of Use, please reach out to me at ricouard77@gmail.com