mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-12-26 00:50:38 +00:00
Add more lists setttings
This commit is contained in:
parent
d2f7ab1464
commit
2e2a9f5f14
12 changed files with 1665 additions and 98 deletions
|
@ -82,6 +82,9 @@ extension View {
|
|||
case let .mentionStatusEditor(account, visibility):
|
||||
StatusEditorView(mode: .mention(account: account, visibility: visibility))
|
||||
.withEnvironments()
|
||||
case .listCreate:
|
||||
ListCreateView()
|
||||
.withEnvironments()
|
||||
case let .listEdit(list):
|
||||
ListEditView(list: list)
|
||||
.withEnvironments()
|
||||
|
|
|
@ -143,6 +143,11 @@ struct TimelineTab: View {
|
|||
Label(list.title, systemImage: "list.bullet")
|
||||
}
|
||||
}
|
||||
Button {
|
||||
routerPath.presentedSheet = .listCreate
|
||||
} label: {
|
||||
Label("account.list.create", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,8 +22,6 @@ public struct AccountDetailView: View {
|
|||
|
||||
@State private var viewModel: AccountDetailViewModel
|
||||
@State private var isCurrentUser: Bool = false
|
||||
@State private var isCreateListAlertPresented: Bool = false
|
||||
@State private var createListTitle: String = ""
|
||||
@State private var showBlockConfirmation: Bool = false
|
||||
|
||||
@State private var isEditingAccount: Bool = false
|
||||
|
@ -262,7 +260,7 @@ public struct AccountDetailView: View {
|
|||
}
|
||||
}
|
||||
Button("account.list.create") {
|
||||
isCreateListAlertPresented = true
|
||||
routerPath.presentedSheet = .listCreate
|
||||
}
|
||||
.tint(theme.tintColor)
|
||||
.buttonStyle(.borderless)
|
||||
|
@ -271,23 +269,6 @@ public struct AccountDetailView: View {
|
|||
.task {
|
||||
await currentAccount.fetchLists()
|
||||
}
|
||||
.alert("account.list.create", isPresented: $isCreateListAlertPresented) {
|
||||
TextField("account.list.name", text: $createListTitle)
|
||||
Button("action.cancel") {
|
||||
isCreateListAlertPresented = false
|
||||
createListTitle = ""
|
||||
}
|
||||
Button("account.list.create.confirm") {
|
||||
guard !createListTitle.isEmpty else { return }
|
||||
isCreateListAlertPresented = false
|
||||
Task {
|
||||
await currentAccount.createList(title: createListTitle)
|
||||
createListTitle = ""
|
||||
}
|
||||
}
|
||||
} message: {
|
||||
Text("account.list.create.description")
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
|
|
@ -87,15 +87,7 @@ import Observation
|
|||
tags = []
|
||||
}
|
||||
}
|
||||
|
||||
public func createList(title: String) async {
|
||||
guard let client else { return }
|
||||
do {
|
||||
let list: Models.List = try await client.post(endpoint: Lists.createList(title: title))
|
||||
lists.append(list)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
|
||||
public func deleteList(list: Models.List) async {
|
||||
guard let client else { return }
|
||||
lists.removeAll(where: { $0.id == list.id })
|
||||
|
|
|
@ -42,6 +42,7 @@ public enum SheetDestination: Identifiable {
|
|||
case replyToStatusEditor(status: Status)
|
||||
case quoteStatusEditor(status: Status)
|
||||
case mentionStatusEditor(account: Account, visibility: Models.Visibility)
|
||||
case listCreate
|
||||
case listEdit(list: Models.List)
|
||||
case listAddAccount(account: Account)
|
||||
case addAccount
|
||||
|
@ -59,6 +60,8 @@ public enum SheetDestination: Identifiable {
|
|||
case .editStatusEditor, .newStatusEditor, .replyToStatusEditor, .quoteStatusEditor,
|
||||
.mentionStatusEditor, .settings, .accountPushNotficationsSettings:
|
||||
"statusEditor"
|
||||
case .listCreate:
|
||||
"listCreate"
|
||||
case .listEdit:
|
||||
"listEdit"
|
||||
case .listAddAccount:
|
||||
|
|
|
@ -12,9 +12,6 @@ public struct ListAddAccountView: View {
|
|||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@State private var viewModel: ListAddAccountViewModel
|
||||
|
||||
@State private var isCreateListAlertPresented: Bool = false
|
||||
@State private var createListTitle: String = ""
|
||||
|
||||
public init(account: Account) {
|
||||
_viewModel = .init(initialValue: .init(account: account))
|
||||
}
|
||||
|
@ -40,10 +37,6 @@ public struct ListAddAccountView: View {
|
|||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
Button("lists.create") {
|
||||
isCreateListAlertPresented = true
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.background(theme.secondaryBackgroundColor)
|
||||
|
@ -56,23 +49,6 @@ public struct ListAddAccountView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.alert("lists.create", isPresented: $isCreateListAlertPresented) {
|
||||
TextField("lists.name", text: $createListTitle)
|
||||
Button("action.cancel") {
|
||||
isCreateListAlertPresented = false
|
||||
createListTitle = ""
|
||||
}
|
||||
Button("lists.create.confirm") {
|
||||
guard !createListTitle.isEmpty else { return }
|
||||
isCreateListAlertPresented = false
|
||||
Task {
|
||||
await currentAccount.createList(title: createListTitle)
|
||||
createListTitle = ""
|
||||
}
|
||||
}
|
||||
} message: {
|
||||
Text("lists.name.message")
|
||||
}
|
||||
}
|
||||
.task {
|
||||
viewModel.client = client
|
||||
|
|
65
Packages/Lists/Sources/Lists/Create/ListCreateView.swift
Normal file
65
Packages/Lists/Sources/Lists/Create/ListCreateView.swift
Normal file
|
@ -0,0 +1,65 @@
|
|||
import DesignSystem
|
||||
import EmojiText
|
||||
import Models
|
||||
import Network
|
||||
import SwiftUI
|
||||
import Env
|
||||
|
||||
@MainActor
|
||||
public struct ListCreateView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(Client.self) private var client
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
|
||||
@State private var title = ""
|
||||
@State private var repliesPolicy: Models.List.RepliesPolicy = .list
|
||||
@State private var isExclusive: Bool = false
|
||||
@State private var isSaving: Bool = false
|
||||
|
||||
public init() { }
|
||||
|
||||
public var body: some View {
|
||||
NavigationStack {
|
||||
Form {
|
||||
Section("lists.edit.settings") {
|
||||
TextField("list.edit.title", text: $title)
|
||||
Picker("list.edit.repliesPolicy",
|
||||
selection: $repliesPolicy) {
|
||||
ForEach(Models.List.RepliesPolicy.allCases) { policy in
|
||||
Text(policy.title)
|
||||
.tag(policy)
|
||||
}
|
||||
}
|
||||
Toggle("list.edit.isExclusive", isOn: $isExclusive)
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.background(theme.secondaryBackgroundColor)
|
||||
.toolbar {
|
||||
ToolbarItem {
|
||||
Button {
|
||||
Task {
|
||||
isSaving = true
|
||||
let _: Models.List = try await client.post(endpoint: Lists.createList(title: title,
|
||||
repliesPolicy: repliesPolicy,
|
||||
exclusive: isExclusive ))
|
||||
await currentAccount.fetchLists()
|
||||
isSaving = false
|
||||
dismiss()
|
||||
}
|
||||
} label: {
|
||||
if isSaving {
|
||||
ProgressView()
|
||||
} else {
|
||||
Text("lists.create.confirm")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle(title)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,7 +18,29 @@ public struct ListEditView: View {
|
|||
|
||||
public var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
Form {
|
||||
Section("lists.edit.settings") {
|
||||
TextField("list.edit.title", text: $viewModel.title) {
|
||||
Task { await viewModel.update() }
|
||||
}
|
||||
Picker("list.edit.repliesPolicy",
|
||||
selection: $viewModel.repliesPolicy) {
|
||||
ForEach(Models.List.RepliesPolicy.allCases) { policy in
|
||||
Text(policy.title)
|
||||
.tag(policy)
|
||||
}
|
||||
}
|
||||
Toggle("list.edit.isExclusive", isOn: $viewModel.isExclusive)
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
.disabled(viewModel.isUpdating)
|
||||
.onChange(of: viewModel.repliesPolicy) { _, _ in
|
||||
Task { await viewModel.update() }
|
||||
}
|
||||
.onChange(of: viewModel.isExclusive) { _, _ in
|
||||
Task { await viewModel.update() }
|
||||
}
|
||||
|
||||
Section("lists.edit.users-in-list") {
|
||||
if viewModel.isLoadingAccounts {
|
||||
HStack {
|
||||
|
@ -26,7 +48,6 @@ public struct ListEditView: View {
|
|||
ProgressView()
|
||||
Spacer()
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
} else {
|
||||
ForEach(viewModel.accounts) { account in
|
||||
HStack {
|
||||
|
@ -41,7 +62,6 @@ public struct ListEditView: View {
|
|||
.font(.scaledFootnote)
|
||||
}
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}.onDelete { indexes in
|
||||
if let index = indexes.first {
|
||||
Task {
|
||||
|
@ -52,6 +72,7 @@ public struct ListEditView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.background(theme.secondaryBackgroundColor)
|
||||
|
|
|
@ -3,18 +3,28 @@ import Models
|
|||
import Network
|
||||
import Observation
|
||||
import SwiftUI
|
||||
import Env
|
||||
|
||||
@MainActor
|
||||
@Observable public class ListEditViewModel {
|
||||
let list: Models.List
|
||||
var list: Models.List
|
||||
|
||||
var client: Client?
|
||||
|
||||
var isLoadingAccounts: Bool = true
|
||||
var accounts: [Account] = []
|
||||
|
||||
var title: String
|
||||
var repliesPolicy: Models.List.RepliesPolicy
|
||||
var isExclusive: Bool
|
||||
|
||||
var isUpdating: Bool = false
|
||||
|
||||
init(list: Models.List) {
|
||||
self.list = list
|
||||
self.title = list.title
|
||||
self.repliesPolicy = list.repliesPolicy
|
||||
self.isExclusive = list.exclusive
|
||||
}
|
||||
|
||||
func fetchAccounts() async {
|
||||
|
@ -27,7 +37,27 @@ import SwiftUI
|
|||
isLoadingAccounts = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func update() async {
|
||||
guard let client else { return }
|
||||
do {
|
||||
isUpdating = true
|
||||
let list: Models.List = try await client.put(endpoint:
|
||||
Lists.updateList(id: list.id,
|
||||
title: title,
|
||||
repliesPolicy: repliesPolicy,
|
||||
exclusive: isExclusive ))
|
||||
self.list = list
|
||||
self.title = list.title
|
||||
self.repliesPolicy = list.repliesPolicy
|
||||
self.isExclusive = list.exclusive
|
||||
self.isUpdating = false
|
||||
await CurrentAccount.shared.fetchLists()
|
||||
} catch {
|
||||
isUpdating = false
|
||||
}
|
||||
}
|
||||
|
||||
func delete(account: Account) async {
|
||||
guard let client else { return }
|
||||
do {
|
||||
|
@ -38,3 +68,16 @@ import SwiftUI
|
|||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
extension Models.List.RepliesPolicy {
|
||||
var title: LocalizedStringKey {
|
||||
switch self {
|
||||
case .followed:
|
||||
return "list.repliesPolicy.followed"
|
||||
case .list:
|
||||
return "list.repliesPolicy.list"
|
||||
case .none:
|
||||
return "list.repliesPolicy.none"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,16 @@ import Foundation
|
|||
public struct List: Codable, Identifiable, Equatable, Hashable {
|
||||
public let id: String
|
||||
public let title: String
|
||||
public let repliesPolicy: String
|
||||
public let repliesPolicy: RepliesPolicy
|
||||
public let exclusive: Bool
|
||||
|
||||
public enum RepliesPolicy: String, Sendable, Codable, CaseIterable, Identifiable {
|
||||
public var id: String {
|
||||
rawValue
|
||||
}
|
||||
|
||||
case followed, list, `none`
|
||||
}
|
||||
}
|
||||
|
||||
extension List: Sendable {}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import Foundation
|
||||
import Models
|
||||
|
||||
public enum Lists: Endpoint {
|
||||
case lists
|
||||
case list(id: String)
|
||||
case createList(title: String)
|
||||
case createList(title: String, repliesPolicy: List.RepliesPolicy, exclusive: Bool)
|
||||
case updateList(id: String, title: String, repliesPolicy: List.RepliesPolicy, exclusive: Bool)
|
||||
case accounts(listId: String)
|
||||
case updateAccounts(listId: String, accounts: [String])
|
||||
|
||||
|
@ -11,7 +13,7 @@ public enum Lists: Endpoint {
|
|||
switch self {
|
||||
case .lists, .createList:
|
||||
"lists"
|
||||
case let .list(id):
|
||||
case let .list(id), let .updateList(id, _, _, _):
|
||||
"lists/\(id)"
|
||||
case let .accounts(listId):
|
||||
"lists/\(listId)/accounts"
|
||||
|
@ -24,8 +26,11 @@ public enum Lists: Endpoint {
|
|||
switch self {
|
||||
case .accounts:
|
||||
return [.init(name: "limit", value: String(0))]
|
||||
case let .createList(title):
|
||||
return [.init(name: "title", value: title)]
|
||||
case let .createList(title, repliesPolicy, exclusive),
|
||||
let .updateList(_, title, repliesPolicy, exclusive):
|
||||
return [.init(name: "title", value: title),
|
||||
.init(name: "replies_policy", value: repliesPolicy.rawValue),
|
||||
.init(name: "exclusive", value: exclusive ? "true" : "false")]
|
||||
case let .updateAccounts(_, accounts):
|
||||
var params: [URLQueryItem] = []
|
||||
for account in accounts {
|
||||
|
|
Loading…
Reference in a new issue