1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-13 13:50:32 +05:30

Add video description expanding

This commit is contained in:
Arkadiusz Fal 2023-04-22 19:22:13 +02:00
parent b19918e219
commit d52ccf2ce6
6 changed files with 86 additions and 7 deletions

View File

@ -13,6 +13,14 @@ struct Constants {
#endif #endif
} }
static var isIPad: Bool {
#if os(iOS)
UIDevice.current.userInterfaceIdiom == .pad
#else
false
#endif
}
static var progressViewScale: Double { static var progressViewScale: Double {
#if os(macOS) #if os(macOS)
0.4 0.4

View File

@ -132,6 +132,12 @@ extension Defaults.Keys {
static let seekGestureSpeed = Key<Double>("seekGestureSpeed", default: 0.5) static let seekGestureSpeed = Key<Double>("seekGestureSpeed", default: 0.5)
static let seekGestureSensitivity = Key<Double>("seekGestureSensitivity", default: 30.0) static let seekGestureSensitivity = Key<Double>("seekGestureSensitivity", default: 30.0)
static let showKeywords = Key<Bool>("showKeywords", default: false) static let showKeywords = Key<Bool>("showKeywords", default: false)
#if os(iOS)
static let expandVideoDescriptionDefault = Constants.isIPad
#else
static let expandVideoDescriptionDefault = true
#endif
static let expandVideoDescription = Key<Bool>("expandVideoDescription", default: expandVideoDescriptionDefault)
#if !os(tvOS) #if !os(tvOS)
static let commentsPlacement = Key<CommentsPlacement>("commentsPlacement", default: .separate) static let commentsPlacement = Key<CommentsPlacement>("commentsPlacement", default: .separate)
#endif #endif

View File

@ -6,27 +6,54 @@ import Foundation
import SwiftUI import SwiftUI
struct VideoDescription: View { struct VideoDescription: View {
static let collapsedLines = 5
private var search: SearchModel { .shared } private var search: SearchModel { .shared }
@Default(.showKeywords) private var showKeywords @Default(.showKeywords) private var showKeywords
@Default(.expandVideoDescription) private var expandVideoDescription
var video: Video var video: Video
var detailsSize: CGSize? var detailsSize: CGSize?
@Binding var expand: Bool
var description: String { var description: String {
video.description ?? "" video.description ?? ""
} }
var body: some View { var body: some View {
Group {
if !expandVideoDescription && !expand {
Button {
expand = true
} label: {
descriptionView
}
.buttonStyle(.plain)
} else {
descriptionView
}
}
.id(video.videoID)
}
var descriptionView: some View {
VStack { VStack {
#if os(iOS) #if os(iOS)
ActiveLabelDescriptionRepresentable(description: description, detailsSize: detailsSize) ActiveLabelDescriptionRepresentable(
description: description,
detailsSize: detailsSize,
expand: shouldExpand
)
#else #else
textDescription textDescription
#endif #endif
keywords keywords
} }
.id(video.videoID) }
var shouldExpand: Bool {
expandVideoDescription || expand
} }
@ViewBuilder var textDescription: some View { @ViewBuilder var textDescription: some View {
@ -34,14 +61,18 @@ struct VideoDescription: View {
Group { Group {
if #available(macOS 12, *) { if #available(macOS 12, *) {
Text(description) Text(description)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(shouldExpand ? 500 : Self.collapsedLines)
#if !os(tvOS) #if !os(tvOS)
.textSelection(.enabled) .textSelection(.enabled)
#endif #endif
} else { } else {
Text(description) Text(description)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(shouldExpand ? 500 : Self.collapsedLines)
} }
} }
.frame(maxWidth: .infinity, alignment: .leading) .multilineTextAlignment(.leading)
.font(.system(size: 14)) .font(.system(size: 14))
.lineSpacing(3) .lineSpacing(3)
#endif #endif
@ -89,6 +120,7 @@ struct VideoDescription: View {
struct ActiveLabelDescriptionRepresentable: UIViewRepresentable { struct ActiveLabelDescriptionRepresentable: UIViewRepresentable {
var description: String var description: String
var detailsSize: CGSize? var detailsSize: CGSize?
var expand: Bool
@State private var label = ActiveLabel() @State private var label = ActiveLabel()
@ -103,12 +135,12 @@ struct VideoDescription: View {
func updateUIView(_: UIViewType, context _: Context) { func updateUIView(_: UIViewType, context _: Context) {
updatePreferredMaxLayoutWidth() updatePreferredMaxLayoutWidth()
updateNumberOfLines()
} }
func customizeLabel() { func customizeLabel() {
label.customize { label in label.customize { label in
label.enabledTypes = [.url, .timestamp] label.enabledTypes = [.url, .timestamp]
label.numberOfLines = 0
label.text = description label.text = description
label.contentMode = .scaleAspectFill label.contentMode = .scaleAspectFill
label.font = .systemFont(ofSize: 14) label.font = .systemFont(ofSize: 14)
@ -119,12 +151,17 @@ struct VideoDescription: View {
label.handleURLTap(urlTapHandler(_:)) label.handleURLTap(urlTapHandler(_:))
label.handleTimestampTap(timestampTapHandler(_:)) label.handleTimestampTap(timestampTapHandler(_:))
} }
updateNumberOfLines()
} }
func updatePreferredMaxLayoutWidth() { func updatePreferredMaxLayoutWidth() {
label.preferredMaxLayoutWidth = (detailsSize?.width ?? 330) - 30 label.preferredMaxLayoutWidth = (detailsSize?.width ?? 330) - 30
} }
func updateNumberOfLines() {
label.numberOfLines = expand ? 0 : VideoDescription.collapsedLines
}
func urlTapHandler(_ url: URL) { func urlTapHandler(_ url: URL) {
var urlToOpen = url var urlToOpen = url
@ -156,7 +193,7 @@ struct VideoDescription: View {
struct VideoDescription_Previews: PreviewProvider { struct VideoDescription_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
VideoDescription(video: .fixture) VideoDescription(video: .fixture, expand: .constant(false))
.injectFixtureEnvironmentObjects() .injectFixtureEnvironmentObjects()
} }
} }

View File

@ -160,6 +160,7 @@ struct VideoDetails: View {
@State private var subscribed = false @State private var subscribed = false
@State private var subscriptionToggleButtonDisabled = false @State private var subscriptionToggleButtonDisabled = false
@State private var page = DetailsPage.info @State private var page = DetailsPage.info
@State private var descriptionExpanded = false
@Environment(\.navigationStyle) private var navigationStyle @Environment(\.navigationStyle) private var navigationStyle
#if os(iOS) #if os(iOS)
@ -175,6 +176,7 @@ struct VideoDetails: View {
@Default(.enableReturnYouTubeDislike) private var enableReturnYouTubeDislike @Default(.enableReturnYouTubeDislike) private var enableReturnYouTubeDislike
@Default(.playerSidebar) private var playerSidebar @Default(.playerSidebar) private var playerSidebar
@Default(.showInspector) private var showInspector @Default(.showInspector) private var showInspector
@Default(.expandVideoDescription) private var expandVideoDescription
var body: some View { var body: some View {
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
@ -281,7 +283,9 @@ struct VideoDetails: View {
} }
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} else if let description = video.description, !description.isEmpty { } else if let description = video.description, !description.isEmpty {
VideoDescription(video: video, detailsSize: detailsSize) Section(header: descriptionHeader) {
VideoDescription(video: video, detailsSize: detailsSize, expand: $descriptionExpanded)
}
} else if !video.isLocal { } else if !video.isLocal {
Text("No description") Text("No description")
.font(.caption) .font(.caption)
@ -345,6 +349,20 @@ struct VideoDetails: View {
} }
} }
} }
var descriptionHeader: some View {
HStack {
Text("Description".localized())
if !expandVideoDescription, !descriptionExpanded {
Spacer()
Image(systemName: "arrow.up.and.down")
.imageScale(.small)
}
}
.font(.caption)
.foregroundColor(.secondary)
}
} }
struct VideoDetails_Previews: PreviewProvider { struct VideoDetails_Previews: PreviewProvider {

View File

@ -8,6 +8,7 @@ struct PlayerSettings: View {
@Default(.playerSidebar) private var playerSidebar @Default(.playerSidebar) private var playerSidebar
@Default(.showKeywords) private var showKeywords @Default(.showKeywords) private var showKeywords
@Default(.expandVideoDescription) private var expandVideoDescription
@Default(.pauseOnHidingPlayer) private var pauseOnHidingPlayer @Default(.pauseOnHidingPlayer) private var pauseOnHidingPlayer
#if os(iOS) #if os(iOS)
@Default(.honorSystemOrientationLock) private var honorSystemOrientationLock @Default(.honorSystemOrientationLock) private var honorSystemOrientationLock
@ -85,6 +86,9 @@ struct PlayerSettings: View {
if !accounts.isEmpty { if !accounts.isEmpty {
keywordsToggle keywordsToggle
#if !os(tvOS)
expandVideoDescriptionToggle
#endif
returnYouTubeDislikeToggle returnYouTubeDislikeToggle
} }
} }
@ -160,6 +164,10 @@ struct PlayerSettings: View {
Toggle("Show keywords", isOn: $showKeywords) Toggle("Show keywords", isOn: $showKeywords)
} }
private var expandVideoDescriptionToggle: some View {
Toggle("Open video description expanded", isOn: $expandVideoDescription)
}
private var returnYouTubeDislikeToggle: some View { private var returnYouTubeDislikeToggle: some View {
Toggle("Enable Return YouTube Dislike", isOn: $enableReturnYouTubeDislike) Toggle("Enable Return YouTube Dislike", isOn: $enableReturnYouTubeDislike)
} }
@ -212,7 +220,9 @@ struct PlayerSettings: View {
Text("Always").tag(ShowInspectorSetting.always) Text("Always").tag(ShowInspectorSetting.always)
Text("Only for local files and URLs").tag(ShowInspectorSetting.onlyLocal) Text("Only for local files and URLs").tag(ShowInspectorSetting.onlyLocal)
} }
#if os(macOS)
.labelsHidden() .labelsHidden()
#endif
} }
} }

View File

@ -247,7 +247,7 @@ struct SettingsView: View {
case .player: case .player:
return 450 return 450
case .controls: case .controls:
return 900 return 920
case .quality: case .quality:
return 420 return 420
case .history: case .history: