Some Polish (#1058)

This commit is contained in:
Ethan Pippin 2024-05-16 07:34:08 -06:00 committed by GitHub
parent 957022e09d
commit 66c26553ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 126 additions and 30 deletions

View File

@ -11,6 +11,8 @@ import SwiftUI
// TODO: only allow `view` selection when truncated?
// TODO: fix when also using `lineLimit(reserveSpace > 1)`
// TODO: some false positives for showing see more?
// TODO: allow removing empty lines
struct TruncatedText: View {

View File

@ -288,7 +288,7 @@
E12186DE2718F1C50010884C /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = E12186DD2718F1C50010884C /* Defaults */; };
E122A9132788EAAD0060FA63 /* MediaStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStream.swift */; };
E122A9142788EAAD0060FA63 /* MediaStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStream.swift */; };
E12376AE2A33D680001F5B44 /* AboutViewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12376AD2A33D680001F5B44 /* AboutViewCard.swift */; };
E12376AE2A33D680001F5B44 /* AboutView+Card.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12376AD2A33D680001F5B44 /* AboutView+Card.swift */; };
E12376B02A33D6AE001F5B44 /* AboutViewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */; };
E12376B12A33DB33001F5B44 /* MediaSourceInfoCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E170D106294D23BA0017224C /* MediaSourceInfoCoordinator.swift */; };
E12376B32A33DFAC001F5B44 /* ItemOverviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12376B22A33DFAC001F5B44 /* ItemOverviewView.swift */; };
@ -1115,7 +1115,7 @@
E11CEB8F28999D84003E74C7 /* EpisodeItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeItemView.swift; sourceTree = "<group>"; };
E11CEB9328999D9E003E74C7 /* EpisodeItemContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeItemContentView.swift; sourceTree = "<group>"; };
E122A9122788EAAD0060FA63 /* MediaStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaStream.swift; sourceTree = "<group>"; };
E12376AD2A33D680001F5B44 /* AboutViewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewCard.swift; sourceTree = "<group>"; };
E12376AD2A33D680001F5B44 /* AboutView+Card.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AboutView+Card.swift"; sourceTree = "<group>"; };
E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewCard.swift; sourceTree = "<group>"; };
E12376B22A33DFAC001F5B44 /* ItemOverviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemOverviewView.swift; sourceTree = "<group>"; };
E129428428F080B500796AC6 /* OnReceiveNotificationModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnReceiveNotificationModifier.swift; sourceTree = "<group>"; };
@ -2879,7 +2879,7 @@
E18ACA932A15A3D800BB4F35 /* Components */ = {
isa = PBXGroup;
children = (
E12376AD2A33D680001F5B44 /* AboutViewCard.swift */,
E12376AD2A33D680001F5B44 /* AboutView+Card.swift */,
E1E750662A33E9B400B2C1EE /* MediaSourcesCard.swift */,
E1E750652A33E9B400B2C1EE /* OverviewCard.swift */,
E1E750672A33E9B400B2C1EE /* RatingsCard.swift */,
@ -4393,7 +4393,7 @@
E1A1529028FD23D600600579 /* PlaybackSettingsCoordinator.swift in Sources */,
E11042752B8013DF00821020 /* Stateful.swift in Sources */,
E1AA331F2782639D00F6439C /* OverlayType.swift in Sources */,
E12376AE2A33D680001F5B44 /* AboutViewCard.swift in Sources */,
E12376AE2A33D680001F5B44 /* AboutView+Card.swift in Sources */,
E1A2C154279A7D5A005EC829 /* UIApplication.swift in Sources */,
E1D8428F2933F2D900D1041A /* MediaSourceInfo.swift in Sources */,
E1BDF2EC2952290200CC0294 /* AspectFillActionButton.swift in Sources */,

View File

@ -45,6 +45,11 @@ struct SwiftfinApp: App {
// Sometimes the tab bar won't appear properly on push, always have material background
UITabBar.appearance().scrollEdgeAppearance = UITabBarAppearance(idiom: .unspecified)
// don't keep last user id
if Defaults[.signOutOnClose] {
Defaults[.lastSignedInUserID] = nil
}
}
var body: some Scene {

View File

@ -6,22 +6,112 @@
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//
import CollectionHStack
import Defaults
import JellyfinAPI
import OrderedCollections
import SwiftUI
// TODO: rename `AboutItemView`
// TODO: see what to do about bottom padding
// - don't like it adds more than the edge
// - just have this determine bottom padding
// instead of scrollviews?
extension ItemView {
struct AboutView: View {
private enum AboutViewItem: Hashable {
case image
case overview
case mediaSource(MediaSourceInfo)
case ratings
}
@Default(.accentColor)
private var accentColor
@ObservedObject
var viewModel: ItemViewModel
@State
private var contentSize: CGSize = .zero
@State
private var items: OrderedSet<AboutViewItem>
init(viewModel: ItemViewModel) {
self.viewModel = viewModel
var items: OrderedSet<AboutViewItem> = [
.image,
.overview,
]
if let mediaSources = viewModel.item.mediaSources {
items.append(contentsOf: mediaSources.map { AboutViewItem.mediaSource($0) })
}
if viewModel.item.hasRatings {
items.append(.ratings)
}
self._items = State(initialValue: items)
}
// TODO: break out into a general solution for general use?
// use similar math from CollectionHStack
private var padImageWidth: CGFloat {
let portraitMinWidth: CGFloat = 140
let contentWidth = contentSize.width
let usableWidth = contentWidth - EdgeInsets.edgePadding * 2
var columns = CGFloat(Int(usableWidth / portraitMinWidth))
let preItemSpacing = (columns - 1) * (EdgeInsets.edgePadding / 2)
let preTotalNegative = EdgeInsets.edgePadding * 2 + preItemSpacing
if columns * portraitMinWidth + preTotalNegative > contentWidth {
columns -= 1
}
let itemSpacing = (columns - 1) * (EdgeInsets.edgePadding / 2)
let totalNegative = EdgeInsets.edgePadding * 2 + itemSpacing
let itemWidth = (contentWidth - totalNegative) / columns
return max(0, itemWidth)
}
private var phoneImageWidth: CGFloat {
let contentWidth = contentSize.width
let usableWidth = contentWidth - EdgeInsets.edgePadding * 2
let itemSpacing = (EdgeInsets.edgePadding / 2) * 2
let itemWidth = (usableWidth - itemSpacing) / 3
return max(0, itemWidth)
}
private var cardSize: CGSize {
let height = UIDevice.isPad ? padImageWidth * 3 / 2 : phoneImageWidth * 3 / 2
let width = height * 1.65
return CGSize(width: width, height: height)
}
private var imageView: some View {
ZStack {
Color.clear
ImageView(
viewModel.item.type == .episode ? viewModel.item.seriesImageSource(.primary, maxWidth: 300) : viewModel
.item.imageSource(.primary, maxWidth: 300)
)
.accessibilityIgnoresInvertColors()
}
.posterStyle(.portrait)
.posterShadow()
.frame(width: UIDevice.isPad ? padImageWidth : phoneImageWidth)
}
var body: some View {
VStack(alignment: .leading) {
L10n.about.text
@ -30,30 +120,30 @@ extension ItemView {
.accessibility(addTraits: [.isHeader])
.edgePadding(.horizontal)
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ImageView(
viewModel.item.type == .episode ? viewModel.item.seriesImageSource(.primary, maxWidth: 300) : viewModel
.item.imageSource(.primary, maxWidth: 300)
)
.posterStyle(.portrait)
.posterShadow()
.frame(width: 130)
.accessibilityIgnoresInvertColors()
CollectionHStack($items, variadicWidths: true) { item in
switch item {
case .image:
imageView
case .overview:
OverviewCard(item: viewModel.item)
if let mediaSources = viewModel.item.mediaSources {
ForEach(mediaSources) { source in
MediaSourcesCard(subtitle: mediaSources.count > 1 ? source.displayTitle : nil, source: source)
}
}
.frame(width: cardSize.width, height: cardSize.height)
case let .mediaSource(source):
MediaSourcesCard(
subtitle: (viewModel.item.mediaSources ?? []).count > 1 ? source.displayTitle : nil,
source: source
)
.frame(width: cardSize.width, height: cardSize.height)
case .ratings:
RatingsCard(item: viewModel.item)
.frame(width: cardSize.width, height: cardSize.height)
}
.edgePadding(.horizontal)
}
.clipsToBounds(false)
.insets(horizontal: EdgeInsets.edgePadding)
.itemSpacing(EdgeInsets.edgePadding / 2)
.scrollBehavior(.continuousLeadingEdge)
}
.trackingSize($contentSize)
}
}
}

View File

@ -23,8 +23,8 @@ extension ItemView.AboutView {
} label: {
ZStack(alignment: .leading) {
Color.secondarySystemFill
.cornerRadius(10)
Color.systemFill
.cornerRadius(ratio: 1 / 45, of: \.height)
VStack(alignment: .leading, spacing: 5) {
Text(title)
@ -48,7 +48,6 @@ extension ItemView.AboutView {
}
.padding()
}
.frame(width: 330, height: 195)
}
.buttonStyle(.plain)
}

View File

@ -50,7 +50,7 @@ extension ItemView {
}
var body: some View {
ScrollView {
ScrollView(showsIndicators: false) {
VStack(spacing: 0) {
overlay()
.frame(height: (size.height + safeAreaInsets.vertical) * heightRatio)

View File

@ -16,7 +16,7 @@ struct CollectionItemView: View {
var viewModel: CollectionItemViewModel
var body: some View {
ScrollView {
ScrollView(showsIndicators: false) {
ContentView(viewModel: viewModel)
.edgePadding(.bottom)
}

View File

@ -15,7 +15,7 @@ struct EpisodeItemView: View {
var viewModel: EpisodeItemViewModel
var body: some View {
ScrollView {
ScrollView(showsIndicators: false) {
ContentView(viewModel: viewModel)
.edgePadding(.bottom)
}

View File

@ -36,7 +36,7 @@ extension ItemView {
ImageView(viewModel.item.imageSource(.backdrop, maxWidth: 1920))
}
}
.aspectRatio(contentMode: .fill)
.aspectRatio(1.77, contentMode: .fill)
}
var body: some View {