Fix iOS 15 Poster Buttons (#1172)

This commit is contained in:
Ethan Pippin 2024-08-08 10:01:23 -06:00 committed by GitHub
parent e4fd98c244
commit d85ffb4156
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 120 additions and 27 deletions

View File

@ -90,11 +90,13 @@ extension String {
.replacingOccurrences(of: ".swift", with: "")
}
// TODO: fix if count > 62
static func random(count: Int) -> String {
let characters = Self.alphanumeric.randomSample(count: count)
return String(characters)
}
// TODO: fix if upper bound > 62
static func random(count range: Range<Int>) -> String {
let characters = Self.alphanumeric.randomSample(count: Int.random(in: range))
return String(characters)
@ -114,6 +116,20 @@ extension String {
return s
}
// TODO: remove after iOS 15 support removed
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(
with: constraintRect,
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil
)
return ceil(boundingBox.height)
}
}
extension CharacterSet {

View File

@ -31,8 +31,16 @@ extension Backport where Content: View {
content
.lineLimit(limit, reservesSpace: reservesSpace)
} else {
// This may still not be enough and will probably have to
// use String.height in a frame as caller site
//
// The `.font` modifier must come after this modifier in
// order for the layout and content fonts to match
ZStack(alignment: .top) {
Text(String(repeating: " \n", count: limit))
if reservesSpace {
Text("A" + String(repeating: "A\nA", count: limit - 1))
.hidden()
}
content
.lineLimit(limit)

View File

@ -37,7 +37,5 @@ struct EnvironmentModifier<Wrapped: View, Value>: ViewModifier {
func body(content: Content) -> some View {
wrapped(environmentValue)
// wrapped(content)
}
}

View File

@ -42,24 +42,27 @@ final class UserSession {
extension Container {
var currentUserSession: Factory<UserSession?> {
self {
if let lastUserID = Defaults[.lastSignedInUserID],
let user = try? SwiftfinStore.dataStack.fetchOne(
From<UserModel>().where(\.$id == lastUserID)
)
{
guard let server = user.server,
let _ = SwiftfinStore.dataStack.fetchExisting(server)
else {
fatalError("No associated server for last user")
}
guard let lastUserID = Defaults[.lastSignedInUserID] else { return nil }
return .init(
server: server.state,
user: user.state
)
guard let user = try? SwiftfinStore.dataStack.fetchOne(
From<UserModel>().where(\.$id == lastUserID)
) else {
// had last user ID but no saved user
Defaults[.lastSignedInUserID] = nil
return nil
}
return nil
guard let server = user.server,
let _ = SwiftfinStore.dataStack.fetchExisting(server)
else {
fatalError("No associated server for last user")
}
return .init(
server: server.state,
user: user.state
)
}.cached
}
}

View File

@ -824,6 +824,7 @@
E1DABAFA2A270E62008AC34A /* OverviewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DABAF92A270E62008AC34A /* OverviewCard.swift */; };
E1DABAFC2A270EE7008AC34A /* MediaSourcesCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */; };
E1DABAFE2A27B982008AC34A /* RatingsCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DABAFD2A27B982008AC34A /* RatingsCard.swift */; };
E1DC7ACA2C63337C00AEE368 /* iOS15View.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DC7AC92C63337C00AEE368 /* iOS15View.swift */; };
E1DC9814296DC06200982F06 /* PulseLogHandler in Frameworks */ = {isa = PBXBuildFile; productRef = E1DC9813296DC06200982F06 /* PulseLogHandler */; };
E1DC981A296DD1CD00982F06 /* CinematicBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DC9818296DD1CD00982F06 /* CinematicBackgroundView.swift */; };
E1DC983D296DEB9B00982F06 /* UnwatchedIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DC983C296DEB9B00982F06 /* UnwatchedIndicator.swift */; };
@ -1485,6 +1486,7 @@
E1DABAF92A270E62008AC34A /* OverviewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverviewCard.swift; sourceTree = "<group>"; };
E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourcesCard.swift; sourceTree = "<group>"; };
E1DABAFD2A27B982008AC34A /* RatingsCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingsCard.swift; sourceTree = "<group>"; };
E1DC7AC92C63337C00AEE368 /* iOS15View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOS15View.swift; sourceTree = "<group>"; };
E1DC9818296DD1CD00982F06 /* CinematicBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicBackgroundView.swift; sourceTree = "<group>"; };
E1DC983C296DEB9B00982F06 /* UnwatchedIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnwatchedIndicator.swift; sourceTree = "<group>"; };
E1DC9840296DEBD800982F06 /* WatchedIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchedIndicator.swift; sourceTree = "<group>"; };
@ -2100,6 +2102,7 @@
E1DE2B492B97ECB900F6715F /* ErrorView.swift */,
E1921B7528E63306003A5238 /* GestureView.swift */,
E178B0752BE435D70023651B /* HourMinutePicker.swift */,
E1DC7AC92C63337C00AEE368 /* iOS15View.swift */,
E1FE69A928C29CC20021BC93 /* LandscapePosterProgressBar.swift */,
4E16FD4E2C0183B500110147 /* LetterPickerBar */,
E1A8FDEB2C0574A800D0A51C /* ListRow.swift */,
@ -4571,6 +4574,7 @@
E1BDF2F329524C3B00CC0294 /* ChaptersActionButton.swift in Sources */,
E173DA5026D048D600CC4EB7 /* ServerDetailView.swift in Sources */,
E1BE1CF02BDB6C97008176A9 /* UserProfileSettingsView.swift in Sources */,
E1DC7ACA2C63337C00AEE368 /* iOS15View.swift in Sources */,
E1CFE28028FA606800B7D34C /* ChapterTrack.swift in Sources */,
E1401CA22938122C00E8B599 /* AppIcons.swift in Sources */,
E1BDF2FB2952502300CC0294 /* SubtitleActionButton.swift in Sources */,

