Version 1.4 - Translations, Like toasts Queue redesign.
This commit is contained in:
@@ -10,32 +10,34 @@ import StoreKit
|
||||
|
||||
struct MainTabView: View {
|
||||
@Environment(MAService.self) private var service
|
||||
@State private var selectedTab: String = "library"
|
||||
|
||||
var body: some View {
|
||||
TabView {
|
||||
Tab("Library", systemImage: "music.note.list") {
|
||||
TabView(selection: $selectedTab) {
|
||||
Tab("Library", systemImage: "music.note.list", value: "library") {
|
||||
LibraryView()
|
||||
}
|
||||
|
||||
Tab("Favorites", systemImage: "heart.fill") {
|
||||
Tab("Favorites", systemImage: "heart.fill", value: "favorites") {
|
||||
FavoritesView()
|
||||
}
|
||||
|
||||
Tab("Search", systemImage: "magnifyingglass") {
|
||||
Tab("Search", systemImage: "magnifyingglass", value: "search") {
|
||||
NavigationStack {
|
||||
SearchView()
|
||||
.withMANavigation()
|
||||
}
|
||||
}
|
||||
|
||||
Tab("Players", systemImage: "speaker.wave.2.fill") {
|
||||
Tab("Players", systemImage: "speaker.wave.2.fill", value: "players") {
|
||||
PlayerListView()
|
||||
}
|
||||
|
||||
Tab("Settings", systemImage: "gear") {
|
||||
Tab("Settings", systemImage: "gear", value: "settings") {
|
||||
SettingsView()
|
||||
}
|
||||
}
|
||||
.withToast()
|
||||
.task {
|
||||
// Start listening to player events and load players when main view appears
|
||||
service.playerManager.startListening()
|
||||
@@ -386,8 +388,9 @@ struct PlayerRow: View {
|
||||
|
||||
struct SettingsView: View {
|
||||
@Environment(MAService.self) private var service
|
||||
@Environment(MAStoreManager.self) private var storeManager
|
||||
@Environment(\.themeManager) private var themeManager
|
||||
@Environment(\.localeManager) private var localeManager
|
||||
@Environment(MAStoreManager.self) private var storeManager
|
||||
@State private var showThankYou = false
|
||||
|
||||
var body: some View {
|
||||
@@ -435,6 +438,24 @@ struct SettingsView: View {
|
||||
Text("Choose how the app looks. System follows your device settings.")
|
||||
}
|
||||
|
||||
// Language Section
|
||||
Section {
|
||||
Picker("Language", selection: Binding(
|
||||
get: { localeManager.selectedLanguageCode ?? "system" },
|
||||
set: { localeManager.selectedLanguageCode = $0 == "system" ? nil : $0 }
|
||||
)) {
|
||||
Text("System").tag("system")
|
||||
ForEach(SupportedLanguage.allCases) { lang in
|
||||
Text(verbatim: lang.endonym).tag(lang.rawValue)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.menu)
|
||||
} header: {
|
||||
Text("Language")
|
||||
} footer: {
|
||||
Text("Choose the app language. System uses your device language.")
|
||||
}
|
||||
|
||||
// Connection Section
|
||||
Section {
|
||||
if let serverURL = service.authManager.serverURL {
|
||||
@@ -462,74 +483,67 @@ struct SettingsView: View {
|
||||
Label("Disconnect", systemImage: "arrow.right.square")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Support Development Section
|
||||
Section {
|
||||
if storeManager.products.isEmpty {
|
||||
HStack {
|
||||
if let loadError = storeManager.loadError {
|
||||
Label(loadError, systemImage: "exclamationmark.triangle")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
ForEach(storeManager.products, id: \.id) { product in
|
||||
HStack(spacing: 12) {
|
||||
Image(systemName: storeManager.iconName(for: product))
|
||||
.font(.title2)
|
||||
.foregroundStyle(.orange)
|
||||
.frame(width: 32)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(storeManager.tierName(for: product))
|
||||
.font(.body)
|
||||
.foregroundStyle(.primary)
|
||||
Text(product.displayPrice)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
ProgressView()
|
||||
Spacer()
|
||||
}
|
||||
} else {
|
||||
ForEach(storeManager.products, id: \.id) { product in
|
||||
|
||||
Button {
|
||||
Task {
|
||||
await storeManager.purchase(product)
|
||||
}
|
||||
Task { await storeManager.purchase(product) }
|
||||
} label: {
|
||||
HStack(spacing: 12) {
|
||||
Image(systemName: storeManager.iconName(for: product.id))
|
||||
.font(.title2)
|
||||
.foregroundStyle(.orange)
|
||||
.frame(width: 32)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(storeManager.tierName(for: product.id))
|
||||
.font(.body)
|
||||
.foregroundStyle(.primary)
|
||||
Text(product.description)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(product.displayPrice)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
.foregroundStyle(.orange)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 6)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(.orange.opacity(0.15))
|
||||
)
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
Text(product.displayPrice)
|
||||
.font(.subheadline.weight(.medium))
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 6)
|
||||
.background(Color.orange.opacity(0.15))
|
||||
.foregroundStyle(.orange)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(storeManager.isPurchasing)
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
} header: {
|
||||
Text("Support Development")
|
||||
} footer: {
|
||||
Text("Donations help keep this app updated and ad-free. Thank you!")
|
||||
Text("Do you find this app useful? Support the development by buying the developer a virtual record.")
|
||||
}
|
||||
|
||||
}
|
||||
.navigationTitle("Settings")
|
||||
.task {
|
||||
await storeManager.loadProducts()
|
||||
}
|
||||
.alert("Thank You!", isPresented: $showThankYou) {
|
||||
Button("OK", role: .cancel) { }
|
||||
Button("You're welcome!", role: .cancel) { }
|
||||
} message: {
|
||||
Text("Your support means a lot and helps keep this app alive!")
|
||||
Text("Your support means a lot and helps keep Mobile Music Assistant alive.")
|
||||
}
|
||||
.onChange(of: storeManager.purchaseResult) {
|
||||
if case .success = storeManager.purchaseResult {
|
||||
.onChange(of: storeManager.purchaseResult) { _, result in
|
||||
if case .success = result {
|
||||
showThankYou = true
|
||||
storeManager.purchaseResult = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user