151 lines
4.9 KiB
Swift
151 lines
4.9 KiB
Swift
//
|
|
// Swiftfin is subject to the terms of the Mozilla Public
|
|
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
//
|
|
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
extension SelectUserView {
|
|
|
|
struct SelectUserBottomBar: View {
|
|
|
|
@Binding
|
|
private var isEditing: Bool
|
|
|
|
@Binding
|
|
private var serverSelection: SelectUserServerSelection
|
|
|
|
@ObservedObject
|
|
private var viewModel: SelectUserViewModel
|
|
|
|
private let areUsersSelected: Bool
|
|
private let userCount: Int
|
|
|
|
private let onDelete: () -> Void
|
|
private let toggleAllUsersSelected: () -> Void
|
|
|
|
// MARK: - Advanced Menu
|
|
|
|
@ViewBuilder
|
|
private var advancedMenu: some View {
|
|
Menu {
|
|
Button(L10n.editUsers, systemImage: "person.crop.circle") {
|
|
isEditing.toggle()
|
|
}
|
|
// TODO: Advanced settings on tvOS?
|
|
//
|
|
// Divider()
|
|
//
|
|
// Button(L10n.advanced, systemImage: "gearshape.fill") {
|
|
// router.route(to: \.advancedSettings)
|
|
// }
|
|
} label: {
|
|
Label(L10n.advanced, systemImage: "gearshape.fill")
|
|
.font(.body.weight(.semibold))
|
|
.foregroundStyle(Color.primary)
|
|
.labelStyle(.iconOnly)
|
|
.frame(width: 50, height: 50)
|
|
}
|
|
|
|
// TODO: Do we want to support a grid view and list view like iOS?
|
|
// if !viewModel.servers.isEmpty {
|
|
// Picker(selection: $userListDisplayType) {
|
|
// ForEach(LibraryDisplayType.allCases, id: \.hashValue) {
|
|
// Label($0.displayTitle, systemImage: $0.systemImage)
|
|
// .tag($0)
|
|
// }
|
|
// } label: {
|
|
// Text(L10n.layout)
|
|
// Text(userListDisplayType.displayTitle)
|
|
// Image(systemName: userListDisplayType.systemImage)
|
|
// }
|
|
// .pickerStyle(.menu)
|
|
// }
|
|
}
|
|
|
|
// MARK: - Delete User Button
|
|
|
|
private var deleteUsersButton: some View {
|
|
ListRowButton(L10n.delete, role: .destructive) {
|
|
onDelete()
|
|
}
|
|
.frame(width: 400, height: 50)
|
|
.disabled(!areUsersSelected)
|
|
}
|
|
|
|
// MARK: - Initializer
|
|
|
|
init(
|
|
isEditing: Binding<Bool>,
|
|
serverSelection: Binding<SelectUserServerSelection>,
|
|
areUsersSelected: Bool,
|
|
viewModel: SelectUserViewModel,
|
|
userCount: Int,
|
|
onDelete: @escaping () -> Void,
|
|
toggleAllUsersSelected: @escaping () -> Void
|
|
) {
|
|
self._isEditing = isEditing
|
|
self._serverSelection = serverSelection
|
|
self.viewModel = viewModel
|
|
self.areUsersSelected = areUsersSelected
|
|
self.userCount = userCount
|
|
self.onDelete = onDelete
|
|
self.toggleAllUsersSelected = toggleAllUsersSelected
|
|
}
|
|
|
|
// MARK: - Content View
|
|
|
|
@ViewBuilder
|
|
private var contentView: some View {
|
|
HStack(alignment: .center) {
|
|
if isEditing {
|
|
deleteUsersButton
|
|
|
|
Button {
|
|
toggleAllUsersSelected()
|
|
} label: {
|
|
Text(areUsersSelected ? L10n.removeAll : L10n.selectAll)
|
|
.foregroundStyle(Color.primary)
|
|
.font(.body.weight(.semibold))
|
|
.frame(width: 200, height: 50)
|
|
.clipShape(RoundedRectangle(cornerRadius: 10))
|
|
}
|
|
|
|
Button {
|
|
isEditing = false
|
|
} label: {
|
|
Text(L10n.cancel)
|
|
.foregroundStyle(Color.primary)
|
|
.font(.body.weight(.semibold))
|
|
.frame(width: 200, height: 50)
|
|
.clipShape(RoundedRectangle(cornerRadius: 10))
|
|
}
|
|
} else {
|
|
ServerSelectionMenu(
|
|
selection: $serverSelection,
|
|
viewModel: viewModel
|
|
)
|
|
|
|
advancedMenu
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Body
|
|
|
|
var body: some View {
|
|
// `Menu` with custom label has some weird additional
|
|
// frame/padding that differs from default label style
|
|
AlternateLayoutView(alignment: .top) {
|
|
Color.clear
|
|
.frame(height: 100)
|
|
} content: {
|
|
contentView
|
|
}
|
|
}
|
|
}
|
|
}
|