View File

@ -66,7 +66,7 @@ struct SwiftfinApp: App {
// Swiftfin
// don't keep last user id
if Defaults[.signOutOnClose] {
if Defaults[.signOutOnClose] || Container.shared.currentUserSession() == nil {
Defaults[.lastSignedInUserID] = nil
}
}

View File

@ -140,16 +140,36 @@ extension PosterButton {
let item: Item
var body: some View {
VStack(alignment: .leading) {
if item.showTitle {
TitleContentView(item: item)
iOS15View {
VStack(alignment: .leading, spacing: 0) {
if item.showTitle {
TitleContentView(item: item)
.backport
.lineLimit(1, reservesSpace: true)
.iOS15 { v in
v.font(.footnote.weight(.regular))
}
}
SubtitleContentView(item: item)
.backport
.lineLimit(1, reservesSpace: true)
.iOS15 { v in
v.font(.caption.weight(.medium))
}
}
} content: {
VStack(alignment: .leading) {
if item.showTitle {
TitleContentView(item: item)
.backport
.lineLimit(1, reservesSpace: true)
}
SubtitleContentView(item: item)
.backport
.lineLimit(1, reservesSpace: true)
}
SubtitleContentView(item: item)
.backport
.lineLimit(1, reservesSpace: true)
}
}
}

View File

@ -0,0 +1,24 @@
//
// 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) 2024 Jellyfin & Jellyfin Contributors
//
import SwiftUI
// TODO: remove when iOS 15 support removed
struct iOS15View<iOS15Content: View, Content: View>: View {
let iOS15: () -> iOS15Content
let content: () -> Content
var body: some View {
if #available(iOS 16, *) {
content()
} else {
iOS15()
}
}
}

View File

@ -11,6 +11,17 @@ import SwiftUI
extension View {
// TODO: remove after removing support for iOS 15
@ViewBuilder
func iOS15<Content: View>(@ViewBuilder _ content: (Self) -> Content) -> some View {
if #available(iOS 16, *) {
self
} else {
content(self)
}
}
func detectOrientation(_ orientation: Binding<UIDeviceOrientation>) -> some View {
modifier(DetectOrientation(orientation: orientation))
}

View File

@ -52,6 +52,7 @@ extension ChannelLibraryView {
.foregroundColor(.primary)
.backport
.lineLimit(1, reservesSpace: true)
.font(.footnote.weight(.regular))
}
}
.buttonStyle(.plain)

View File

@ -49,6 +49,7 @@ extension SeriesEpisodeSelector {
.multilineTextAlignment(.leading)
.backport
.lineLimit(3, reservesSpace: true)
.font(.caption.weight(.light))
}
var body: some View {
@ -61,6 +62,14 @@ extension SeriesEpisodeSelector {
headerView
contentView
.iOS15 { v in
v.frame(
height: "A\nA\nA".height(
withConstrainedWidth: 10,
font: Font.caption.uiFont
)
)
}
L10n.seeMore.text
.font(.caption.weight(.light))

View File

@ -43,7 +43,6 @@ struct SeriesEpisodeSelector: View {
)
.labelStyle(.episodeSelector)
}
.fixedSize()
}
var body: some View {