Update SwiftUI navigation
This commit is contained in:
parent
6af0fda86f
commit
04ecb3226a
10 changed files with 266 additions and 188 deletions
|
@ -834,7 +834,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 22;
|
||||
CURRENT_PROJECT_VERSION = 23;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
||||
|
@ -869,7 +869,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 22;
|
||||
CURRENT_PROJECT_VERSION = 23;
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
||||
|
|
|
@ -74,9 +74,16 @@ struct BudgetDetailsView: View {
|
|||
await dataStore.loadOverview(showLoader: false)
|
||||
}
|
||||
#endif
|
||||
.navigationBarItems(trailing: Button(action: {
|
||||
dataStore.editBudget()
|
||||
}, label: { Text("edit") }))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing, content: {
|
||||
Button(
|
||||
action: {
|
||||
dataStore.editBudget()
|
||||
},
|
||||
label: { Text("edit") }
|
||||
)
|
||||
})
|
||||
}
|
||||
.sheet(
|
||||
isPresented: $dataStore.editingBudget,
|
||||
onDismiss: { Task {
|
||||
|
@ -85,12 +92,19 @@ struct BudgetDetailsView: View {
|
|||
content: {
|
||||
NavigationView {
|
||||
BudgetFormView(budget)
|
||||
.navigationBarItems(leading: Button(action: { Task {
|
||||
await dataStore.cancelEditBudget()
|
||||
}}, label: {
|
||||
Text("cancel")
|
||||
})
|
||||
.navigationTitle("edit_budget"))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading, content: {
|
||||
Button(
|
||||
action: {
|
||||
Task {
|
||||
await dataStore.cancelEditBudget()
|
||||
}
|
||||
},
|
||||
label: { Text("cancel") }
|
||||
)
|
||||
})
|
||||
}
|
||||
.navigationTitle("edit_budget")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -20,7 +20,7 @@ struct BudgetListsView: View {
|
|||
action: { await self.dataStore.getBudgets(count: nil, page: nil) },
|
||||
errorTextLocalizedStringKey: "budgets_load_failure"
|
||||
) { (budgets: [Budget]) in
|
||||
ForEach(budgets) { budget in
|
||||
List(budgets, selection: $dataStore.selectedBudget) { budget in
|
||||
BudgetListItemView(budget)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import TwigsCore
|
|||
|
||||
struct CategoryDetailsView: View {
|
||||
@EnvironmentObject var dataStore: DataStore
|
||||
@EnvironmentObject var categoryDataStore: CategoryDataStore
|
||||
@ObservedObject var categoryDataStore: CategoryDataStore
|
||||
@EnvironmentObject var apiService: TwigsApiService
|
||||
let budget: Budget
|
||||
@State var sum: Int? = 0
|
||||
|
@ -47,13 +47,17 @@ struct CategoryDetailsView: View {
|
|||
}.task {
|
||||
await categoryDataStore.sum(categoryId: category.id)
|
||||
}
|
||||
.navigationBarItems(trailing: Button(action: {
|
||||
Task {
|
||||
await dataStore.edit(category)
|
||||
}
|
||||
}) {
|
||||
Text("edit")
|
||||
})
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing, content: {
|
||||
Button(action: {
|
||||
Task {
|
||||
await dataStore.edit(category)
|
||||
}
|
||||
}) {
|
||||
Text("edit")
|
||||
}
|
||||
})
|
||||
}
|
||||
.sheet(isPresented: self.$dataStore.editingCategory, onDismiss: {
|
||||
self.dataStore.cancelEditCategory()
|
||||
}, content: {
|
||||
|
@ -66,8 +70,9 @@ struct CategoryDetailsView: View {
|
|||
}
|
||||
}
|
||||
|
||||
init (_ budget: Budget) {
|
||||
init (_ budget: Budget, categoryDataStore: CategoryDataStore) {
|
||||
self.budget = budget
|
||||
self.categoryDataStore = categoryDataStore
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +90,7 @@ struct LabeledCounter: View {
|
|||
#if DEBUG
|
||||
struct CategoryDetailsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CategoryDetailsView(MockBudgetRepository.budget)
|
||||
CategoryDetailsView(MockBudgetRepository.budget, categoryDataStore: CategoryDataStore(TwigsInMemoryCacheService()))
|
||||
.environmentObject(TwigsInMemoryCacheService())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ struct CategoryListView: View {
|
|||
|
||||
@ViewBuilder
|
||||
var body: some View {
|
||||
List {
|
||||
List(selection: $dataStore.selectedCategory) {
|
||||
InlineLoadingView(
|
||||
data: $dataStore.categories,
|
||||
action: { await self.dataStore.getCategories(budgetId: budget.id, expense: nil, archived: nil, count: nil, page: nil) },
|
||||
|
@ -101,32 +101,25 @@ struct CategoryListItemView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationLink(
|
||||
tag: category,
|
||||
selection: $dataStore.selectedCategory,
|
||||
destination: {
|
||||
CategoryDetailsView(self.budget)
|
||||
.environmentObject(categoryDataStore)
|
||||
.navigationBarTitle(dataStore.selectedCategory?.title ?? "")
|
||||
},
|
||||
label: {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text(verbatim: category.title)
|
||||
Spacer()
|
||||
remaining
|
||||
}
|
||||
if category.description?.isEmpty == false {
|
||||
Text(verbatim: category.description!)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
progressView
|
||||
}.task {
|
||||
await categoryDataStore.sum(categoryId: category.id)
|
||||
NavigationLink(value: category, label: {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text(verbatim: category.title)
|
||||
Spacer()
|
||||
remaining
|
||||
}
|
||||
})
|
||||
if category.description?.isEmpty == false {
|
||||
Text(verbatim: category.description!)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
progressView
|
||||
}.task {
|
||||
await categoryDataStore.sum(categoryId: category.id)
|
||||
}
|
||||
})
|
||||
.environmentObject(categoryDataStore)
|
||||
}
|
||||
|
||||
var progressView: ProgressView {
|
||||
|
|
|
@ -46,6 +46,23 @@ class DataStore : ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
var selectedBudget: Budget? {
|
||||
get {
|
||||
if case let .success(budget) = self.budget {
|
||||
return budget
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
set {
|
||||
if let budget = newValue {
|
||||
self.budget = .success(budget)
|
||||
} else {
|
||||
self.budget = .empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var budgetId: String? {
|
||||
get {
|
||||
if case let .success(budget) = self.budget {
|
||||
|
|
|
@ -19,7 +19,7 @@ struct RecurringTransactionsListView: View {
|
|||
action: { await self.dataStore.getRecurringTransactions() },
|
||||
errorTextLocalizedStringKey: "Failed to load recurring transactions"
|
||||
) { (transactions: OrderedDictionary<String, [RecurringTransaction]>) in
|
||||
List {
|
||||
List(selection: $dataStore.selectedRecurringTransaction) {
|
||||
ForEach(transactions.keys, id: \.self) { (key: String) in
|
||||
Group {
|
||||
if !transactions[key]!.isEmpty {
|
||||
|
@ -82,35 +82,31 @@ struct RecurringTransactionsListItemView: View {
|
|||
|
||||
var body: some View {
|
||||
NavigationLink(
|
||||
tag: transaction,
|
||||
selection: $dataStore.selectedRecurringTransaction,
|
||||
destination: {
|
||||
RecurringTransactionDetailsView()
|
||||
.navigationBarTitle("details", displayMode: .inline)
|
||||
}
|
||||
) {
|
||||
HStack {
|
||||
VStack(alignment: .leading) {
|
||||
Text(verbatim: transaction.title)
|
||||
.lineLimit(1)
|
||||
.font(.headline)
|
||||
if let description = transaction.description?.trimmingCharacters(in: CharacterSet([" "])), !description.isEmpty {
|
||||
Text(verbatim: description)
|
||||
value: transaction,
|
||||
label: {
|
||||
HStack {
|
||||
VStack(alignment: .leading) {
|
||||
Text(verbatim: transaction.title)
|
||||
.lineLimit(1)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.font(.headline)
|
||||
if let description = transaction.description?.trimmingCharacters(in: CharacterSet([" "])), !description.isEmpty {
|
||||
Text(verbatim: description)
|
||||
.lineLimit(1)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.trailing)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
VStack(alignment: .trailing) {
|
||||
Text(verbatim: transaction.amount.toCurrencyString())
|
||||
.foregroundColor(transaction.expense ? .red : .green)
|
||||
.multilineTextAlignment(.trailing)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
VStack(alignment: .trailing) {
|
||||
Text(verbatim: transaction.amount.toCurrencyString())
|
||||
.foregroundColor(transaction.expense ? .red : .green)
|
||||
.multilineTextAlignment(.trailing)
|
||||
}
|
||||
.padding(.leading)
|
||||
}.padding(5.0)
|
||||
}
|
||||
.padding(.leading)
|
||||
}.padding(5.0)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,43 +18,66 @@ struct SidebarBudgetView: View {
|
|||
@ViewBuilder
|
||||
var mainView: some View {
|
||||
if case let .success(budget) = self.dataStore.budget {
|
||||
NavigationView {
|
||||
List {
|
||||
NavigationLink(
|
||||
tag: 0,
|
||||
selection: $tabSelection,
|
||||
destination: { BudgetDetailsView(budget: budget).navigationBarTitle("overview")
|
||||
},
|
||||
label: { Label("overview", systemImage: "chart.line.uptrend.xyaxis") }
|
||||
)
|
||||
NavigationSplitView(sidebar: {
|
||||
VStack {
|
||||
List(selection: $tabSelection) {
|
||||
NavigationLink(
|
||||
value: 0,
|
||||
label: { Label("overview", systemImage: "chart.line.uptrend.xyaxis") }
|
||||
)
|
||||
.keyboardShortcut("1")
|
||||
NavigationLink(
|
||||
tag: 1,
|
||||
selection: $tabSelection,
|
||||
destination: { TransactionListView<EmptyView>().navigationBarTitle("transactions") },
|
||||
label: { Label("transactions", systemImage: "dollarsign.circle") })
|
||||
NavigationLink(
|
||||
value: 1,
|
||||
label: { Label("transactions", systemImage: "dollarsign.circle") }
|
||||
)
|
||||
.keyboardShortcut("2")
|
||||
NavigationLink(
|
||||
tag: 2,
|
||||
selection: $tabSelection,
|
||||
destination: { CategoryListView(budget).navigationBarTitle("categories") },
|
||||
label: { Label("categories", systemImage: "chart.pie") })
|
||||
NavigationLink(
|
||||
value: 2,
|
||||
label: { Label("categories", systemImage: "chart.pie") }
|
||||
)
|
||||
.keyboardShortcut("3")
|
||||
NavigationLink(
|
||||
tag: 3,
|
||||
selection: $tabSelection,
|
||||
destination: { RecurringTransactionsListView().navigationBarTitle("recurring_transactions") },
|
||||
label: { Label("recurring_transactions", systemImage: "arrow.triangle.2.circlepath") })
|
||||
NavigationLink(
|
||||
value: 3,
|
||||
label: { Label("recurring_transactions", systemImage: "arrow.triangle.2.circlepath") }
|
||||
)
|
||||
.keyboardShortcut("4")
|
||||
Divider()
|
||||
}
|
||||
BudgetListsView()
|
||||
}
|
||||
.navigationTitle(budget.name)
|
||||
if self.tabSelection ?? 0 > 0 {
|
||||
EmptyView()
|
||||
EmptyView()
|
||||
}, content: {
|
||||
if tabSelection == 0, let budget = dataStore.selectedBudget {
|
||||
BudgetDetailsView(budget: budget)
|
||||
.navigationTitle("budgets")
|
||||
} else if tabSelection == 1 {
|
||||
TransactionListView<EmptyView>()
|
||||
.navigationTitle("transactions")
|
||||
} else if tabSelection == 2, let budget = dataStore.selectedBudget {
|
||||
CategoryListView(budget)
|
||||
.navigationTitle("categories")
|
||||
} else if tabSelection == 3 {
|
||||
RecurringTransactionsListView()
|
||||
.navigationTitle("recurring_transactions")
|
||||
} else {
|
||||
ActivityIndicator(isAnimating: .constant(true), style: .large)
|
||||
}
|
||||
}
|
||||
}, detail: {
|
||||
if let _ = dataStore.selectedTransaction {
|
||||
TransactionDetailsView()
|
||||
.navigationTitle("details")
|
||||
.onDisappear {
|
||||
dataStore.selectedTransaction = nil
|
||||
}
|
||||
} else if let _ = dataStore.selectedCategory {
|
||||
if let budget = dataStore.selectedBudget {
|
||||
CategoryDetailsView(budget, categoryDataStore: CategoryDataStore(dataStore.apiService))
|
||||
.navigationTitle(dataStore.selectedCategory?.title ?? "")
|
||||
}
|
||||
} else if let _ = dataStore.selectedRecurringTransaction {
|
||||
RecurringTransactionDetailsView()
|
||||
.navigationTitle("details")
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ActivityIndicator(isAnimating: .constant(true), style: .large)
|
||||
}
|
||||
|
|
|
@ -21,60 +21,100 @@ struct TabbedBudgetView: View {
|
|||
TabView(selection: $tabSelection) {
|
||||
NavigationView {
|
||||
BudgetDetailsView(budget: budget)
|
||||
.navigationBarTitle("overview")
|
||||
.navigationBarItems(leading: HStack {
|
||||
Button("budgets", action: {
|
||||
self.dataStore.showBudgetSelection = true
|
||||
}).padding()
|
||||
})
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
HStack {
|
||||
Button("budgets", action: {
|
||||
self.dataStore.showBudgetSelection = true
|
||||
}).padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle(budget.name)
|
||||
}
|
||||
.tabItem {
|
||||
Image(systemName: "chart.line.uptrend.xyaxis.circle.fill")
|
||||
Text("overview")
|
||||
}
|
||||
.tag(0)
|
||||
.keyboardShortcut("1")
|
||||
NavigationView {
|
||||
TransactionListView<EmptyView>()
|
||||
.navigationBarTitle("transactions")
|
||||
}
|
||||
.tabItem {
|
||||
Image(systemName: "dollarsign.circle.fill")
|
||||
Text("transactions")
|
||||
}
|
||||
.tag(1)
|
||||
.keyboardShortcut("2")
|
||||
NavigationView {
|
||||
CategoryListView(budget)
|
||||
.navigationBarTitle("categories")
|
||||
}
|
||||
.tabItem {
|
||||
Image(systemName: "chart.pie.fill")
|
||||
Text("categories")
|
||||
}
|
||||
.tag(2)
|
||||
.keyboardShortcut("3")
|
||||
NavigationView {
|
||||
RecurringTransactionsListView()
|
||||
.navigationBarTitle("recurring_transactions")
|
||||
}
|
||||
.tabItem {
|
||||
Image(systemName: "arrow.triangle.2.circlepath.circle.fill")
|
||||
Text("recurring")
|
||||
}
|
||||
.tag(3)
|
||||
.keyboardShortcut("4")
|
||||
NavigationView {
|
||||
ProfileView()
|
||||
.navigationBarTitle("profile")
|
||||
}
|
||||
.tabItem {
|
||||
Image(systemName: "person.circle.fill")
|
||||
Text("profile")
|
||||
}
|
||||
.tag(4)
|
||||
.keyboardShortcut("5")
|
||||
.tabItem {
|
||||
Image(systemName: "chart.line.uptrend.xyaxis.circle.fill")
|
||||
Text("overview")
|
||||
}
|
||||
.tag(0)
|
||||
.keyboardShortcut("1")
|
||||
NavigationSplitView(
|
||||
sidebar: {
|
||||
TransactionListView<EmptyView>()
|
||||
.navigationTitle(budget.name)
|
||||
},
|
||||
detail: {
|
||||
if let _ = dataStore.selectedTransaction {
|
||||
TransactionDetailsView()
|
||||
.navigationTitle("details")
|
||||
.onDisappear {
|
||||
dataStore.selectedTransaction = nil
|
||||
}
|
||||
} else {
|
||||
ActivityIndicator(isAnimating: .constant(true), style: .large)
|
||||
}
|
||||
})
|
||||
.tabItem {
|
||||
Image(systemName: "dollarsign.circle.fill")
|
||||
Text("transactions")
|
||||
}
|
||||
.tag(1)
|
||||
.keyboardShortcut("2")
|
||||
NavigationSplitView(
|
||||
sidebar: {
|
||||
CategoryListView(budget)
|
||||
.navigationTitle(budget.name)
|
||||
},
|
||||
content: {
|
||||
if let _ = dataStore.selectedCategory {
|
||||
if let budget = dataStore.selectedBudget {
|
||||
CategoryDetailsView(budget, categoryDataStore: CategoryDataStore(dataStore.apiService))
|
||||
.navigationTitle(dataStore.selectedCategory?.title ?? "")
|
||||
}
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
if let _ = dataStore.selectedTransaction {
|
||||
TransactionDetailsView()
|
||||
.navigationTitle("details")
|
||||
} else {
|
||||
ActivityIndicator(isAnimating: .constant(true), style: .large)
|
||||
}
|
||||
})
|
||||
.tabItem {
|
||||
Image(systemName: "chart.pie.fill")
|
||||
Text("categories")
|
||||
}
|
||||
.tag(2)
|
||||
.keyboardShortcut("3")
|
||||
NavigationSplitView(
|
||||
sidebar: {
|
||||
RecurringTransactionsListView()
|
||||
.navigationTitle(budget.name)
|
||||
},
|
||||
detail: {
|
||||
if let _ = dataStore.selectedRecurringTransaction {
|
||||
RecurringTransactionDetailsView()
|
||||
.navigationTitle("details")
|
||||
} else {
|
||||
ActivityIndicator(isAnimating: .constant(true), style: .large)
|
||||
}
|
||||
})
|
||||
.tabItem {
|
||||
Image(systemName: "arrow.triangle.2.circlepath.circle.fill")
|
||||
Text("recurring")
|
||||
}
|
||||
.tag(3)
|
||||
.keyboardShortcut("4")
|
||||
ProfileView()
|
||||
.tabItem {
|
||||
Image(systemName: "person.circle.fill")
|
||||
Text("profile")
|
||||
}
|
||||
.tag(4)
|
||||
.keyboardShortcut("5")
|
||||
}
|
||||
.navigationTitle(budget.name)
|
||||
default:
|
||||
ActivityIndicator(isAnimating: .constant(true), style: .large)
|
||||
}
|
||||
|
@ -91,9 +131,7 @@ struct TabbedBudgetView: View {
|
|||
content: {
|
||||
NavigationView {
|
||||
VStack {
|
||||
List {
|
||||
BudgetListsView().environmentObject(dataStore)
|
||||
}
|
||||
BudgetListsView().environmentObject(dataStore)
|
||||
.navigationTitle("budgets")
|
||||
.navigationBarItems(trailing: Button(action: {dataStore.newBudget()}, label: {
|
||||
Image(systemName: "plus")
|
||||
|
|
|
@ -91,7 +91,7 @@ struct TransactionListView<Content>: View where Content: View {
|
|||
action: { await dataStore.getTransactions() },
|
||||
errorTextLocalizedStringKey: "Failed to load transactions"
|
||||
) { transactions in
|
||||
List {
|
||||
List(selection: $dataStore.selectedTransaction) {
|
||||
TransactionList(transactions)
|
||||
}
|
||||
.searchable(text: $search)
|
||||
|
@ -134,37 +134,29 @@ struct TransactionListItemView: View {
|
|||
var transaction: TwigsCore.Transaction
|
||||
|
||||
var body: some View {
|
||||
NavigationLink(
|
||||
tag: self.transaction,
|
||||
selection: self.$dataStore.selectedTransaction,
|
||||
destination: {
|
||||
TransactionDetailsView()
|
||||
.navigationBarTitle("details", displayMode: .inline)
|
||||
},
|
||||
label: {
|
||||
HStack {
|
||||
VStack(alignment: .leading) {
|
||||
Text(verbatim: transaction.title)
|
||||
NavigationLink(value: self.transaction, label: {
|
||||
HStack {
|
||||
VStack(alignment: .leading) {
|
||||
Text(verbatim: transaction.title)
|
||||
.lineLimit(1)
|
||||
.font(.headline)
|
||||
if let description = transaction.description?.trimmingCharacters(in: CharacterSet([" "])), !description.isEmpty {
|
||||
Text(verbatim: description)
|
||||
.lineLimit(1)
|
||||
.font(.headline)
|
||||
if let description = transaction.description?.trimmingCharacters(in: CharacterSet([" "])), !description.isEmpty {
|
||||
Text(verbatim: description)
|
||||
.lineLimit(1)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.trailing)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
VStack(alignment: .trailing) {
|
||||
Text(verbatim: transaction.amount.toCurrencyString())
|
||||
.foregroundColor(transaction.expense ? .red : .green)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.trailing)
|
||||
}
|
||||
.padding(.leading)
|
||||
}.padding(5.0)
|
||||
}
|
||||
)
|
||||
}
|
||||
Spacer()
|
||||
VStack(alignment: .trailing) {
|
||||
Text(verbatim: transaction.amount.toCurrencyString())
|
||||
.foregroundColor(transaction.expense ? .red : .green)
|
||||
.multilineTextAlignment(.trailing)
|
||||
}
|
||||
.padding(.leading)
|
||||
}.padding(5.0)
|
||||
})
|
||||
}
|
||||
|
||||
init (_ transaction: TwigsCore.Transaction) {
|
||||
|
|
Loading…
Reference in a new issue