iOS/iPadOS - User List Images (#586)
This commit is contained in:
parent
93c19dbe54
commit
fb38394a43
|
@ -154,9 +154,3 @@ struct SettingsView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SettingsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SettingsView(viewModel: SettingsViewModel(server: .sample, user: .sample))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -409,6 +409,7 @@
|
|||
E18E023C288749540022598C /* UIScrollViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18E0239288749540022598C /* UIScrollViewExtensions.swift */; };
|
||||
E19169CE272514760085832A /* HTTPScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19169CD272514760085832A /* HTTPScheme.swift */; };
|
||||
E19169CF272514760085832A /* HTTPScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19169CD272514760085832A /* HTTPScheme.swift */; };
|
||||
E192608028D28AAD002314B4 /* UserProfileButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E192607F28D28AAD002314B4 /* UserProfileButton.swift */; };
|
||||
E1937A3B288E54AD00CB80AA /* BaseItemDto+Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1937A3A288E54AD00CB80AA /* BaseItemDto+Images.swift */; };
|
||||
E1937A3C288E54AD00CB80AA /* BaseItemDto+Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1937A3A288E54AD00CB80AA /* BaseItemDto+Images.swift */; };
|
||||
E1937A3E288F0D3D00CB80AA /* UIScreenExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1937A3D288F0D3D00CB80AA /* UIScreenExtensions.swift */; };
|
||||
|
@ -893,6 +894,7 @@
|
|||
E18E0203288749200022598C /* BlurView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlurView.swift; sourceTree = "<group>"; };
|
||||
E18E0239288749540022598C /* UIScrollViewExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIScrollViewExtensions.swift; sourceTree = "<group>"; };
|
||||
E19169CD272514760085832A /* HTTPScheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPScheme.swift; sourceTree = "<group>"; };
|
||||
E192607F28D28AAD002314B4 /* UserProfileButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileButton.swift; sourceTree = "<group>"; };
|
||||
E1937A3A288E54AD00CB80AA /* BaseItemDto+Images.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BaseItemDto+Images.swift"; sourceTree = "<group>"; };
|
||||
E1937A3D288F0D3D00CB80AA /* UIScreenExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIScreenExtensions.swift; sourceTree = "<group>"; };
|
||||
E1937A60288F32DB00CB80AA /* Poster.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Poster.swift; sourceTree = "<group>"; };
|
||||
|
@ -1500,6 +1502,7 @@
|
|||
E1AA331C2782541500F6439C /* PrimaryButton.swift */,
|
||||
E18E01A4288746AF0022598C /* RefreshableScrollView.swift */,
|
||||
E1D3043428D1763100587289 /* SeeAllButton.swift */,
|
||||
E192607F28D28AAD002314B4 /* UserProfileButton.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2920,6 +2923,7 @@
|
|||
E13DD4022717EE79009D4DAF /* UserListCoordinator.swift in Sources */,
|
||||
E1FCD09626C47118007C8DCF /* ErrorMessage.swift in Sources */,
|
||||
53EE24E6265060780068F029 /* SearchView.swift in Sources */,
|
||||
E192608028D28AAD002314B4 /* UserProfileButton.swift in Sources */,
|
||||
625CB5752678C33500530A6E /* MediaViewModel.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"location" : "https://github.com/LePips/CollectionView",
|
||||
"state" : {
|
||||
"branch" : "main",
|
||||
"revision" : "1dbf31d860626f8debdbb08201517a4684d226c6"
|
||||
"revision" : "b05ad718700cc99a4b88009ede6cf04c7326cd99"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// 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) 2022 Jellyfin & Jellyfin Contributors
|
||||
//
|
||||
|
||||
import JellyfinAPI
|
||||
import SwiftUI
|
||||
|
||||
struct UserProfileButton: View {
|
||||
|
||||
let user: UserDto
|
||||
private var action: () -> Void
|
||||
|
||||
init(user: UserDto) {
|
||||
self.user = user
|
||||
self.action = {}
|
||||
}
|
||||
|
||||
init(user: SwiftfinStore.State.User) {
|
||||
self.init(user: .init(name: user.username, id: user.id))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center) {
|
||||
Button {
|
||||
action()
|
||||
} label: {
|
||||
ImageView(user.profileImageSource(maxWidth: 120, maxHeight: 120))
|
||||
.failure {
|
||||
ZStack {
|
||||
Color.secondarySystemFill
|
||||
.opacity(0.5)
|
||||
|
||||
Image(systemName: "person.fill")
|
||||
.resizable()
|
||||
.frame(width: 60, height: 60)
|
||||
}
|
||||
}
|
||||
.clipShape(Circle())
|
||||
}
|
||||
.frame(width: 120, height: 120)
|
||||
|
||||
Text(user.name ?? .emptyDash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UserProfileButton {
|
||||
func onSelect(_ action: @escaping () -> Void) -> Self {
|
||||
var copy = self
|
||||
copy.action = action
|
||||
return copy
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
// Copyright (c) 2022 Jellyfin & Jellyfin Contributors
|
||||
//
|
||||
|
||||
import CollectionView
|
||||
import SwiftUI
|
||||
|
||||
struct UserListView: View {
|
||||
|
@ -15,44 +16,6 @@ struct UserListView: View {
|
|||
@ObservedObject
|
||||
var viewModel: UserListViewModel
|
||||
|
||||
private var listView: some View {
|
||||
ScrollView {
|
||||
LazyVStack {
|
||||
ForEach(viewModel.users, id: \.id) { user in
|
||||
Button {
|
||||
viewModel.signIn(user: user)
|
||||
} label: {
|
||||
ZStack(alignment: Alignment.leading) {
|
||||
Rectangle()
|
||||
.foregroundColor(Color(UIColor.secondarySystemFill))
|
||||
.frame(height: 50)
|
||||
.cornerRadius(10)
|
||||
|
||||
HStack {
|
||||
Text(user.username)
|
||||
.font(.title2)
|
||||
|
||||
Spacer()
|
||||
|
||||
if viewModel.isLoading {
|
||||
ProgressView()
|
||||
}
|
||||
}.padding(.leading)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.contextMenu {
|
||||
Button(role: .destructive) {
|
||||
viewModel.remove(user: user)
|
||||
} label: {
|
||||
Label(L10n.remove, systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var noUserView: some View {
|
||||
VStack {
|
||||
L10n.signInGetStarted.text
|
||||
|
@ -68,44 +31,59 @@ struct UserListView: View {
|
|||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var innerBody: some View {
|
||||
if viewModel.users.isEmpty {
|
||||
noUserView
|
||||
.offset(y: -50)
|
||||
} else {
|
||||
listView
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var toolbarContent: some View {
|
||||
HStack {
|
||||
Button {
|
||||
userListRouter.route(to: \.serverDetail, viewModel.server)
|
||||
} label: {
|
||||
Image(systemName: "info.circle.fill")
|
||||
}
|
||||
|
||||
if !viewModel.users.isEmpty {
|
||||
Button {
|
||||
userListRouter.route(to: \.userSignIn, viewModel.server)
|
||||
} label: {
|
||||
Image(systemName: "person.crop.circle.fill.badge.plus")
|
||||
private var gridView: some View {
|
||||
CollectionView(items: viewModel.users) { _, user, _ in
|
||||
UserProfileButton(user: user)
|
||||
.onSelect {
|
||||
viewModel.signIn(user: user)
|
||||
}
|
||||
}
|
||||
.contextMenu {
|
||||
Button(role: .destructive) {
|
||||
viewModel.remove(user: user)
|
||||
} label: {
|
||||
Label(L10n.remove, systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
.layout { _, layoutEnvironment in
|
||||
.grid(
|
||||
layoutEnvironment: layoutEnvironment,
|
||||
layoutMode: .adaptive(withMinItemSize: 120),
|
||||
itemSpacing: 30,
|
||||
lineSpacing: 30
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
innerBody
|
||||
.navigationTitle(viewModel.server.name)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
toolbarContent
|
||||
Group {
|
||||
if viewModel.users.isEmpty {
|
||||
noUserView
|
||||
.offset(y: -50)
|
||||
} else {
|
||||
gridView
|
||||
}
|
||||
}
|
||||
.navigationTitle(viewModel.server.name)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
||||
if !viewModel.users.isEmpty {
|
||||
Button {
|
||||
userListRouter.route(to: \.userSignIn, viewModel.server)
|
||||
} label: {
|
||||
Image(systemName: "person.crop.circle.fill.badge.plus")
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
userListRouter.route(to: \.serverDetail, viewModel.server)
|
||||
} label: {
|
||||
Image(systemName: "info.circle.fill")
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
viewModel.fetchUsers()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
viewModel.fetchUsers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue