mirror of
https://github.com/yattee/yattee.git
synced 2025-12-12 19:18:16 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a074d7607 | ||
|
|
9d8b20148b | ||
|
|
0ffb9d0606 | ||
|
|
8258d8d5b4 | ||
|
|
94915b0496 | ||
|
|
053b4a22b8 |
15
Backports/Badge+Backport.swift
Normal file
15
Backports/Badge+Backport.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
import SwiftUI
|
||||
|
||||
extension Backport where Content: View {
|
||||
@ViewBuilder func badge(_ count: Text?) -> some View {
|
||||
#if os(tvOS)
|
||||
content
|
||||
#else
|
||||
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
||||
content.badge(count)
|
||||
} else {
|
||||
content
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
15
Backports/ListRowSeparator+Backport.swift
Normal file
15
Backports/ListRowSeparator+Backport.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
extension Backport where Content: View {
|
||||
@ViewBuilder func listRowSeparator(_ visible: Bool) -> some View {
|
||||
if #available(iOS 15, macOS 13, *) {
|
||||
content
|
||||
#if !os(tvOS)
|
||||
.listRowSeparator(visible ? .visible : .hidden)
|
||||
#endif
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Backports/Refreshable+Backport.swift
Normal file
11
Backports/Refreshable+Backport.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
import SwiftUI
|
||||
|
||||
extension Backport where Content: View {
|
||||
@ViewBuilder func refreshable(action: @Sendable @escaping () async -> Void) -> some View {
|
||||
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
||||
content.refreshable(action: action)
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Backports/Tint+Backport.swift
Normal file
11
Backports/Tint+Backport.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
import SwiftUI
|
||||
|
||||
extension Backport where Content: View {
|
||||
@ViewBuilder func tint(_ color: Color?) -> some View {
|
||||
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
||||
content.tint(color)
|
||||
} else {
|
||||
content.foregroundColor(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
97
Backports/VisualEffectBlur-iOS.swift
Normal file
97
Backports/VisualEffectBlur-iOS.swift
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright © 2020 Apple Inc.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
#if os(iOS)
|
||||
public struct VisualEffectBlur<Content: View>: View {
|
||||
/// Defaults to .systemMaterial
|
||||
var blurStyle: UIBlurEffect.Style
|
||||
|
||||
/// Defaults to nil
|
||||
var vibrancyStyle: UIVibrancyEffectStyle?
|
||||
|
||||
var content: Content
|
||||
|
||||
public init(blurStyle: UIBlurEffect.Style = .systemMaterial, vibrancyStyle: UIVibrancyEffectStyle? = nil, @ViewBuilder content: () -> Content) {
|
||||
self.blurStyle = blurStyle
|
||||
self.vibrancyStyle = vibrancyStyle
|
||||
self.content = content()
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
Representable(blurStyle: blurStyle, vibrancyStyle: vibrancyStyle, content: ZStack { content })
|
||||
.accessibility(hidden: Content.self == EmptyView.self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Representable
|
||||
|
||||
extension VisualEffectBlur {
|
||||
struct Representable<Content: View>: UIViewRepresentable {
|
||||
var blurStyle: UIBlurEffect.Style
|
||||
var vibrancyStyle: UIVibrancyEffectStyle?
|
||||
var content: Content
|
||||
|
||||
func makeUIView(context: Context) -> UIVisualEffectView {
|
||||
context.coordinator.blurView
|
||||
}
|
||||
|
||||
func updateUIView(_: UIVisualEffectView, context: Context) {
|
||||
context.coordinator.update(content: content, blurStyle: blurStyle, vibrancyStyle: vibrancyStyle)
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(content: content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Coordinator
|
||||
|
||||
extension VisualEffectBlur.Representable {
|
||||
class Coordinator {
|
||||
let blurView = UIVisualEffectView()
|
||||
let vibrancyView = UIVisualEffectView()
|
||||
let hostingController: UIHostingController<Content>
|
||||
|
||||
init(content: Content) {
|
||||
hostingController = UIHostingController(rootView: content)
|
||||
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
hostingController.view.backgroundColor = nil
|
||||
blurView.contentView.addSubview(vibrancyView)
|
||||
|
||||
blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
vibrancyView.contentView.addSubview(hostingController.view)
|
||||
vibrancyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
}
|
||||
|
||||
func update(content: Content, blurStyle: UIBlurEffect.Style, vibrancyStyle: UIVibrancyEffectStyle?) {
|
||||
hostingController.rootView = content
|
||||
|
||||
let blurEffect = UIBlurEffect(style: blurStyle)
|
||||
blurView.effect = blurEffect
|
||||
|
||||
if let vibrancyStyle {
|
||||
vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect, style: vibrancyStyle)
|
||||
} else {
|
||||
vibrancyView.effect = nil
|
||||
}
|
||||
|
||||
hostingController.view.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension VisualEffectBlur where Content == EmptyView {
|
||||
init(blurStyle: UIBlurEffect.Style = .systemMaterial) {
|
||||
self.init(blurStyle: blurStyle, vibrancyStyle: nil) {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
83
Backports/VisualEffectBlur-macOS.swift
Normal file
83
Backports/VisualEffectBlur-macOS.swift
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright © 2020 Apple Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
#if os(macOS)
|
||||
|
||||
public struct VisualEffectBlur: View {
|
||||
private var material: NSVisualEffectView.Material
|
||||
private var blendingMode: NSVisualEffectView.BlendingMode
|
||||
private var state: NSVisualEffectView.State
|
||||
|
||||
public init(
|
||||
material: NSVisualEffectView.Material = .headerView,
|
||||
blendingMode: NSVisualEffectView.BlendingMode = .withinWindow,
|
||||
state: NSVisualEffectView.State = .followsWindowActiveState
|
||||
) {
|
||||
self.material = material
|
||||
self.blendingMode = blendingMode
|
||||
self.state = state
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
Representable(
|
||||
material: material,
|
||||
blendingMode: blendingMode,
|
||||
state: state
|
||||
).accessibility(hidden: true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Representable
|
||||
|
||||
extension VisualEffectBlur {
|
||||
struct Representable: NSViewRepresentable {
|
||||
var material: NSVisualEffectView.Material
|
||||
var blendingMode: NSVisualEffectView.BlendingMode
|
||||
var state: NSVisualEffectView.State
|
||||
|
||||
func makeNSView(context: Context) -> NSVisualEffectView {
|
||||
context.coordinator.visualEffectView
|
||||
}
|
||||
|
||||
func updateNSView(_: NSVisualEffectView, context: Context) {
|
||||
context.coordinator.update(material: material)
|
||||
context.coordinator.update(blendingMode: blendingMode)
|
||||
context.coordinator.update(state: state)
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator()
|
||||
}
|
||||
}
|
||||
|
||||
class Coordinator {
|
||||
let visualEffectView = NSVisualEffectView()
|
||||
|
||||
init() {
|
||||
visualEffectView.blendingMode = .withinWindow
|
||||
}
|
||||
|
||||
func update(material: NSVisualEffectView.Material) {
|
||||
visualEffectView.material = material
|
||||
}
|
||||
|
||||
func update(blendingMode: NSVisualEffectView.BlendingMode) {
|
||||
visualEffectView.blendingMode = blendingMode
|
||||
}
|
||||
|
||||
func update(state: NSVisualEffectView.State) {
|
||||
visualEffectView.state = state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,10 +1,7 @@
|
||||
## Build 165
|
||||
* Added Info section in Player settings
|
||||
Added option to hide chapters
|
||||
Added option to hide related videos
|
||||
Moved other previous Info section settings
|
||||
* Fixed issue where screensaver would turn on while playing video with AVPlayer on tvOS
|
||||
* Fixed reported crashes
|
||||
## Build 166
|
||||
* Fixed issue with formatting video dates (Piped)
|
||||
* Brought back iOS 14 and macOS 11 support
|
||||
|
||||
|
||||
## Previous builds
|
||||
* Added support for "Podcasts" and "Releases" channel tabs (Invidious)
|
||||
@@ -20,6 +17,5 @@
|
||||
* Fixed regression with opening videos links
|
||||
* Fixed issue with deselecting formats in Quality profiles
|
||||
* Fixed compatibility with iOS 17, macOS 14 and tvOS 17
|
||||
* Dropped support for iOS 14 and macOS 11
|
||||
* Fixed reported crashes
|
||||
* Other minor fixes and improvements
|
||||
|
||||
@@ -496,7 +496,17 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
|
||||
let uploaded = details["uploaded"]?.double
|
||||
var published = (uploaded.isNil || uploaded == -1) ? nil : (uploaded! / 1000).formattedAsRelativeTime()
|
||||
if published.isNil {
|
||||
var publishedAt: Date?
|
||||
|
||||
let dateFormatter = ISO8601DateFormatter()
|
||||
dateFormatter.formatOptions = [.withInternetDateTime]
|
||||
|
||||
if published.isNil,
|
||||
let date = details["uploadDate"]?.string,
|
||||
let formattedDate = dateFormatter.date(from: date)
|
||||
{
|
||||
publishedAt = formattedDate
|
||||
} else {
|
||||
published = (details["uploadedDate"] ?? details["uploadDate"])?.string ?? ""
|
||||
}
|
||||
|
||||
@@ -526,6 +536,7 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
thumbnails: thumbnails,
|
||||
live: live,
|
||||
short: details["isShort"]?.bool ?? (length <= Video.shortLength),
|
||||
publishedAt: publishedAt,
|
||||
likes: details["likes"]?.int,
|
||||
dislikes: details["dislikes"]?.int,
|
||||
streams: extractStreams(from: content),
|
||||
|
||||
@@ -40,7 +40,7 @@ struct ChannelVideosView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
let content = VStack {
|
||||
#if os(tvOS)
|
||||
VStack {
|
||||
HStack(spacing: 24) {
|
||||
@@ -181,12 +181,19 @@ struct ChannelVideosView: View {
|
||||
.navigationTitle(navigationTitle)
|
||||
#endif
|
||||
|
||||
#if os(tvOS)
|
||||
.background(Color.background(scheme: colorScheme))
|
||||
#endif
|
||||
#if !os(iOS)
|
||||
.focusScope(focusNamespace)
|
||||
#endif
|
||||
return Group {
|
||||
if #available(macOS 12.0, *) {
|
||||
content
|
||||
#if os(tvOS)
|
||||
.background(Color.background(scheme: colorScheme))
|
||||
#endif
|
||||
#if !os(iOS)
|
||||
.focusScope(focusNamespace)
|
||||
#endif
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var verticalCellsEdgesIgnoringSafeArea: Edge.Set {
|
||||
|
||||
@@ -63,9 +63,16 @@ struct Constants {
|
||||
|
||||
static func seekIcon(_ type: String, _ interval: TimeInterval) -> String {
|
||||
let interval = Int(interval)
|
||||
let allVersions = [5, 10, 15, 30, 45, 60, 75, 90]
|
||||
let allVersions = [10, 15, 30, 45, 60, 75, 90]
|
||||
let iOS15 = [5]
|
||||
let iconName = "go\(type).\(interval)"
|
||||
|
||||
if #available(iOS 15, macOS 12, *) {
|
||||
if iOS15.contains(interval) {
|
||||
return iconName
|
||||
}
|
||||
}
|
||||
|
||||
if allVersions.contains(interval) {
|
||||
return iconName
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ struct DocumentsView: View {
|
||||
}
|
||||
.navigationTitle(directoryLabel)
|
||||
.padding(.horizontal)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarTitleDisplayMode(RefreshControl.navigationBarTitleDisplayMode)
|
||||
.backport
|
||||
.refreshable {
|
||||
DispatchQueue.main.async {
|
||||
self.refresh()
|
||||
|
||||
@@ -15,10 +15,14 @@ struct AccountViewButton: View {
|
||||
} label: {
|
||||
HStack(spacing: 6) {
|
||||
if !accountPickerDisplaysUsername || !(model.current?.isPublic ?? true) {
|
||||
if let name = model.current?.app?.rawValue.capitalized {
|
||||
Image(name)
|
||||
.resizable()
|
||||
.frame(width: accountImageSize, height: accountImageSize)
|
||||
if #available(iOS 15, macOS 12, *) {
|
||||
if let name = model.current?.app?.rawValue.capitalized {
|
||||
Image(name)
|
||||
.resizable()
|
||||
.frame(width: accountImageSize, height: accountImageSize)
|
||||
} else {
|
||||
Image(systemName: "globe")
|
||||
}
|
||||
} else {
|
||||
Image(systemName: "globe")
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ struct AppSidebarPlaylists: View {
|
||||
|
||||
if accounts.app.userPlaylistsEndpointIncludesVideos, !playlist.videos.isEmpty {
|
||||
label
|
||||
.backport
|
||||
.badge(Text("\(playlist.videos.count)"))
|
||||
} else {
|
||||
label
|
||||
|
||||
@@ -33,6 +33,7 @@ struct AppSidebarSubscriptions: View {
|
||||
Spacer()
|
||||
}
|
||||
.lineLimit(1)
|
||||
.backport
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil)
|
||||
}
|
||||
.contextMenu {
|
||||
|
||||
@@ -95,6 +95,7 @@ struct AppTabNavigation: View {
|
||||
.accessibility(label: Text("Subscriptions"))
|
||||
}
|
||||
.tag(TabSelection.subscriptions)
|
||||
.backport
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedText : nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ struct Sidebar: View {
|
||||
}
|
||||
.onChange(of: navigation.sidebarSectionChanged) { _ in
|
||||
if let tabSelection = navigation.tabSelection {
|
||||
scrollScrollViewToItem(scrollView: scrollView, for: navigation.tabSelection)
|
||||
scrollScrollViewToItem(scrollView: scrollView, for: tabSelection)
|
||||
}
|
||||
}
|
||||
.listStyle(.sidebar)
|
||||
@@ -81,6 +81,7 @@ struct Sidebar: View {
|
||||
Label("Subscriptions", systemImage: "star.circle")
|
||||
.accessibility(label: Text("Subscriptions"))
|
||||
}
|
||||
.backport
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedText : nil)
|
||||
.contextMenu {
|
||||
playUnwatchedButton
|
||||
|
||||
@@ -47,7 +47,7 @@ final class AppleAVPlayerViewController: UIViewController {
|
||||
infoViewControllers.append(infoViewController([.chapters], title: "Chapters"))
|
||||
infoViewControllers.append(infoViewController([.comments], title: "Comments"))
|
||||
|
||||
let queueSections = [NowPlayingView.ViewSection.playingNext]
|
||||
var queueSections = [NowPlayingView.ViewSection.playingNext]
|
||||
|
||||
infoViewControllers.append(contentsOf: [
|
||||
infoViewController([.related], title: "Related"),
|
||||
|
||||
@@ -7,8 +7,19 @@ struct ControlBackgroundModifier: ViewModifier {
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if enabled {
|
||||
content
|
||||
if #available(iOS 15, macOS 12, *) {
|
||||
content
|
||||
.background(.thinMaterial)
|
||||
} else {
|
||||
content
|
||||
#if os(macOS)
|
||||
.background(VisualEffectBlur(material: .hudWindow))
|
||||
#elseif os(iOS)
|
||||
.background(VisualEffectBlur(blurStyle: .systemThinMaterial).edgesIgnoringSafeArea(edgesIgnoringSafeArea))
|
||||
#else
|
||||
.background(.thinMaterial)
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
content
|
||||
}
|
||||
|
||||
@@ -255,6 +255,8 @@ struct PlayerControls: View {
|
||||
{
|
||||
ThumbnailView(url: url)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.transition(.opacity)
|
||||
.animation(.default)
|
||||
} else if player.videoForDisplay == nil {
|
||||
Color.black
|
||||
}
|
||||
|
||||
@@ -18,9 +18,8 @@ struct RelatedView: View {
|
||||
|
||||
Color.clear.padding(.bottom, 50)
|
||||
.listRowBackground(Color.clear)
|
||||
#if os(iOS)
|
||||
.listRowSeparator(.hidden)
|
||||
#endif
|
||||
.backport
|
||||
.listRowSeparator(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,17 +219,25 @@ struct CommentView: View {
|
||||
}
|
||||
|
||||
private var commentText: some View {
|
||||
Text(comment.text)
|
||||
#if !os(tvOS)
|
||||
.textSelection(.enabled)
|
||||
#endif
|
||||
#if os(macOS)
|
||||
.font(.system(size: 14))
|
||||
#elseif os(iOS)
|
||||
.font(.system(size: 15))
|
||||
#endif
|
||||
.lineSpacing(3)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
Group {
|
||||
let text = Text(comment.text)
|
||||
#if os(macOS)
|
||||
.font(.system(size: 14))
|
||||
#elseif os(iOS)
|
||||
.font(.system(size: 15))
|
||||
#endif
|
||||
.lineSpacing(3)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
if #available(iOS 15.0, macOS 12.0, *) {
|
||||
text
|
||||
#if !os(tvOS)
|
||||
.textSelection(.enabled)
|
||||
#endif
|
||||
} else {
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func openChannelAction() {
|
||||
|
||||
@@ -32,8 +32,13 @@ struct CommentsView: View {
|
||||
|
||||
struct CommentsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
||||
CommentsView()
|
||||
.previewInterfaceOrientation(.landscapeRight)
|
||||
.injectFixtureEnvironmentObjects()
|
||||
}
|
||||
|
||||
CommentsView()
|
||||
.previewInterfaceOrientation(.landscapeRight)
|
||||
.injectFixtureEnvironmentObjects()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,10 +79,15 @@ struct InspectorView: View {
|
||||
Text(detail.localized())
|
||||
.foregroundColor(.secondary)
|
||||
Spacer()
|
||||
Text(value).lineLimit(1)
|
||||
#if !os(tvOS)
|
||||
let value = Text(value).lineLimit(1)
|
||||
if #available(iOS 15.0, macOS 12.0, *) {
|
||||
value
|
||||
#if !os(tvOS)
|
||||
.textSelection(.enabled)
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
.font(.caption)
|
||||
}
|
||||
|
||||
@@ -30,9 +30,8 @@ struct PlayerQueueView: View {
|
||||
#endif
|
||||
Color.clear.padding(.bottom, 50)
|
||||
.listRowBackground(Color.clear)
|
||||
#if os(iOS)
|
||||
.listRowSeparator(.hidden)
|
||||
#endif
|
||||
.backport
|
||||
.listRowSeparator(false)
|
||||
}
|
||||
.environment(\.inNavigationView, false)
|
||||
}
|
||||
|
||||
@@ -59,15 +59,23 @@ struct VideoDescription: View {
|
||||
|
||||
@ViewBuilder var textDescription: some View {
|
||||
#if !os(iOS)
|
||||
Text(description)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(shouldExpand ? 500 : Self.collapsedLines)
|
||||
#if !os(tvOS)
|
||||
.textSelection(.enabled)
|
||||
#endif
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.system(size: 14))
|
||||
.lineSpacing(3)
|
||||
Group {
|
||||
if #available(macOS 12, *) {
|
||||
Text(description)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(shouldExpand ? 500 : Self.collapsedLines)
|
||||
#if !os(tvOS)
|
||||
.textSelection(.enabled)
|
||||
#endif
|
||||
} else {
|
||||
Text(description)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(shouldExpand ? 500 : Self.collapsedLines)
|
||||
}
|
||||
}
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.system(size: 14))
|
||||
.lineSpacing(3)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -294,6 +294,9 @@ struct VideoPlayerView: View {
|
||||
}
|
||||
})
|
||||
#endif
|
||||
|
||||
.background(Color.black)
|
||||
|
||||
if !detailsHiddenInFullScreen {
|
||||
VideoDetails(
|
||||
video: player.videoForDisplay,
|
||||
|
||||
@@ -91,6 +91,13 @@ struct PlaylistsView: View {
|
||||
loadResource()
|
||||
}
|
||||
#if os(iOS)
|
||||
.refreshControl { refreshControl in
|
||||
model.load(force: true) {
|
||||
model.reloadPlaylists.toggle()
|
||||
refreshControl.endRefreshing()
|
||||
}
|
||||
}
|
||||
.backport
|
||||
.refreshable {
|
||||
DispatchQueue.main.async {
|
||||
model.load(force: true) { model.reloadPlaylists.toggle() }
|
||||
|
||||
@@ -2,6 +2,7 @@ import Repeat
|
||||
import SwiftUI
|
||||
import SwiftUIIntrospect
|
||||
|
||||
@available(iOS 15.0, macOS 12, *)
|
||||
struct FocusableSearchTextField: View {
|
||||
@ObservedObject private var state = SearchModel.shared
|
||||
|
||||
|
||||
@@ -95,7 +95,11 @@ struct SearchView: View {
|
||||
filtersMenu
|
||||
}
|
||||
|
||||
FocusableSearchTextField()
|
||||
if #available(macOS 12, *) {
|
||||
FocusableSearchTextField()
|
||||
} else {
|
||||
SearchTextField()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -175,7 +179,11 @@ struct SearchView: View {
|
||||
searchMenu
|
||||
}
|
||||
ToolbarItem(placement: .principal) {
|
||||
FocusableSearchTextField()
|
||||
if #available(iOS 15, *) {
|
||||
FocusableSearchTextField()
|
||||
} else {
|
||||
SearchTextField()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
|
||||
@@ -201,7 +201,7 @@ struct QualityProfileForm: View {
|
||||
|
||||
@ViewBuilder var formatsPicker: some View {
|
||||
#if os(macOS)
|
||||
ForEach(QualityProfile.Format.allCases, id: \.self) { format in
|
||||
let list = ForEach(QualityProfile.Format.allCases, id: \.self) { format in
|
||||
MultiselectRow(
|
||||
title: format.description,
|
||||
selected: isFormatSelected(format),
|
||||
@@ -210,8 +210,16 @@ struct QualityProfileForm: View {
|
||||
toggleFormat(format, value: value)
|
||||
}
|
||||
}
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
|
||||
Group {
|
||||
if #available(macOS 12.0, *) {
|
||||
list
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
} else {
|
||||
list
|
||||
.listStyle(.inset)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
#else
|
||||
ForEach(QualityProfile.Format.allCases, id: \.self) { format in
|
||||
|
||||
@@ -175,14 +175,24 @@ struct QualitySettings: View {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
List {
|
||||
if #available(macOS 12.0, *) {
|
||||
#if os(macOS)
|
||||
List {
|
||||
list
|
||||
}
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
#else
|
||||
list
|
||||
}
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
#else
|
||||
list
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
#if os(macOS)
|
||||
List {
|
||||
list
|
||||
}
|
||||
#else
|
||||
list
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,15 @@ struct SponsorBlockSettings: View {
|
||||
}
|
||||
}
|
||||
|
||||
list
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
Group {
|
||||
if #available(macOS 12.0, *) {
|
||||
list
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
} else {
|
||||
list
|
||||
.listStyle(.inset)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
#else
|
||||
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
||||
|
||||
@@ -34,9 +34,8 @@ struct ChannelsView: View {
|
||||
Text(channel.name)
|
||||
.lineLimit(1)
|
||||
}
|
||||
#if !os(tvOS)
|
||||
.backport
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil)
|
||||
#endif
|
||||
|
||||
Group {
|
||||
#if os(tvOS)
|
||||
@@ -74,9 +73,8 @@ struct ChannelsView: View {
|
||||
|
||||
Color.clear.padding(.bottom, 50)
|
||||
.listRowBackground(Color.clear)
|
||||
#if os(iOS)
|
||||
.listRowSeparator(.hidden)
|
||||
#endif
|
||||
.backport
|
||||
.listRowSeparator(false)
|
||||
}
|
||||
}
|
||||
#if !os(tvOS)
|
||||
@@ -91,8 +89,14 @@ struct ChannelsView: View {
|
||||
subscriptions.load(force: true)
|
||||
}
|
||||
#if os(iOS)
|
||||
.refreshControl { refreshControl in
|
||||
subscriptions.load(force: true) {
|
||||
refreshControl.endRefreshing()
|
||||
}
|
||||
}
|
||||
.backport
|
||||
.refreshable {
|
||||
subscriptions.load(force: true)
|
||||
await subscriptions.load(force: true)
|
||||
}
|
||||
#endif
|
||||
#if !os(tvOS)
|
||||
|
||||
@@ -22,8 +22,14 @@ struct FeedView: View {
|
||||
feed.loadResources()
|
||||
}
|
||||
#if os(iOS)
|
||||
.refreshControl { refreshControl in
|
||||
feed.loadResources(force: true) {
|
||||
refreshControl.endRefreshing()
|
||||
}
|
||||
}
|
||||
.backport
|
||||
.refreshable {
|
||||
feed.loadResources(force: true)
|
||||
await feed.loadResources(force: true)
|
||||
}
|
||||
#endif
|
||||
#if !os(tvOS)
|
||||
|
||||
@@ -16,7 +16,11 @@ struct TrendingCountry: View {
|
||||
VStack {
|
||||
#if !os(tvOS)
|
||||
HStack {
|
||||
TextField("Country", text: $query, prompt: Text(Self.prompt))
|
||||
if #available(iOS 15.0, macOS 12.0, *) {
|
||||
TextField("Country", text: $query, prompt: Text(Self.prompt))
|
||||
} else {
|
||||
TextField(Self.prompt, text: $query)
|
||||
}
|
||||
|
||||
Button("Done") { selectCountryAndDismiss() }
|
||||
.keyboardShortcut(.defaultAction)
|
||||
@@ -53,8 +57,12 @@ struct TrendingCountry: View {
|
||||
|
||||
return Group {
|
||||
#if os(macOS)
|
||||
list
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
if #available(macOS 12.0, *) {
|
||||
list
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
} else {
|
||||
list
|
||||
}
|
||||
#else
|
||||
list
|
||||
#endif
|
||||
|
||||
@@ -95,7 +95,12 @@ struct TrendingView: View {
|
||||
.navigationTitle("Trending")
|
||||
#endif
|
||||
#if os(iOS)
|
||||
|
||||
.refreshControl { refreshControl in
|
||||
resource.load().onCompletion { _ in
|
||||
refreshControl.endRefreshing()
|
||||
}
|
||||
}
|
||||
.backport
|
||||
.refreshable {
|
||||
DispatchQueue.main.async {
|
||||
resource.load()
|
||||
|
||||
@@ -48,19 +48,23 @@ struct ThumbnailView: View {
|
||||
}
|
||||
|
||||
@ViewBuilder var asyncImageIfAvailable: some View {
|
||||
CachedAsyncImage(url: url, urlCache: BaseCacheModel.imageCache, transaction: Transaction(animation: .default)) { phase in
|
||||
switch phase {
|
||||
case let .success(image):
|
||||
image
|
||||
.resizable()
|
||||
case .failure:
|
||||
placeholder.onAppear {
|
||||
guard let url else { return }
|
||||
thumbnails.insertUnloadable(url)
|
||||
if #available(iOS 15, macOS 12, *) {
|
||||
CachedAsyncImage(url: url, urlCache: BaseCacheModel.imageCache) { phase in
|
||||
switch phase {
|
||||
case let .success(image):
|
||||
image
|
||||
.resizable()
|
||||
case .failure:
|
||||
placeholder.onAppear {
|
||||
guard let url else { return }
|
||||
thumbnails.insertUnloadable(url)
|
||||
}
|
||||
default:
|
||||
placeholder
|
||||
}
|
||||
default:
|
||||
placeholder
|
||||
}
|
||||
} else {
|
||||
webImage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ struct OpenSettingsButton: View {
|
||||
#endif
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
let button = Button {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
|
||||
#if os(macOS)
|
||||
@@ -20,7 +20,13 @@ struct OpenSettingsButton: View {
|
||||
Label("Open Settings", systemImage: "gearshape.2")
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.buttonStyle(.borderedProminent)
|
||||
|
||||
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
||||
button
|
||||
.buttonStyle(.borderedProminent)
|
||||
} else {
|
||||
button
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,14 @@ struct PopularView: View {
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.refreshControl { refreshControl in
|
||||
resource?.load().onCompletion { _ in
|
||||
refreshControl.endRefreshing()
|
||||
}
|
||||
.onFailure { self.error = $0 }
|
||||
.onSuccess { _ in self.error = nil }
|
||||
}
|
||||
.backport
|
||||
.refreshable {
|
||||
DispatchQueue.main.async {
|
||||
resource?.load()
|
||||
@@ -54,7 +62,7 @@ struct PopularView: View {
|
||||
.onSuccess { _ in self.error = nil }
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarTitleDisplayMode(RefreshControl.navigationBarTitleDisplayMode)
|
||||
#endif
|
||||
#if os(macOS)
|
||||
.toolbar {
|
||||
|
||||
@@ -281,7 +281,11 @@ struct VideoContextMenuView: View {
|
||||
let label = Label("Remove…", systemImage: "trash.fill")
|
||||
.foregroundColor(Color("AppRedColor"))
|
||||
|
||||
Button(role: .destructive, action: action) { label }
|
||||
if #available(iOS 15, macOS 12, *) {
|
||||
Button(role: .destructive, action: action) { label }
|
||||
} else {
|
||||
Button(action: action) { label }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
15
Vendor/RefreshControl/Extensions/UIResponder+Extensions.swift
vendored
Normal file
15
Vendor/RefreshControl/Extensions/UIResponder+Extensions.swift
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// UIResponder+Extensions.swift
|
||||
// SwiftUI_Pull_to_Refresh
|
||||
//
|
||||
// Created by Geri Borbás on 21/09/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
extension UIResponder {
|
||||
var parentViewController: UIViewController? {
|
||||
next as? UIViewController ?? next?.parentViewController
|
||||
}
|
||||
}
|
||||
70
Vendor/RefreshControl/Extensions/UIView+Extensions.swift
vendored
Normal file
70
Vendor/RefreshControl/Extensions/UIView+Extensions.swift
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// UIView+Extensions.swift
|
||||
// SwiftUI_Pull_to_Refresh
|
||||
//
|
||||
// Created by Geri Borbás on 19/09/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
extension UIView {
|
||||
/// Returs frame in screen coordinates.
|
||||
var globalFrame: CGRect {
|
||||
if let window {
|
||||
return convert(bounds, to: window.screen.coordinateSpace)
|
||||
} else {
|
||||
return .zero
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns with all the instances of the given view type in the view hierarchy.
|
||||
func viewsInHierarchy<ViewType: UIView>() -> [ViewType]? {
|
||||
var views: [ViewType] = []
|
||||
viewsInHierarchy(views: &views)
|
||||
return views.isEmpty ? nil : views
|
||||
}
|
||||
|
||||
private func viewsInHierarchy<ViewType: UIView>(views: inout [ViewType]) {
|
||||
subviews.forEach { eachSubView in
|
||||
if let matchingView = eachSubView as? ViewType {
|
||||
views.append(matchingView)
|
||||
}
|
||||
eachSubView.viewsInHierarchy(views: &views)
|
||||
}
|
||||
}
|
||||
|
||||
/// Search ancestral view hierarcy for the given view type.
|
||||
func searchViewAnchestorsFor<ViewType: UIView>(
|
||||
_ onViewFound: (ViewType) -> Void
|
||||
) {
|
||||
if let matchingView = superview as? ViewType {
|
||||
onViewFound(matchingView)
|
||||
} else {
|
||||
superview?.searchViewAnchestorsFor(onViewFound)
|
||||
}
|
||||
}
|
||||
|
||||
/// Search ancestral view hierarcy for the given view type.
|
||||
func searchViewAnchestorsFor<ViewType: UIView>() -> ViewType? {
|
||||
if let matchingView = superview as? ViewType {
|
||||
return matchingView
|
||||
} else {
|
||||
return superview?.searchViewAnchestorsFor()
|
||||
}
|
||||
}
|
||||
|
||||
func printViewHierarchyInformation(_ level: Int = 0) {
|
||||
printViewInformation(level)
|
||||
subviews.forEach { $0.printViewHierarchyInformation(level + 1) }
|
||||
}
|
||||
|
||||
func printViewInformation(_ level: Int) {
|
||||
let leadingWhitespace = String(repeating: " ", count: level)
|
||||
let className = "\(Self.self)"
|
||||
let superclassName = "\(superclass!)"
|
||||
let frame = "\(self.frame)"
|
||||
let id = (accessibilityIdentifier == nil) ? "" : " `\(accessibilityIdentifier!)`"
|
||||
print("\(leadingWhitespace)\(className): \(superclassName)\(id) \(frame)")
|
||||
}
|
||||
}
|
||||
56
Vendor/RefreshControl/RefreshControl.swift
vendored
Normal file
56
Vendor/RefreshControl/RefreshControl.swift
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// RefreshControl.swift
|
||||
// SwiftUI_Pull_to_Refresh
|
||||
//
|
||||
// Created by Geri Borbás on 18/09/2021.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
final class RefreshControl: ObservableObject {
|
||||
static var navigationBarTitleDisplayMode: NavigationBarItem.TitleDisplayMode {
|
||||
if #available(iOS 15.0, *) {
|
||||
return .automatic
|
||||
}
|
||||
|
||||
return .inline
|
||||
}
|
||||
|
||||
let onValueChanged: (_ refreshControl: UIRefreshControl) -> Void
|
||||
|
||||
init(onValueChanged: @escaping ((UIRefreshControl) -> Void)) {
|
||||
self.onValueChanged = onValueChanged
|
||||
}
|
||||
|
||||
/// Adds a `UIRefreshControl` to the `UIScrollView` provided.
|
||||
func add(to scrollView: UIScrollView) {
|
||||
scrollView.refreshControl = UIRefreshControl().withTarget(
|
||||
self,
|
||||
action: #selector(onValueChangedAction),
|
||||
for: .valueChanged
|
||||
)
|
||||
.testable(as: "RefreshControl")
|
||||
}
|
||||
|
||||
@objc private func onValueChangedAction(sender: UIRefreshControl) {
|
||||
onValueChanged(sender)
|
||||
}
|
||||
}
|
||||
|
||||
extension UIRefreshControl {
|
||||
/// Convinience method to assign target action inline.
|
||||
func withTarget(_ target: Any?, action: Selector, for controlEvents: UIControl.Event) -> UIRefreshControl {
|
||||
addTarget(target, action: action, for: controlEvents)
|
||||
return self
|
||||
}
|
||||
|
||||
/// Convinience method to match refresh control for UI testing.
|
||||
func testable(as id: String) -> UIRefreshControl {
|
||||
isAccessibilityElement = true
|
||||
accessibilityIdentifier = id
|
||||
return self
|
||||
}
|
||||
}
|
||||
46
Vendor/RefreshControl/RefreshControlModifier.swift
vendored
Normal file
46
Vendor/RefreshControl/RefreshControlModifier.swift
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// RefreshControlModifier.swift
|
||||
// SwiftUI_Pull_to_Refresh
|
||||
//
|
||||
// Created by Geri Borbás on 18/09/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct RefreshControlModifier: ViewModifier {
|
||||
@State private var geometryReaderFrame: CGRect = .zero
|
||||
let refreshControl: RefreshControl
|
||||
|
||||
init(onValueChanged: @escaping (UIRefreshControl) -> Void) {
|
||||
refreshControl = RefreshControl(onValueChanged: onValueChanged)
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
||||
return content
|
||||
} else {
|
||||
return content
|
||||
.background(
|
||||
GeometryReader { geometry in
|
||||
ScrollViewMatcher(
|
||||
onResolve: { scrollView in
|
||||
refreshControl.add(to: scrollView)
|
||||
},
|
||||
geometryReaderFrame: $geometryReaderFrame
|
||||
)
|
||||
.preference(key: FramePreferenceKey.self, value: geometry.frame(in: .global))
|
||||
.onPreferenceChange(FramePreferenceKey.self) { frame in
|
||||
self.geometryReaderFrame = frame
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
func refreshControl(onValueChanged: @escaping (_ refreshControl: UIRefreshControl) -> Void) -> some View {
|
||||
modifier(RefreshControlModifier(onValueChanged: onValueChanged))
|
||||
}
|
||||
}
|
||||
18
Vendor/RefreshControl/ScrollViewMatcher/FramePreferenceKey.swift
vendored
Normal file
18
Vendor/RefreshControl/ScrollViewMatcher/FramePreferenceKey.swift
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// FramePreferenceKey.swift
|
||||
// SwiftUI_Pull_to_Refresh
|
||||
//
|
||||
// Created by Geri Borbás on 21/09/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct FramePreferenceKey: PreferenceKey {
|
||||
typealias Value = CGRect
|
||||
static var defaultValue = CGRect.zero
|
||||
|
||||
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
|
||||
value = nextValue()
|
||||
}
|
||||
}
|
||||
106
Vendor/RefreshControl/ScrollViewMatcher/ScrollViewMatcher.swift
vendored
Normal file
106
Vendor/RefreshControl/ScrollViewMatcher/ScrollViewMatcher.swift
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// ScrollViewMatcher.swift
|
||||
// SwiftUI_Pull_to_Refresh
|
||||
//
|
||||
// Created by Geri Borbás on 17/09/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
final class ScrollViewMatcher: UIViewControllerRepresentable {
|
||||
let onMatch: (UIScrollView) -> Void
|
||||
@Binding var geometryReaderFrame: CGRect
|
||||
|
||||
init(onResolve: @escaping (UIScrollView) -> Void, geometryReaderFrame: Binding<CGRect>) {
|
||||
onMatch = onResolve
|
||||
_geometryReaderFrame = geometryReaderFrame
|
||||
}
|
||||
|
||||
func makeUIViewController(context _: Context) -> ScrollViewMatcherViewController {
|
||||
ScrollViewMatcherViewController(onResolve: onMatch, geometryReaderFrame: geometryReaderFrame)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ viewController: ScrollViewMatcherViewController, context _: Context) {
|
||||
viewController.geometryReaderFrame = geometryReaderFrame
|
||||
}
|
||||
}
|
||||
|
||||
final class ScrollViewMatcherViewController: UIViewController {
|
||||
let onMatch: (UIScrollView) -> Void
|
||||
private var scrollView: UIScrollView? {
|
||||
didSet {
|
||||
if oldValue != scrollView,
|
||||
let scrollView
|
||||
{
|
||||
onMatch(scrollView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var geometryReaderFrame: CGRect {
|
||||
didSet {
|
||||
match()
|
||||
}
|
||||
}
|
||||
|
||||
init(onResolve: @escaping (UIScrollView) -> Void, geometryReaderFrame: CGRect, debug _: Bool = false) {
|
||||
onMatch = onResolve
|
||||
self.geometryReaderFrame = geometryReaderFrame
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder _: NSCoder) {
|
||||
fatalError("Use init(onMatch:) to instantiate ScrollViewMatcherViewController.")
|
||||
}
|
||||
|
||||
func match() {
|
||||
// matchUsingHierarchy()
|
||||
matchUsingGeometry()
|
||||
}
|
||||
|
||||
func matchUsingHierarchy() {
|
||||
if parent != nil {
|
||||
// Lookup view ancestry for any `UIScrollView`.
|
||||
view.searchViewAnchestorsFor { (scrollView: UIScrollView) in
|
||||
self.scrollView = scrollView
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func matchUsingGeometry() {
|
||||
if let parent {
|
||||
if let scrollViewsInHierarchy: [UIScrollView] = parent.view.viewsInHierarchy() {
|
||||
// Return first match if only a single scroll view is found in the hierarchy.
|
||||
if scrollViewsInHierarchy.count == 1,
|
||||
let firstScrollViewInHierarchy = scrollViewsInHierarchy.first
|
||||
{
|
||||
scrollView = firstScrollViewInHierarchy
|
||||
|
||||
// Filter by frame origins if multiple matches found.
|
||||
} else {
|
||||
if let firstMatchingFrameOrigin = scrollViewsInHierarchy.filter({
|
||||
$0.globalFrame.origin.close(to: geometryReaderFrame.origin)
|
||||
}).first {
|
||||
scrollView = firstMatchingFrameOrigin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func didMove(toParent parent: UIViewController?) {
|
||||
super.didMove(toParent: parent)
|
||||
match()
|
||||
}
|
||||
}
|
||||
|
||||
extension CGPoint {
|
||||
/// Returns `true` if this point is close the other point (considering a ~1 pt tolerance).
|
||||
func close(to point: CGPoint) -> Bool {
|
||||
let inset = Double(1)
|
||||
let rect = CGRect(x: x - inset, y: y - inset, width: inset * 2, height: inset * 2)
|
||||
return rect.contains(point)
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,9 @@
|
||||
371F2F1A269B43D300E4A7AB /* NavigationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371F2F19269B43D300E4A7AB /* NavigationModel.swift */; };
|
||||
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371F2F19269B43D300E4A7AB /* NavigationModel.swift */; };
|
||||
371F2F1C269B43D300E4A7AB /* NavigationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371F2F19269B43D300E4A7AB /* NavigationModel.swift */; };
|
||||
3722AEBC274DA396005EA4D6 /* Badge+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */; };
|
||||
3722AEBE274DA401005EA4D6 /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBD274DA401005EA4D6 /* Backport.swift */; };
|
||||
3726386E2948A4B80043702D /* Badge+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */; };
|
||||
37270F1C28E06E3E00856150 /* String+Localizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37270F1B28E06E3E00856150 /* String+Localizable.swift */; };
|
||||
37270F1D28E06E3E00856150 /* String+Localizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37270F1B28E06E3E00856150 /* String+Localizable.swift */; };
|
||||
37270F1E28E06E3E00856150 /* String+Localizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37270F1B28E06E3E00856150 /* String+Localizable.swift */; };
|
||||
@@ -322,6 +324,7 @@
|
||||
37579D5E27864F5F00FD0B98 /* Help.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37579D5C27864F5F00FD0B98 /* Help.swift */; };
|
||||
37579D5F27864F5F00FD0B98 /* Help.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37579D5C27864F5F00FD0B98 /* Help.swift */; };
|
||||
3758638A2721B0A9000CB14E /* ChannelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3743B86727216D3600261544 /* ChannelCell.swift */; };
|
||||
3759234628C26C7B00C052EC /* Refreshable+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3759234528C26C7B00C052EC /* Refreshable+Backport.swift */; };
|
||||
37599F30272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; };
|
||||
37599F31272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; };
|
||||
37599F32272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; };
|
||||
@@ -429,6 +432,24 @@
|
||||
37732FF42703D32400F04329 /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37732FF32703D32400F04329 /* Sidebar.swift */; };
|
||||
37732FF52703D32400F04329 /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37732FF32703D32400F04329 /* Sidebar.swift */; };
|
||||
37737786276F9858000521C1 /* Windows.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37737785276F9858000521C1 /* Windows.swift */; };
|
||||
3773B7FE2ADC076800B5FEF3 /* RefreshControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7F52ADC076800B5FEF3 /* RefreshControl.swift */; };
|
||||
3773B8012ADC076800B5FEF3 /* README in Resources */ = {isa = PBXBuildFile; fileRef = 3773B7F62ADC076800B5FEF3 /* README */; };
|
||||
3773B8022ADC076800B5FEF3 /* README in Resources */ = {isa = PBXBuildFile; fileRef = 3773B7F62ADC076800B5FEF3 /* README */; };
|
||||
3773B8032ADC076800B5FEF3 /* README in Resources */ = {isa = PBXBuildFile; fileRef = 3773B7F62ADC076800B5FEF3 /* README */; };
|
||||
3773B8042ADC076800B5FEF3 /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7F82ADC076800B5FEF3 /* UIView+Extensions.swift */; };
|
||||
3773B8062ADC076800B5FEF3 /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7F82ADC076800B5FEF3 /* UIView+Extensions.swift */; };
|
||||
3773B8072ADC076800B5FEF3 /* UIResponder+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7F92ADC076800B5FEF3 /* UIResponder+Extensions.swift */; };
|
||||
3773B8092ADC076800B5FEF3 /* UIResponder+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7F92ADC076800B5FEF3 /* UIResponder+Extensions.swift */; };
|
||||
3773B80A2ADC076800B5FEF3 /* RefreshControlModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7FA2ADC076800B5FEF3 /* RefreshControlModifier.swift */; };
|
||||
3773B80D2ADC076800B5FEF3 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7FC2ADC076800B5FEF3 /* FramePreferenceKey.swift */; };
|
||||
3773B80E2ADC076800B5FEF3 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7FC2ADC076800B5FEF3 /* FramePreferenceKey.swift */; };
|
||||
3773B80F2ADC076800B5FEF3 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7FC2ADC076800B5FEF3 /* FramePreferenceKey.swift */; };
|
||||
3773B8102ADC076800B5FEF3 /* ScrollViewMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7FD2ADC076800B5FEF3 /* ScrollViewMatcher.swift */; };
|
||||
3773B8122ADC076800B5FEF3 /* ScrollViewMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B7FD2ADC076800B5FEF3 /* ScrollViewMatcher.swift */; };
|
||||
3773B8152ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B8132ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift */; };
|
||||
3773B8162ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B8132ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift */; };
|
||||
3773B8172ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B8142ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift */; };
|
||||
3773B8182ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3773B8142ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift */; };
|
||||
3774123327387CB000423605 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
|
||||
3774124927387D2300423605 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF28F26740715007FC770 /* Channel.swift */; };
|
||||
3774124A27387D2300423605 /* ContentItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FB28402721B22200A57617 /* ContentItem.swift */; };
|
||||
@@ -500,6 +521,9 @@
|
||||
377ABC48286E5887009C986F /* Sequence+Unique.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377ABC47286E5887009C986F /* Sequence+Unique.swift */; };
|
||||
377ABC49286E5887009C986F /* Sequence+Unique.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377ABC47286E5887009C986F /* Sequence+Unique.swift */; };
|
||||
377ABC4A286E5887009C986F /* Sequence+Unique.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377ABC47286E5887009C986F /* Sequence+Unique.swift */; };
|
||||
377E17142928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
||||
377E17152928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
||||
377E17162928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
||||
377F9F74294403770043F856 /* Cache in Frameworks */ = {isa = PBXBuildFile; productRef = 377F9F73294403770043F856 /* Cache */; };
|
||||
377F9F76294403880043F856 /* Cache in Frameworks */ = {isa = PBXBuildFile; productRef = 377F9F75294403880043F856 /* Cache */; };
|
||||
377F9F7B294403F20043F856 /* VideosCacheModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377F9F7A294403F20043F856 /* VideosCacheModel.swift */; };
|
||||
@@ -543,8 +567,12 @@
|
||||
3788AC2726F6840700F6BAA9 /* FavoriteItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3788AC2626F6840700F6BAA9 /* FavoriteItemView.swift */; };
|
||||
3788AC2826F6840700F6BAA9 /* FavoriteItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3788AC2626F6840700F6BAA9 /* FavoriteItemView.swift */; };
|
||||
3788AC2926F6840700F6BAA9 /* FavoriteItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3788AC2626F6840700F6BAA9 /* FavoriteItemView.swift */; };
|
||||
378AE93A274EDFAF006A4EE1 /* Badge+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */; };
|
||||
378AE93C274EDFB2006A4EE1 /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBD274DA401005EA4D6 /* Backport.swift */; };
|
||||
378AE93D274EDFB3006A4EE1 /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBD274DA401005EA4D6 /* Backport.swift */; };
|
||||
378AE93E274EDFB4006A4EE1 /* Tint+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */; };
|
||||
378AE93F274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */; };
|
||||
378AE940274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */; };
|
||||
378AE943274EF00A006A4EE1 /* Color+Background.swift in Sources */ = {isa = PBXBuildFile; fileRef = 378AE942274EF00A006A4EE1 /* Color+Background.swift */; };
|
||||
378AE944274EF00A006A4EE1 /* Color+Background.swift in Sources */ = {isa = PBXBuildFile; fileRef = 378AE942274EF00A006A4EE1 /* Color+Background.swift */; };
|
||||
378AE945274EF00A006A4EE1 /* Color+Background.swift in Sources */ = {isa = PBXBuildFile; fileRef = 378AE942274EF00A006A4EE1 /* Color+Background.swift */; };
|
||||
@@ -1065,7 +1093,9 @@
|
||||
371CC76F29468BDC00979C1A /* SettingsButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsButtons.swift; sourceTree = "<group>"; };
|
||||
371CC7732946963000979C1A /* ListingStyleButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListingStyleButtons.swift; sourceTree = "<group>"; };
|
||||
371F2F19269B43D300E4A7AB /* NavigationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationModel.swift; sourceTree = "<group>"; };
|
||||
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Badge+Backport.swift"; sourceTree = "<group>"; };
|
||||
3722AEBD274DA401005EA4D6 /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; };
|
||||
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Tint+Backport.swift"; sourceTree = "<group>"; };
|
||||
37270F1B28E06E3E00856150 /* String+Localizable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Localizable.swift"; sourceTree = "<group>"; };
|
||||
3728203F2945E4A8009A0E2D /* SubscriptionsPageButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsPageButton.swift; sourceTree = "<group>"; };
|
||||
3729037D2739E47400EA99F6 /* MenuCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCommands.swift; sourceTree = "<group>"; };
|
||||
@@ -1124,6 +1154,7 @@
|
||||
3756C2A52861131100E4B059 /* NetworkState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkState.swift; sourceTree = "<group>"; };
|
||||
3756C2A92861151C00E4B059 /* NetworkStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkStateModel.swift; sourceTree = "<group>"; };
|
||||
37579D5C27864F5F00FD0B98 /* Help.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Help.swift; sourceTree = "<group>"; };
|
||||
3759234528C26C7B00C052EC /* Refreshable+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Refreshable+Backport.swift"; sourceTree = "<group>"; };
|
||||
37599F2F272B42810087F250 /* FavoriteItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteItem.swift; sourceTree = "<group>"; };
|
||||
37599F33272B44000087F250 /* FavoritesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesModel.swift; sourceTree = "<group>"; };
|
||||
37599F37272B4D740087F250 /* FavoriteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteButton.swift; sourceTree = "<group>"; };
|
||||
@@ -1175,6 +1206,15 @@
|
||||
37732FEF2703A26300F04329 /* AccountValidationStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountValidationStatus.swift; sourceTree = "<group>"; };
|
||||
37732FF32703D32400F04329 /* Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sidebar.swift; sourceTree = "<group>"; };
|
||||
37737785276F9858000521C1 /* Windows.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Windows.swift; sourceTree = "<group>"; };
|
||||
3773B7F52ADC076800B5FEF3 /* RefreshControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshControl.swift; sourceTree = "<group>"; };
|
||||
3773B7F62ADC076800B5FEF3 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
3773B7F82ADC076800B5FEF3 /* UIView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = "<group>"; };
|
||||
3773B7F92ADC076800B5FEF3 /* UIResponder+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIResponder+Extensions.swift"; sourceTree = "<group>"; };
|
||||
3773B7FA2ADC076800B5FEF3 /* RefreshControlModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshControlModifier.swift; sourceTree = "<group>"; };
|
||||
3773B7FC2ADC076800B5FEF3 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = "<group>"; };
|
||||
3773B7FD2ADC076800B5FEF3 /* ScrollViewMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollViewMatcher.swift; sourceTree = "<group>"; };
|
||||
3773B8132ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "VisualEffectBlur-iOS.swift"; sourceTree = "<group>"; };
|
||||
3773B8142ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "VisualEffectBlur-macOS.swift"; sourceTree = "<group>"; };
|
||||
37758C0A2A1D1C8B001FD900 /* HideWatchedButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideWatchedButtons.swift; sourceTree = "<group>"; };
|
||||
3776924D294630110055EC18 /* ChannelAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelAvatarView.swift; sourceTree = "<group>"; };
|
||||
3776925129463C310055EC18 /* PlaylistsCacheModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistsCacheModel.swift; sourceTree = "<group>"; };
|
||||
@@ -1185,6 +1225,7 @@
|
||||
377ABC3F286E4AD5009C986F /* InstancesManifest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstancesManifest.swift; sourceTree = "<group>"; };
|
||||
377ABC43286E4B74009C986F /* ManifestedInstance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManifestedInstance.swift; sourceTree = "<group>"; };
|
||||
377ABC47286E5887009C986F /* Sequence+Unique.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Sequence+Unique.swift"; sourceTree = "<group>"; };
|
||||
377E17132928265900894889 /* ListRowSeparator+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ListRowSeparator+Backport.swift"; sourceTree = "<group>"; };
|
||||
377F9F7A294403F20043F856 /* VideosCacheModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideosCacheModel.swift; sourceTree = "<group>"; };
|
||||
377F9F7E2944175F0043F856 /* FeedCacheModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedCacheModel.swift; sourceTree = "<group>"; };
|
||||
377FF88A291A60310028EB0B /* OpenVideosModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenVideosModel.swift; sourceTree = "<group>"; };
|
||||
@@ -1321,6 +1362,12 @@
|
||||
37DCD3162A191A180059A470 /* AVPlayerViewController+FullScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVPlayerViewController+FullScreen.swift"; sourceTree = "<group>"; };
|
||||
37DD87C6271C9CFE0027CBF9 /* PlayerStreams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerStreams.swift; sourceTree = "<group>"; };
|
||||
37DD9DA22785BBC900539416 /* NoCommentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoCommentsView.swift; sourceTree = "<group>"; };
|
||||
37DD9DAF2785D58D00539416 /* RefreshControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshControl.swift; sourceTree = "<group>"; };
|
||||
37DD9DB02785D58D00539416 /* RefreshControlModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshControlModifier.swift; sourceTree = "<group>"; };
|
||||
37DD9DB82785D60200539416 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = "<group>"; };
|
||||
37DD9DB92785D60200539416 /* ScrollViewMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollViewMatcher.swift; sourceTree = "<group>"; };
|
||||
37DD9DC12785D63A00539416 /* UIView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = "<group>"; };
|
||||
37DD9DC22785D63A00539416 /* UIResponder+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIResponder+Extensions.swift"; sourceTree = "<group>"; };
|
||||
37E04C0E275940FB00172673 /* VerticalScrollingFix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalScrollingFix.swift; sourceTree = "<group>"; };
|
||||
37E084AB2753D95F00039B7D /* AccountsNavigationLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsNavigationLink.swift; sourceTree = "<group>"; };
|
||||
37E64DD026D597EB00C71877 /* SubscribedChannelsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscribedChannelsModel.swift; sourceTree = "<group>"; };
|
||||
@@ -1651,9 +1698,15 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3722AEBD274DA401005EA4D6 /* Backport.swift */,
|
||||
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */,
|
||||
377E17132928265900894889 /* ListRowSeparator+Backport.swift */,
|
||||
37136CAB286273060095C0CF /* PersistentSystemOverlays+Backport.swift */,
|
||||
3773B8132ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift */,
|
||||
3773B8142ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift */,
|
||||
3759234528C26C7B00C052EC /* Refreshable+Backport.swift */,
|
||||
37E80F3F287B472300561799 /* ScrollContentBackground+Backport.swift */,
|
||||
376E331128AD3B320070E30C /* ScrollDismissesKeyboard+Backport.swift */,
|
||||
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */,
|
||||
37B7CFE82A19603B001B0564 /* ToolbarBackground+Backport.swift */,
|
||||
37B7CFEA2A1960EC001B0564 /* ToolbarColorScheme+Backport.swift */,
|
||||
);
|
||||
@@ -1822,6 +1875,57 @@
|
||||
path = Modifiers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3773B7D12ADC05FF00B5FEF3 /* Recovered References */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
37DD9DC12785D63A00539416 /* UIView+Extensions.swift */,
|
||||
37DD9DAF2785D58D00539416 /* RefreshControl.swift */,
|
||||
37DD9DB02785D58D00539416 /* RefreshControlModifier.swift */,
|
||||
37DD9DB82785D60200539416 /* FramePreferenceKey.swift */,
|
||||
37DD9DB92785D60200539416 /* ScrollViewMatcher.swift */,
|
||||
37DD9DC22785D63A00539416 /* UIResponder+Extensions.swift */,
|
||||
);
|
||||
name = "Recovered References";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3773B7F32ADC076800B5FEF3 /* Vendor */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3773B7F42ADC076800B5FEF3 /* RefreshControl */,
|
||||
);
|
||||
path = Vendor;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3773B7F42ADC076800B5FEF3 /* RefreshControl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3773B7F52ADC076800B5FEF3 /* RefreshControl.swift */,
|
||||
3773B7F62ADC076800B5FEF3 /* README */,
|
||||
3773B7F72ADC076800B5FEF3 /* Extensions */,
|
||||
3773B7FA2ADC076800B5FEF3 /* RefreshControlModifier.swift */,
|
||||
3773B7FB2ADC076800B5FEF3 /* ScrollViewMatcher */,
|
||||
);
|
||||
path = RefreshControl;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3773B7F72ADC076800B5FEF3 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3773B7F82ADC076800B5FEF3 /* UIView+Extensions.swift */,
|
||||
3773B7F92ADC076800B5FEF3 /* UIResponder+Extensions.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3773B7FB2ADC076800B5FEF3 /* ScrollViewMatcher */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3773B7FC2ADC076800B5FEF3 /* FramePreferenceKey.swift */,
|
||||
3773B7FD2ADC076800B5FEF3 /* ScrollViewMatcher.swift */,
|
||||
);
|
||||
path = ScrollViewMatcher;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
377F9F79294403DC0043F856 /* Cache */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1975,6 +2079,7 @@
|
||||
37D4B159267164AE00C925CA /* tvOS */,
|
||||
37D4B1B72672CFE300C925CA /* Model */,
|
||||
37D4B0C12671614700C925CA /* Shared */,
|
||||
3773B7F32ADC076800B5FEF3 /* Vendor */,
|
||||
3722AEBA274DA312005EA4D6 /* Backports */,
|
||||
37C7A9022679058300E721B4 /* Extensions */,
|
||||
3748186426A762300084E870 /* Fixtures */,
|
||||
@@ -1987,6 +2092,7 @@
|
||||
37D4B0E12671614900C925CA /* Tests macOS */,
|
||||
3DA101AC287C30F50027D920 /* Xcode-config */,
|
||||
37D9169A27388A81002B1BAA /* README.md */,
|
||||
3773B7D12ADC05FF00B5FEF3 /* Recovered References */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -2560,6 +2666,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3773B8012ADC076800B5FEF3 /* README in Resources */,
|
||||
37D4B0E82671614900C925CA /* Assets.xcassets in Resources */,
|
||||
375B537428DF6CBB004C1D19 /* Localizable.strings in Resources */,
|
||||
);
|
||||
@@ -2569,6 +2676,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3773B8022ADC076800B5FEF3 /* README in Resources */,
|
||||
37D4B0E92671614900C925CA /* Assets.xcassets in Resources */,
|
||||
375B537528DF6CBB004C1D19 /* Localizable.strings in Resources */,
|
||||
);
|
||||
@@ -2592,6 +2700,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3773B8032ADC076800B5FEF3 /* README in Resources */,
|
||||
37D4B1862671691600C925CA /* Assets.xcassets in Resources */,
|
||||
375B537628DF6CBB004C1D19 /* Localizable.strings in Resources */,
|
||||
37D4B15F267164AF00C925CA /* Assets.xcassets in Resources */,
|
||||
@@ -2755,6 +2864,7 @@
|
||||
37A362BE29537AAA00BDF328 /* PlaybackSettings.swift in Sources */,
|
||||
371B7E612759706A00D21217 /* CommentsView.swift in Sources */,
|
||||
37D9BA0629507F69002586BD /* PlayerControlsSettings.swift in Sources */,
|
||||
3773B80A2ADC076800B5FEF3 /* RefreshControlModifier.swift in Sources */,
|
||||
379DC3D128BA4EB400B09677 /* Seek.swift in Sources */,
|
||||
371B7E6A2759791900D21217 /* CommentsModel.swift in Sources */,
|
||||
37E8B0F027B326F30024006F /* Comparable+Clamped.swift in Sources */,
|
||||
@@ -2778,6 +2888,7 @@
|
||||
37BD07B52698AA4D003EBB87 /* ContentView.swift in Sources */,
|
||||
37D2E0D428B67EFC00F64D52 /* Delay.swift in Sources */,
|
||||
3776925229463C310055EC18 /* PlaylistsCacheModel.swift in Sources */,
|
||||
3759234628C26C7B00C052EC /* Refreshable+Backport.swift in Sources */,
|
||||
374924ED2921669B0017D862 /* PreferenceKeys.swift in Sources */,
|
||||
37130A5B277657090033018A /* Yattee.xcdatamodeld in Sources */,
|
||||
37152EEA26EFEB95004FB96D /* LazyView.swift in Sources */,
|
||||
@@ -2822,6 +2933,7 @@
|
||||
37DD87C7271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */,
|
||||
37F7D82C289EB05F00E2B3D0 /* SettingsPickerModifier.swift in Sources */,
|
||||
375EC95D289EEEE000751258 /* QualityProfile.swift in Sources */,
|
||||
3773B8102ADC076800B5FEF3 /* ScrollViewMatcher.swift in Sources */,
|
||||
371B7E662759786B00D21217 /* Comment+Fixtures.swift in Sources */,
|
||||
37BE0BD326A1D4780092E2DB /* AppleAVPlayerView.swift in Sources */,
|
||||
37A9965E26D6F9B9006E3224 /* HomeView.swift in Sources */,
|
||||
@@ -2830,8 +2942,10 @@
|
||||
378AE943274EF00A006A4EE1 /* Color+Background.swift in Sources */,
|
||||
37F4AE7226828F0900BD60EA /* VerticalCells.swift in Sources */,
|
||||
376578852685429C00D4EA09 /* CaseIterable+Next.swift in Sources */,
|
||||
3722AEBC274DA396005EA4D6 /* Badge+Backport.swift in Sources */,
|
||||
3748186626A7627F0084E870 /* Video+Fixtures.swift in Sources */,
|
||||
37599F34272B44000087F250 /* FavoritesModel.swift in Sources */,
|
||||
3773B8152ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift in Sources */,
|
||||
3717407D2949D40800FDDBC7 /* ChannelLinkView.swift in Sources */,
|
||||
379ACB512A1F8DB000E01914 /* HomeSettingsButton.swift in Sources */,
|
||||
37030FF727B0347C00ECDDAA /* MPVPlayerView.swift in Sources */,
|
||||
@@ -2844,6 +2958,7 @@
|
||||
37FFC440272734C3009FFD26 /* Throttle.swift in Sources */,
|
||||
3709528A29283E14001ECA40 /* NoDocumentsView.swift in Sources */,
|
||||
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||
378AE940274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
|
||||
376BE50927347B5F009AD608 /* SettingsHeader.swift in Sources */,
|
||||
376527BB285F60F700102284 /* PlayerTimeModel.swift in Sources */,
|
||||
37270F1C28E06E3E00856150 /* String+Localizable.swift in Sources */,
|
||||
@@ -2911,6 +3026,7 @@
|
||||
377A20A92693C9A2002842B8 /* TypedContentAccessors.swift in Sources */,
|
||||
37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */,
|
||||
377ABC48286E5887009C986F /* Sequence+Unique.swift in Sources */,
|
||||
3773B8172ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift in Sources */,
|
||||
37520699285E8DD300CA655F /* Chapter.swift in Sources */,
|
||||
37C7B21429ABD9F20013C196 /* ChannelPage.swift in Sources */,
|
||||
37319F0527103F94004ECCD0 /* PlayerQueue.swift in Sources */,
|
||||
@@ -2925,6 +3041,7 @@
|
||||
3784B23B272894DA00B09468 /* ShareSheet.swift in Sources */,
|
||||
379775932689365600DD52A8 /* Array+Next.swift in Sources */,
|
||||
37CFB48528AFE2510070024C /* VideoDescription.swift in Sources */,
|
||||
3773B8042ADC076800B5FEF3 /* UIView+Extensions.swift in Sources */,
|
||||
37B81AFC26D2C9C900675966 /* VideoDetailsPaddingModifier.swift in Sources */,
|
||||
371CC77029468BDC00979C1A /* SettingsButtons.swift in Sources */,
|
||||
37C7A1D5267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */,
|
||||
@@ -2950,6 +3067,7 @@
|
||||
371AC09F294D13AA0085989E /* UnwatchedFeedCountModel.swift in Sources */,
|
||||
370015A928BBAE7F000149FD /* ProgressBar.swift in Sources */,
|
||||
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
||||
377E17142928265900894889 /* ListRowSeparator+Backport.swift in Sources */,
|
||||
373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
||||
37F7AB4D28A9361F00FB46B5 /* UIDevice+Cellular.swift in Sources */,
|
||||
37141673267A8E10006CA35D /* Country.swift in Sources */,
|
||||
@@ -2966,6 +3084,7 @@
|
||||
37EF5C222739D37B00B03725 /* MenuModel.swift in Sources */,
|
||||
37599F30272B42810087F250 /* FavoriteItem.swift in Sources */,
|
||||
374924E729215FB60017D862 /* TapRecognizerViewModifier.swift in Sources */,
|
||||
3773B8072ADC076800B5FEF3 /* UIResponder+Extensions.swift in Sources */,
|
||||
373197D92732015300EF734F /* RelatedView.swift in Sources */,
|
||||
3710A55529488C7D006F8025 /* PlaceholderListItem.swift in Sources */,
|
||||
37F4AD1B28612B23004D0F66 /* OpeningStream.swift in Sources */,
|
||||
@@ -2974,6 +3093,7 @@
|
||||
370E990A2A1EA8C500D144E9 /* WatchModel.swift in Sources */,
|
||||
371AC0B6294D1D6E0085989E /* PlayingIndicatorView.swift in Sources */,
|
||||
37E084AC2753D95F00039B7D /* AccountsNavigationLink.swift in Sources */,
|
||||
3773B7FE2ADC076800B5FEF3 /* RefreshControl.swift in Sources */,
|
||||
378E9C38294552A700B2D696 /* ThumbnailView.swift in Sources */,
|
||||
37732FF42703D32400F04329 /* Sidebar.swift in Sources */,
|
||||
37D4B19726717E1500C925CA /* Video.swift in Sources */,
|
||||
@@ -3015,6 +3135,7 @@
|
||||
3784CDE227772EE40055BBF2 /* Watch.swift in Sources */,
|
||||
37FB285E272225E800A57617 /* ContentItemView.swift in Sources */,
|
||||
3797758B2689345500DD52A8 /* Store.swift in Sources */,
|
||||
3773B80D2ADC076800B5FEF3 /* FramePreferenceKey.swift in Sources */,
|
||||
377F9F7B294403F20043F856 /* VideosCacheModel.swift in Sources */,
|
||||
37B795902771DAE0001CF27B /* OpenURLHandler.swift in Sources */,
|
||||
37732FF02703A26300F04329 /* AccountValidationStatus.swift in Sources */,
|
||||
@@ -3029,6 +3150,7 @@
|
||||
374710062755291C00CE0F87 /* SearchTextField.swift in Sources */,
|
||||
37B7CFEC2A197844001B0564 /* AppleAVPlayerView.swift in Sources */,
|
||||
37F0F4EB286F397E00C06C2E /* SettingsModel.swift in Sources */,
|
||||
378AE93F274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
|
||||
379ACB4D2A1F8A4100E01914 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */,
|
||||
37C194C826F6A9C8005D3B96 /* RecentsModel.swift in Sources */,
|
||||
37737786276F9858000521C1 /* Windows.swift in Sources */,
|
||||
@@ -3079,6 +3201,7 @@
|
||||
37192D5828B179D60012EEDD /* ChaptersView.swift in Sources */,
|
||||
3784CDE327772EE40055BBF2 /* Watch.swift in Sources */,
|
||||
371AC0B7294D1D6E0085989E /* PlayingIndicatorView.swift in Sources */,
|
||||
3773B8182ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift in Sources */,
|
||||
37E80F3D287B107F00561799 /* VideoDetailsOverlay.swift in Sources */,
|
||||
375DFB5926F9DA010013F468 /* InstancesModel.swift in Sources */,
|
||||
3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||
@@ -3109,6 +3232,8 @@
|
||||
37EAD870267B9ED100D9E01B /* Segment.swift in Sources */,
|
||||
3788AC2826F6840700F6BAA9 /* FavoriteItemView.swift in Sources */,
|
||||
377FF88C291A60310028EB0B /* OpenVideosModel.swift in Sources */,
|
||||
378AE93A274EDFAF006A4EE1 /* Badge+Backport.swift in Sources */,
|
||||
3773B8162ADC081300B5FEF3 /* VisualEffectBlur-iOS.swift in Sources */,
|
||||
37599F35272B44000087F250 /* FavoritesModel.swift in Sources */,
|
||||
376527BC285F60F700102284 /* PlayerTimeModel.swift in Sources */,
|
||||
37F64FE526FE70A60081B69E /* RedrawOnModifier.swift in Sources */,
|
||||
@@ -3170,6 +3295,7 @@
|
||||
3748186F26A769D60084E870 /* DetailBadge.swift in Sources */,
|
||||
3744A96128B99ADD005DE0A7 /* PlayerControlsLayout.swift in Sources */,
|
||||
372915E72687E3B900F5A35B /* Defaults.swift in Sources */,
|
||||
377E17152928265900894889 /* ListRowSeparator+Backport.swift in Sources */,
|
||||
371CC76929466ED000979C1A /* AccountsView.swift in Sources */,
|
||||
37C3A242272359900087A57A /* Double+Format.swift in Sources */,
|
||||
37B795912771DAE0001CF27B /* OpenURLHandler.swift in Sources */,
|
||||
@@ -3279,6 +3405,7 @@
|
||||
377ABC41286E4AD5009C986F /* InstancesManifest.swift in Sources */,
|
||||
373CFAF02697A78B003CB2C6 /* AddToPlaylistView.swift in Sources */,
|
||||
3763495226DFF59D00B9A393 /* AppSidebarRecents.swift in Sources */,
|
||||
3773B80E2ADC076800B5FEF3 /* FramePreferenceKey.swift in Sources */,
|
||||
370015AA28BBAE7F000149FD /* ProgressBar.swift in Sources */,
|
||||
371B7E672759786B00D21217 /* Comment+Fixtures.swift in Sources */,
|
||||
3769C02F2779F18600DDB3EA /* PlaceholderProgressView.swift in Sources */,
|
||||
@@ -3410,6 +3537,7 @@
|
||||
376BE50D27349108009AD608 /* BrowsingSettings.swift in Sources */,
|
||||
37CFB48728AFE2510070024C /* VideoDescription.swift in Sources */,
|
||||
37DD87C9271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */,
|
||||
378AE93E274EDFB4006A4EE1 /* Tint+Backport.swift in Sources */,
|
||||
37FFC442272734C3009FFD26 /* Throttle.swift in Sources */,
|
||||
377FF88D291A60310028EB0B /* OpenVideosModel.swift in Sources */,
|
||||
37F4AD2828613B81004D0F66 /* Color+Debug.swift in Sources */,
|
||||
@@ -3438,6 +3566,7 @@
|
||||
37A362C429537FED00BDF328 /* PlaybackSettingsPresentationDetents+Backport.swift in Sources */,
|
||||
37BDFF1929487B99000C6404 /* PlaylistVideosView.swift in Sources */,
|
||||
37B7CFEF2A197A08001B0564 /* SafeAreaModel.swift in Sources */,
|
||||
3773B8092ADC076800B5FEF3 /* UIResponder+Extensions.swift in Sources */,
|
||||
37C0698427260B2100F7F6CB /* ThumbnailsModel.swift in Sources */,
|
||||
374924DC2921050B0017D862 /* LocationsSettings.swift in Sources */,
|
||||
37D6025B28C17375009E8D98 /* PlaybackStatsView.swift in Sources */,
|
||||
@@ -3452,6 +3581,7 @@
|
||||
37B044B926F7AB9000E1419D /* SettingsView.swift in Sources */,
|
||||
3743B86A27216D3600261544 /* ChannelCell.swift in Sources */,
|
||||
3751BA8527E6914F007B1A60 /* ReturnYouTubeDislikeAPI.swift in Sources */,
|
||||
3773B8062ADC076800B5FEF3 /* UIView+Extensions.swift in Sources */,
|
||||
37769250294630110055EC18 /* ChannelAvatarView.swift in Sources */,
|
||||
37030FFD27B0398000ECDDAA /* MPVClient.swift in Sources */,
|
||||
378E9C4229455A5800B2D696 /* ChannelsView.swift in Sources */,
|
||||
@@ -3530,6 +3660,7 @@
|
||||
37C069802725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
||||
37EBD8CC27AF26C200F1C24B /* MPVBackend.swift in Sources */,
|
||||
3711404126B206A6005B3555 /* SearchModel.swift in Sources */,
|
||||
3773B80F2ADC076800B5FEF3 /* FramePreferenceKey.swift in Sources */,
|
||||
37FD77022932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */,
|
||||
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */,
|
||||
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */,
|
||||
@@ -3550,6 +3681,7 @@
|
||||
37D9BA0829507F69002586BD /* PlayerControlsSettings.swift in Sources */,
|
||||
37599F32272B42810087F250 /* FavoriteItem.swift in Sources */,
|
||||
37E8B0EE27B326C00024006F /* TimelineView.swift in Sources */,
|
||||
3726386E2948A4B80043702D /* Badge+Backport.swift in Sources */,
|
||||
37141675267A8E10006CA35D /* Country.swift in Sources */,
|
||||
370F500C27CC1821001B35DC /* MPVViewController.swift in Sources */,
|
||||
3782B9542755667600990149 /* String+Format.swift in Sources */,
|
||||
@@ -3587,10 +3719,12 @@
|
||||
3761ABFF26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */,
|
||||
37C3A24F272360470087A57A /* ChannelPlaylist+Fixtures.swift in Sources */,
|
||||
3718B9A02921A9620003DB2E /* VideoDetailsOverlay.swift in Sources */,
|
||||
377E17162928265900894889 /* ListRowSeparator+Backport.swift in Sources */,
|
||||
37FB28432721B22200A57617 /* ContentItem.swift in Sources */,
|
||||
37D2E0D228B67DBC00F64D52 /* AnimationCompletionObserverModifier.swift in Sources */,
|
||||
37AAF2A226741C97007FC770 /* FeedView.swift in Sources */,
|
||||
37484C1B26FC837400287258 /* PlayerSettings.swift in Sources */,
|
||||
3773B8122ADC076800B5FEF3 /* ScrollViewMatcher.swift in Sources */,
|
||||
372915E82687E3B900F5A35B /* Defaults.swift in Sources */,
|
||||
37BAB54C269B39FD00E75ED1 /* TVNavigationView.swift in Sources */,
|
||||
3718B9A62921A9BE0003DB2E /* PreferenceKeys.swift in Sources */,
|
||||
@@ -3667,7 +3801,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Open in Yattee/Open in Yattee.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Open in Yattee/Info.plist";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Open in Yattee";
|
||||
@@ -3698,7 +3832,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Open in Yattee/Info.plist";
|
||||
@@ -3729,7 +3863,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
@@ -3749,7 +3883,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
@@ -3913,7 +4047,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "iOS/Yattee (iOS).entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -3931,7 +4065,7 @@
|
||||
INFOPLIST_KEY_UIRequiresFullScreen = YES;
|
||||
INFOPLIST_KEY_UIStatusBarHidden = NO;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -3966,7 +4100,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION=1";
|
||||
@@ -3981,7 +4115,7 @@
|
||||
INFOPLIST_KEY_UIRequiresFullScreen = YES;
|
||||
INFOPLIST_KEY_UIStatusBarHidden = NO;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -4018,7 +4152,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@@ -4033,7 +4167,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.5;
|
||||
OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app;
|
||||
@@ -4057,7 +4191,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = 78Z5H3M6RJ;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
@@ -4073,7 +4207,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.5;
|
||||
OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app;
|
||||
@@ -4092,7 +4226,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4116,7 +4250,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4142,7 +4276,7 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4167,7 +4301,7 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4193,7 +4327,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -4233,7 +4367,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
"DEVELOPMENT_TEAM[sdk=appletvos*]" = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -4274,7 +4408,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -4298,7 +4432,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 165;
|
||||
CURRENT_PROJECT_VERSION = 166;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
||||
@@ -38,7 +38,7 @@ struct InstancesSettings: View {
|
||||
if !selectedInstance.isNil, selectedInstance.app.supportsAccounts {
|
||||
SettingsHeader(text: "Accounts".localized())
|
||||
|
||||
List(selection: $selectedAccount) {
|
||||
let list = List(selection: $selectedAccount) {
|
||||
if selectedInstanceAccounts.isEmpty {
|
||||
Text("You have no accounts for this location")
|
||||
.foregroundColor(.secondary)
|
||||
@@ -69,7 +69,13 @@ struct InstancesSettings: View {
|
||||
.tag(account)
|
||||
}
|
||||
}
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
|
||||
if #available(macOS 12.0, *) {
|
||||
list
|
||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||
} else {
|
||||
list
|
||||
}
|
||||
}
|
||||
|
||||
if selectedInstance != nil, selectedInstance.app.hasFrontendURL {
|
||||
|
||||
@@ -4,6 +4,7 @@ final class MPVOGLView: NSView {
|
||||
override init(frame frameRect: CGRect) {
|
||||
super.init(frame: frameRect)
|
||||
autoresizingMask = [.width, .height]
|
||||
wantsBestResolutionOpenGLSurface = true
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
|
||||
Reference in New Issue
Block a user