Skip to content

Commit

Permalink
[tvOS] Login Flow Cleanup - Second Pass (#1403)
Browse files Browse the repository at this point in the history
* Background on Server User Signin. Button Sizing. More visible deletion notice. Menu ListView insets.

* wip

* Change Highlight. Move Add User Button. Remove Add User inline option.

* Take 2

* Undo user changes.

* Remove all changes.

* "selectServer" = "Select Server";

* Recommendations

Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>

* Update ServerDetailView.swift

Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>

* Update ServerDetailView.swift

Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>

* build strings

---------

Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>
  • Loading branch information
JPKribs and LePips authored Jan 24, 2025
1 parent 757ea4d commit b0b604c
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 128 deletions.
2 changes: 2 additions & 0 deletions Shared/Strings/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,8 @@ internal enum L10n {
internal static let selectAll = L10n.tr("Localizable", "selectAll", fallback: "Select All")
/// Select Image
internal static let selectImage = L10n.tr("Localizable", "selectImage", fallback: "Select Image")
/// Select server
internal static let selectServer = L10n.tr("Localizable", "selectServer", fallback: "Select server")
/// Series
internal static let series = L10n.tr("Localizable", "series", fallback: "Series")
/// Series Backdrop
Expand Down
28 changes: 24 additions & 4 deletions Swiftfin tvOS/Components/ListRowButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import SwiftUI
struct ListRowButton: View {

let title: String
let role: ButtonRole?
let action: () -> Void

init(_ title: String, action: @escaping () -> Void) {
init(_ title: String, role: ButtonRole? = nil, action: @escaping () -> Void) {
self.title = title
self.role = role
self.action = action
}

Expand All @@ -23,15 +25,33 @@ struct ListRowButton: View {
action()
} label: {
ZStack {
Rectangle()
.foregroundStyle(.secondary)
RoundedRectangle(cornerRadius: 10)
.fill(secondaryStyle)

Text(title)
.foregroundStyle(primaryStyle)
.font(.body.weight(.bold))
.foregroundStyle(.primary)
}
}
.buttonStyle(.card)
.frame(height: 75)
}

// MARK: - Styles

private var primaryStyle: some ShapeStyle {
if role == .destructive {
return AnyShapeStyle(Color.red)
} else {
return AnyShapeStyle(.primary)
}
}

private var secondaryStyle: some ShapeStyle {
if role == .destructive {
return AnyShapeStyle(Color.red.opacity(0.2))
} else {
return AnyShapeStyle(.secondary)
}
}
}
21 changes: 21 additions & 0 deletions Swiftfin tvOS/Components/SplitLoginWindowView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ struct SplitLoginWindowView<Leading: View, Trailing: View>: View {
private let trailingTitle: String
private let trailingContentView: () -> Trailing

// MARK: - Background Variable

private let backgroundImageSource: ImageSource?

// MARK: - Body

var body: some View {
Expand Down Expand Up @@ -52,6 +56,21 @@ struct SplitLoginWindowView<Leading: View, Trailing: View>: View {
}
}
.navigationBarBranding(isLoading: isLoading)
.background {
if let backgroundImageSource {
ZStack {
ImageView(backgroundImageSource)
.aspectRatio(contentMode: .fill)
.id(backgroundImageSource)
.transition(.opacity)
.animation(.linear, value: backgroundImageSource)

Color.black
.opacity(0.9)
}
.ignoresSafeArea()
}
}
}
}

Expand All @@ -61,6 +80,7 @@ extension SplitLoginWindowView {
isLoading: Bool = false,
leadingTitle: String,
trailingTitle: String,
backgroundImageSource: ImageSource? = nil,
@ViewBuilder leadingContentView: @escaping () -> Leading,
@ViewBuilder trailingContentView: @escaping () -> Trailing
) {
Expand All @@ -69,5 +89,6 @@ extension SplitLoginWindowView {
self.trailingTitle = trailingTitle
self.leadingContentView = leadingContentView
self.trailingContentView = trailingContentView
self.backgroundImageSource = backgroundImageSource
}
}
66 changes: 44 additions & 22 deletions Swiftfin tvOS/Views/SelectUserView/Components/AddUserButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,59 @@ extension SelectUserView {
self.servers = servers
}

@ViewBuilder
private var content: some View {
ZStack {
Color.secondarySystemFill

RelativeSystemImageView(systemName: "plus")
.foregroundStyle(.secondary)
}
.clipShape(.circle)
.aspectRatio(1, contentMode: .fill)
.hoverEffect(.highlight)

Text(L10n.addUser)
.font(.title3)
.fontWeight(.semibold)
.foregroundStyle(isEnabled ? .primary : .secondary)

if serverSelection == .all {
// For layout, not to be localized
Text("Hidden")
.font(.footnote)
.hidden()
}
}

var body: some View {
VStack {
if serverSelection == .all {
Menu {
Text(L10n.selectServer)

ForEach(servers) { server in
Button {
action(server)
} label: {
Text(server.name)
Text(server.currentURL.absoluteString)
}
}
} label: {
content
}
.buttonStyle(.borderless)
.buttonBorderShape(.circle)
} else {
Button {
if let selectedServer {
action(selectedServer)
}
} label: {
ZStack {
Color.secondarySystemFill

RelativeSystemImageView(systemName: "plus")
.foregroundStyle(.secondary)
}
.clipShape(.circle)
.aspectRatio(1, contentMode: .fill)
.hoverEffect(.highlight)

Text(L10n.addUser)
.font(.title3)
.fontWeight(.semibold)
.foregroundStyle(isEnabled ? .primary : .secondary)

if serverSelection == .all {
Text(L10n.hidden)
.font(.footnote)
.hidden()
}
content
}
.buttonStyle(.borderless)
.buttonBorderShape(.circle)
.disabled(!isEnabled)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,26 @@ extension SelectUserView {

@ViewBuilder
private var advancedMenu: some View {
Menu(L10n.advanced, systemImage: "gearshape.fill") {

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?
// 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) {
Expand All @@ -51,40 +64,20 @@ extension SelectUserView {
// }
// .pickerStyle(.menu)
// }

// TODO: Advanced settings on tvOS?
// Section {
// Button(L10n.advanced, systemImage: "gearshape.fill") {
// router.route(to: \.advancedSettings)
// }
// }
}
.labelStyle(.iconOnly)
}

// MARK: - Delete User Button

private var deleteUsersButton: some View {
Button {
ListRowButton(L10n.delete, role: .destructive) {
onDelete()
} label: {
ZStack {
Color.red

Text(L10n.delete)
.font(.body.weight(.semibold))
.foregroundStyle(areUsersSelected ? .primary : .secondary)

if !areUsersSelected {
Color.black
.opacity(0.5)
}
}
.frame(width: 400, height: 65)
.clipShape(RoundedRectangle(cornerRadius: 10))
}
.frame(width: 400, height: 50)
.disabled(!areUsersSelected)
.buttonStyle(.card)
}

// MARK: - Initializer

init(
isEditing: Binding<Bool>,
serverSelection: Binding<SelectUserServerSelection>,
Expand All @@ -103,6 +96,8 @@ extension SelectUserView {
self.toggleAllUsersSelected = toggleAllUsersSelected
}

// MARK: - Content View

@ViewBuilder
private var contentView: some View {
HStack(alignment: .center) {
Expand All @@ -113,30 +108,34 @@ extension SelectUserView {
toggleAllUsersSelected()
} label: {
Text(areUsersSelected ? L10n.removeAll : L10n.selectAll)
.font(.body.weight(.semibold))
.foregroundStyle(Color.primary)
.font(.body.weight(.semibold))
.frame(width: 200, height: 50)
.clipShape(RoundedRectangle(cornerRadius: 10))
}

Button {
isEditing = false
} label: {
L10n.cancel.text
.font(.body.weight(.semibold))
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
)

if userCount > 1 {
advancedMenu
}
advancedMenu
}
}
}

// MARK: - Body

var body: some View {
// `Menu` with custom label has some weird additional
// frame/padding that differs from default label style
Expand Down
Loading

0 comments on commit b0b604c

Please sign in to comment.