Compare commits
No commits in common. "07b6bf33cb376e4ac6ff448a13c09ae577454488" and "b85c0eb95dd2a034dd3fe0172990669ccd64f9d6" have entirely different histories.
07b6bf33cb
...
b85c0eb95d
|
@ -1,8 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 2024.3 (133)
|
|
||||||
- Add additional info to Tip Jar
|
|
||||||
|
|
||||||
## 2024.3 (132)
|
## 2024.3 (132)
|
||||||
- Add ToS nag before signing in
|
- Add ToS nag before signing in
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,12 @@ struct TipJarView: View {
|
||||||
@StateObject private var observer = UbiquitousKeyValueStoreObserver()
|
@StateObject private var observer = UbiquitousKeyValueStoreObserver()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
ZStack {
|
||||||
productsOrLoading
|
Color.appGroupedBackground
|
||||||
}
|
.edgesIgnoringSafeArea(.all)
|
||||||
.listStyle(.insetGrouped)
|
|
||||||
.appGroupedListBackground(container: PreferencesNavigationController.self)
|
productsView
|
||||||
.overlay {
|
|
||||||
if showConfetti {
|
if showConfetti {
|
||||||
ConfettiView()
|
ConfettiView()
|
||||||
.transition(.opacity.animation(.default))
|
.transition(.opacity.animation(.default))
|
||||||
|
@ -75,66 +75,46 @@ struct TipJarView: View {
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
updatesObserver?.cancel()
|
updatesObserver?.cancel()
|
||||||
}
|
}
|
||||||
.onChange(of: showConfetti) { newValue in
|
.onReceive(Just(showConfetti).filter { $0 }.delay(for: .seconds(5), scheduler: DispatchQueue.main)) { _ in
|
||||||
if newValue {
|
|
||||||
Task {
|
|
||||||
try await Task.sleep(nanoseconds: 5 * NSEC_PER_SEC)
|
|
||||||
showConfetti = false
|
showConfetti = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var productsOrLoading: some View {
|
private var productsView: some View {
|
||||||
if isLoaded {
|
if isLoaded {
|
||||||
productsSections
|
VStack {
|
||||||
} else {
|
if !supporterProducts.isEmpty {
|
||||||
ProgressView()
|
supporterSubscriptions
|
||||||
.progressViewStyle(.circular)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
|
||||||
.listRowBackground(Color.clear)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
tipPurchases
|
||||||
private var productsSections: some View {
|
|
||||||
if let tipStatus {
|
if let tipStatus {
|
||||||
Section {
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
tipStatus
|
tipStatus
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.top, 16)
|
||||||
Text("Thank you!")
|
Text("Thank you!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.appGroupedListRowBackground()
|
} else {
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(.circular)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !supporterProducts.isEmpty {
|
@ViewBuilder
|
||||||
supporterSection
|
private var supporterSubscriptions: some View {
|
||||||
}
|
Text("If you want to contribute Tusker's continued development, you can become a supporter. Supporting Tusker is an auto-renewable monthly subscription.")
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
tipSection
|
.padding(.horizontal)
|
||||||
}
|
|
||||||
|
|
||||||
private var supporterSection: some View {
|
|
||||||
Section {
|
|
||||||
Text("If you want to contribute Tusker's continued development, you can become a supporter and give a montly tip.")
|
|
||||||
.multilineTextAlignment(.leading)
|
|
||||||
|
|
||||||
|
VStack(alignment: .myAlignment) {
|
||||||
ForEach($supporterProducts, id: \.0.id) { $productAndPurchasing in
|
ForEach($supporterProducts, id: \.0.id) { $productAndPurchasing in
|
||||||
TipRow(product: productAndPurchasing.0, buttonWidth: supporterButtonWidth, isPurchasing: $productAndPurchasing.1, showConfetti: $showConfetti)
|
TipRow(product: productAndPurchasing.0, buttonWidth: supporterButtonWidth, isPurchasing: $productAndPurchasing.1, showConfetti: $showConfetti)
|
||||||
}
|
}
|
||||||
} footer: {
|
|
||||||
VStack {
|
|
||||||
var privacyPolicy: AttributedString = "Privacy Policy"
|
|
||||||
let _ = privacyPolicy.link = URL(string: "https://vaccor.space/tusker#privacy")!
|
|
||||||
var eula: AttributedString = "EULA"
|
|
||||||
let _ = eula.link = URL(string: "https://www.apple.com/legal/internet-services/itunes/dev/stdeula/")!
|
|
||||||
Text(AttributedString("Supporting Tusker is an auto-renewable monthly subscription. Subscribing does not provide additional features or capabilities.\n") + privacyPolicy + AttributedString(" and ") + eula)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.appGroupedListRowBackground()
|
|
||||||
.onPreferenceChange(ButtonWidthKey.self) { newValue in
|
.onPreferenceChange(ButtonWidthKey.self) { newValue in
|
||||||
if let supporterButtonWidth {
|
if let supporterButtonWidth {
|
||||||
self.supporterButtonWidth = max(supporterButtonWidth, newValue)
|
self.supporterButtonWidth = max(supporterButtonWidth, newValue)
|
||||||
|
@ -144,16 +124,18 @@ struct TipJarView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var tipSection: some View {
|
@ViewBuilder
|
||||||
Section {
|
private var tipPurchases: some View {
|
||||||
Text("Or, you can choose to make a one-time tip to show your gratitutde or help support the app's development. It is greatly appreciated!")
|
Text("Or, you can choose to make a one-time tip to show your gratitutde or help support the app's development. It is greatly appreciated!")
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.top, 16)
|
||||||
|
|
||||||
|
VStack(alignment: .myAlignment) {
|
||||||
ForEach($tipProducts, id: \.0.id) { $productAndPurchasing in
|
ForEach($tipProducts, id: \.0.id) { $productAndPurchasing in
|
||||||
TipRow(product: productAndPurchasing.0, buttonWidth: tipButtonWidth, isPurchasing: $productAndPurchasing.1, showConfetti: $showConfetti)
|
TipRow(product: productAndPurchasing.0, buttonWidth: tipButtonWidth, isPurchasing: $productAndPurchasing.1, showConfetti: $showConfetti)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.appGroupedListRowBackground()
|
|
||||||
.onPreferenceChange(ButtonWidthKey.self) { newValue in
|
.onPreferenceChange(ButtonWidthKey.self) { newValue in
|
||||||
if let tipButtonWidth {
|
if let tipButtonWidth {
|
||||||
self.tipButtonWidth = max(tipButtonWidth, newValue)
|
self.tipButtonWidth = max(tipButtonWidth, newValue)
|
||||||
|
@ -249,8 +231,6 @@ private struct TipRow: View {
|
||||||
Text(product.displayName)
|
Text(product.displayName)
|
||||||
.alignmentGuide(.myAlignment, computeValue: { context in context[.trailing] })
|
.alignmentGuide(.myAlignment, computeValue: { context in context[.trailing] })
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
if let subscription = product.subscription {
|
if let subscription = product.subscription {
|
||||||
SubscriptionButton(product: product, subscriptionInfo: subscription, isPurchasing: $isPurchasing, buttonWidth: buttonWidth, purchase: purchase)
|
SubscriptionButton(product: product, subscriptionInfo: subscription, isPurchasing: $isPurchasing, buttonWidth: buttonWidth, purchase: purchase)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
// https://help.apple.com/xcode/#/dev745c5c974
|
// https://help.apple.com/xcode/#/dev745c5c974
|
||||||
|
|
||||||
MARKETING_VERSION = 2024.3
|
MARKETING_VERSION = 2024.3
|
||||||
CURRENT_PROJECT_VERSION = 133
|
CURRENT_PROJECT_VERSION = 132
|
||||||
CURRENT_PROJECT_VERSION = $(inherited)$(CURRENT_PROJECT_VERSION_BUILD_SUFFIX_$(CONFIGURATION))
|
CURRENT_PROJECT_VERSION = $(inherited)$(CURRENT_PROJECT_VERSION_BUILD_SUFFIX_$(CONFIGURATION))
|
||||||
|
|
||||||
CURRENT_PROJECT_VERSION_BUILD_SUFFIX_Debug=-dev
|
CURRENT_PROJECT_VERSION_BUILD_SUFFIX_Debug=-dev
|
||||||
|
|
Loading…
Reference in New Issue