mirror of
https://github.com/yattee/yattee.git
synced 2025-12-12 19:18:16 +00:00
Compare commits
6 Commits
revert-652
...
1.5.2-182
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fe8a32fb8 | ||
|
|
5a0c1bbae3 | ||
|
|
4ce9dc6729 | ||
|
|
b783db30b6 | ||
|
|
7741e531f4 | ||
|
|
4b21cd48e3 |
29
CHANGELOG.md
29
CHANGELOG.md
@@ -1,10 +1,25 @@
|
||||
## Build 181
|
||||
* History Setting: hide the recent activity in the sidebar or limit the number of items shown (by @rickykresslein)
|
||||
* Fix issues with empty comments (by @stonerl)
|
||||
* Improved Invidious comments (by @stonerl)
|
||||
* Downgrade MPVKit to 0.36.0-1 due to issues with WebVTT subtitles
|
||||
* Don't show related in sidebar when disabled in settings by @stonerl in https://github.com/yattee/yattee/pull/635
|
||||
* Handle audio session interrupts by other media by @stonerl in https://github.com/yattee/yattee/pull/640
|
||||
* Only show Queue header in sidebar view by @stonerl in https://github.com/yattee/yattee/pull/642
|
||||
* SponsorBlock Improvements by @stonerl in https://github.com/yattee/yattee/pull/639
|
||||
* Chapter title on jump by @stonerl in https://github.com/yattee/yattee/pull/655
|
||||
* Restart finished video by @stonerl in https://github.com/yattee/yattee/pull/646
|
||||
* SponsorBlock jump to end instead of pausing by @stonerl in https://github.com/yattee/yattee/pull/648
|
||||
* Call correct class of SDImageAWebPCoder by @stonerl in https://github.com/yattee/yattee/pull/664
|
||||
* Fix handling and displaying captions by @stonerl in https://github.com/yattee/yattee/pull/636
|
||||
* Advanced settings: make number fields .numPad by @stonerl in https://github.com/yattee/yattee/pull/661
|
||||
* Preserve time on stream change by @stonerl in https://github.com/yattee/yattee/pull/651
|
||||
* Switch to previous backend when leaving PiP by @stonerl in https://github.com/yattee/yattee/pull/641
|
||||
* Handle deep links by @timonus in https://github.com/yattee/yattee/pull/645
|
||||
* Music Mode: don't bindPlayerToLayer when entering foreground by @stonerl in https://github.com/yattee/yattee/pull/644
|
||||
* Allow user to disable thumbnails and jump to current chapter in horizontal view by @stonerl in https://github.com/yattee/yattee/pull/665
|
||||
* Rework qualitiy settings by @stonerl in https://github.com/yattee/yattee/pull/650
|
||||
* HLS: set target bitrate / AVPlayer: higher resolution by @stonerl in https://github.com/yattee/yattee/pull/667
|
||||
* Fix #619: Remove ports from shared YouTube links by @0x000C in https://github.com/yattee/yattee/pull/627
|
||||
* XCode enable IDEPreferLogStreaming by @stonerl in https://github.com/yattee/yattee/pull/638
|
||||
* Updated localizations
|
||||
* Updated dependencies
|
||||
* Upgraded dependencies
|
||||
|
||||
## Previous builds
|
||||
* Add skip, play/pause, and fullscreen shortcuts to macOS player (by @rickykresslein)
|
||||
@@ -16,6 +31,10 @@
|
||||
* Added Controls setting "Action button labels" icon or icon and text
|
||||
* Added Advanced setting for MPV: "deinterlace"
|
||||
* Add help text to all header buttons (by @rickykresslein)
|
||||
* History Setting: hide the recent activity in the sidebar or limit the number of items shown (by @rickykresslein)
|
||||
* Fix issues with empty comments (by @stonerl)
|
||||
* Improved Invidious comments (by @stonerl)
|
||||
* Downgrade MPVKit to 0.36.0-1 due to issues with WebVTT subtitles
|
||||
* Add Chinese (Traditional) localization (by @rexcsk)
|
||||
* Localization fixes
|
||||
* Updated localizations
|
||||
|
||||
@@ -17,13 +17,13 @@ extension String {
|
||||
|
||||
var outputText = self
|
||||
|
||||
results.reversed().forEach { match in
|
||||
(1 ..< match.numberOfRanges).reversed().forEach { rangeIndex in
|
||||
for match in results.reversed() {
|
||||
for rangeIndex in (1 ..< match.numberOfRanges).reversed() {
|
||||
let matchingGroup: String = (self as NSString).substring(with: match.range(at: rangeIndex))
|
||||
let rangeBounds = match.range(at: rangeIndex)
|
||||
|
||||
guard let range = Range(rangeBounds, in: self) else {
|
||||
return
|
||||
continue
|
||||
}
|
||||
let replacement = replacementStringClosure(matchingGroup) ?? matchingGroup
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ extension URL {
|
||||
func byReplacingYatteeProtocol(with urlProtocol: String = "https") -> URL! {
|
||||
var urlAbsoluteString = absoluteString
|
||||
|
||||
guard urlAbsoluteString.hasPrefix(Constants.yatteeProtocol) else {
|
||||
guard urlAbsoluteString.hasPrefix(Strings.yatteeProtocol) else {
|
||||
return self
|
||||
}
|
||||
|
||||
urlAbsoluteString = String(urlAbsoluteString.dropFirst(Constants.yatteeProtocol.count))
|
||||
urlAbsoluteString = String(urlAbsoluteString.dropFirst(Strings.yatteeProtocol.count))
|
||||
if absoluteString.contains("://") {
|
||||
return URL(string: urlAbsoluteString)
|
||||
}
|
||||
|
||||
24
Gemfile.lock
24
Gemfile.lock
@@ -57,17 +57,17 @@ GEM
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.906.0)
|
||||
aws-sdk-core (3.191.6)
|
||||
aws-partitions (1.929.0)
|
||||
aws-sdk-core (3.196.1)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.8)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.78.0)
|
||||
aws-sdk-core (~> 3, >= 3.191.0)
|
||||
aws-sdk-kms (1.81.0)
|
||||
aws-sdk-core (~> 3, >= 3.193.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.146.1)
|
||||
aws-sdk-core (~> 3, >= 3.191.0)
|
||||
aws-sdk-s3 (1.151.0)
|
||||
aws-sdk-core (~> 3, >= 3.194.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.8)
|
||||
aws-sigv4 (1.8.0)
|
||||
@@ -157,27 +157,28 @@ GEM
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
jmespath (1.6.2)
|
||||
json (2.7.1)
|
||||
json (2.7.2)
|
||||
jwt (2.8.1)
|
||||
base64
|
||||
mini_magick (4.12.0)
|
||||
mini_mime (1.1.5)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.0)
|
||||
multipart-post (2.4.1)
|
||||
nanaimo (0.3.0)
|
||||
naturally (2.2.1)
|
||||
nkf (0.2.0)
|
||||
optparse (0.4.0)
|
||||
optparse (0.5.0)
|
||||
os (1.1.4)
|
||||
plist (3.7.1)
|
||||
public_suffix (5.0.5)
|
||||
rake (13.2.0)
|
||||
rake (13.2.1)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.2.6)
|
||||
rexml (3.2.8)
|
||||
strscan (>= 3.0.9)
|
||||
rouge (2.0.7)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
@@ -190,6 +191,7 @@ GEM
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
strscan (3.1.0)
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
|
||||
@@ -66,7 +66,7 @@ protocol VideosAPI {
|
||||
failureHandler: ((RequestError) -> Void)?,
|
||||
completionHandler: @escaping (PlayerQueueItem) -> Void
|
||||
)
|
||||
func shareURL(_ item: ContentItem, frontendURL: String?, time: CMTime?) -> URL?
|
||||
func shareURL(_ item: ContentItem, frontendURLString: String?, time: CMTime?) -> URL?
|
||||
|
||||
func comments(_ id: Video.ID, page: String?) -> Resource?
|
||||
}
|
||||
@@ -111,12 +111,13 @@ extension VideosAPI {
|
||||
func shareURL(_ item: ContentItem, frontendURLString: String? = nil, time: CMTime? = nil) -> URL? {
|
||||
var urlComponents: URLComponents?
|
||||
if let frontendURLString,
|
||||
let frontendURL = URL(string: frontendURLString) {
|
||||
urlComponents = URLComponents(URL: frontendURL, resolvingAgainstBaseURL: false)
|
||||
let frontendURL = URL(string: frontendURLString)
|
||||
{
|
||||
urlComponents = URLComponents(url: frontendURL, resolvingAgainstBaseURL: false)
|
||||
} else if let instanceComponents = account?.instance?.urlComponents {
|
||||
urlComponents = instanceComponents
|
||||
}
|
||||
|
||||
|
||||
guard var urlComponents else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ struct BrowsingSettingsGroupImporter {
|
||||
}
|
||||
|
||||
if let favorites = json["favorites"].array {
|
||||
favorites.forEach { favoriteJSON in
|
||||
for favoriteJSON in favorites {
|
||||
if let jsonString = favoriteJSON.rawString(options: []),
|
||||
let item = FavoriteItem.bridge.deserialize(jsonString)
|
||||
{
|
||||
@@ -32,7 +32,7 @@ struct BrowsingSettingsGroupImporter {
|
||||
}
|
||||
|
||||
if let widgetsFavorites = json["widgetsSettings"].array {
|
||||
widgetsFavorites.forEach { widgetJSON in
|
||||
for widgetJSON in widgetsFavorites {
|
||||
let dict = widgetJSON.dictionaryValue.mapValues { json in json.stringValue }
|
||||
if let item = WidgetSettingsBridge().deserialize(dict) {
|
||||
FavoritesModel.shared.updateWidgetSettings(item)
|
||||
|
||||
@@ -56,7 +56,7 @@ struct LocationsSettingsGroupImporter {
|
||||
}
|
||||
|
||||
if let accounts = json["accounts"].array {
|
||||
accounts.forEach { accountJSON in
|
||||
for accountJSON in accounts {
|
||||
let dict = accountJSON.dictionaryValue.mapValues { json in json.stringValue }
|
||||
if let account = AccountsBridge().deserialize(dict),
|
||||
includedAccountsIDs.contains(account.id)
|
||||
|
||||
@@ -26,7 +26,7 @@ struct QualitySettingsGroupImporter {
|
||||
}
|
||||
|
||||
if let qualityProfiles = json["qualityProfiles"].array {
|
||||
qualityProfiles.forEach { qualityProfileJSON in
|
||||
for qualityProfileJSON in qualityProfiles {
|
||||
let dict = qualityProfileJSON.dictionaryValue.mapValues { json in json.stringValue }
|
||||
if let item = QualityProfileBridge().deserialize(dict) {
|
||||
QualityProfilesModel.shared.update(item, item)
|
||||
|
||||
@@ -6,7 +6,7 @@ struct RecentlyOpenedImporter {
|
||||
|
||||
func performImport() {
|
||||
if let recentlyOpened = json["recentlyOpened"].array {
|
||||
recentlyOpened.forEach { recentlyOpenedJSON in
|
||||
for recentlyOpenedJSON in recentlyOpened {
|
||||
let dict = recentlyOpenedJSON.dictionaryValue.mapValues { json in json.stringValue }
|
||||
if let item = RecentItemBridge().deserialize(dict) {
|
||||
RecentsModel.shared.add(item)
|
||||
|
||||
@@ -147,7 +147,7 @@ struct OpenVideosModel {
|
||||
if prepending {
|
||||
videos.reverse()
|
||||
}
|
||||
videos.forEach { video in
|
||||
for video in videos {
|
||||
player.enqueueVideo(video, play: false, prepending: prepending, loadDetails: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,30 +625,32 @@ final class MPVBackend: PlayerBackend {
|
||||
}
|
||||
}
|
||||
|
||||
@objc func handleAudioSessionInterruption(_ notification: Notification) {
|
||||
logger.info("Audio session interruption received.")
|
||||
#if !os(macOS)
|
||||
@objc func handleAudioSessionInterruption(_ notification: Notification) {
|
||||
logger.info("Audio session interruption received.")
|
||||
|
||||
guard let info = notification.userInfo,
|
||||
let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt
|
||||
else {
|
||||
logger.info("AVAudioSessionInterruptionTypeKey is missing or not a UInt in userInfo.")
|
||||
return
|
||||
guard let info = notification.userInfo,
|
||||
let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt
|
||||
else {
|
||||
logger.info("AVAudioSessionInterruptionTypeKey is missing or not a UInt in userInfo.")
|
||||
return
|
||||
}
|
||||
|
||||
let type = AVAudioSession.InterruptionType(rawValue: typeValue)
|
||||
|
||||
logger.info("Interruption type received: \(String(describing: type))")
|
||||
|
||||
switch type {
|
||||
case .began:
|
||||
pause()
|
||||
logger.info("Audio session interrupted.")
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let type = AVAudioSession.InterruptionType(rawValue: typeValue)
|
||||
|
||||
logger.info("Interruption type received: \(String(describing: type))")
|
||||
|
||||
switch type {
|
||||
case .began:
|
||||
pause()
|
||||
logger.info("Audio session interrupted.")
|
||||
default:
|
||||
break
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self, name: AVAudioSession.interruptionNotification, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self, name: AVAudioSession.interruptionNotification, object: nil)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -60,21 +60,21 @@ class Stream: Equatable, Hashable, Identifiable {
|
||||
var bitrate: Int {
|
||||
switch self {
|
||||
case .hd2160p60, .hd2160p50, .hd2160p48, .hd2160p30:
|
||||
return 56000000 // 56 Mbit/s
|
||||
return 56_000_000 // 56 Mbit/s
|
||||
case .hd1440p60, .hd1440p50, .hd1440p48, .hd1440p30:
|
||||
return 24000000 // 24 Mbit/s
|
||||
return 24_000_000 // 24 Mbit/s
|
||||
case .hd1080p60, .hd1080p50, .hd1080p48, .hd1080p30:
|
||||
return 12000000 // 12 Mbit/s
|
||||
return 12_000_000 // 12 Mbit/s
|
||||
case .hd720p60, .hd720p50, .hd720p48, .hd720p30:
|
||||
return 9500000 // 9.5 Mbit/s
|
||||
return 9_500_000 // 9.5 Mbit/s
|
||||
case .sd480p30:
|
||||
return 4000000 // 4 Mbit/s
|
||||
return 4_000_000 // 4 Mbit/s
|
||||
case .sd360p30:
|
||||
return 1500000 // 1.5 Mbit/s
|
||||
return 1_500_000 // 1.5 Mbit/s
|
||||
case .sd240p30:
|
||||
return 1000000 // 1 Mbit/s
|
||||
return 1_000_000 // 1 Mbit/s
|
||||
case .sd144p30:
|
||||
return 600000 // 0.6 Mbit/s
|
||||
return 600_000 // 0.6 Mbit/s
|
||||
case .unknown:
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ struct URLBookmarkModel {
|
||||
func refreshAll() {
|
||||
logger.info("refreshing all bookmarks")
|
||||
|
||||
allURLs.forEach { url in
|
||||
for url in allURLs {
|
||||
if loadBookmark(url) != nil {
|
||||
logger.info("bookmark for \(url) exists")
|
||||
} else {
|
||||
|
||||
@@ -57,7 +57,7 @@ final class URLParserTests: XCTestCase {
|
||||
]
|
||||
|
||||
func testUrlsParsing() throws {
|
||||
Self.urls.forEach { urlString in
|
||||
for urlString in Self.urls {
|
||||
let url = URL(string: urlString)!
|
||||
let parser = URLParser(url: url)
|
||||
XCTAssertEqual(parser.destination, .fileURL)
|
||||
@@ -66,7 +66,7 @@ final class URLParserTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testVideosParsing() throws {
|
||||
Self.videos.forEach { url, id in
|
||||
for (url, id) in Self.videos {
|
||||
let parser = URLParser(url: URL(string: url)!)
|
||||
XCTAssertEqual(parser.destination, .video)
|
||||
XCTAssertEqual(parser.videoID, id)
|
||||
@@ -74,7 +74,7 @@ final class URLParserTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testChannelsByNameParsing() throws {
|
||||
Self.channelsByName.forEach { url, name in
|
||||
for (url, name) in Self.channelsByName {
|
||||
let parser = URLParser(url: URL(string: url)!)
|
||||
XCTAssertEqual(parser.destination, .channel)
|
||||
XCTAssertEqual(parser.channelName, name)
|
||||
@@ -83,7 +83,7 @@ final class URLParserTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testChannelsByIdParsing() throws {
|
||||
Self.channelsByID.forEach { url, id in
|
||||
for (url, id) in Self.channelsByID {
|
||||
let parser = URLParser(url: URL(string: url)!)
|
||||
XCTAssertEqual(parser.destination, .channel)
|
||||
XCTAssertEqual(parser.channelID, id)
|
||||
@@ -92,7 +92,7 @@ final class URLParserTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testUsersParsing() throws {
|
||||
Self.users.forEach { url, user in
|
||||
for (url, user) in Self.users {
|
||||
let parser = URLParser(url: URL(string: url)!)
|
||||
XCTAssertEqual(parser.destination, .channel)
|
||||
XCTAssertNil(parser.channelID)
|
||||
@@ -102,7 +102,7 @@ final class URLParserTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testPlaylistsParsing() throws {
|
||||
Self.playlists.forEach { url, id in
|
||||
for (url, id) in Self.playlists {
|
||||
let parser = URLParser(url: URL(string: url)!)
|
||||
XCTAssertEqual(parser.destination, .playlist)
|
||||
XCTAssertEqual(parser.playlistID, id)
|
||||
@@ -110,7 +110,7 @@ final class URLParserTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testSearchesParsing() throws {
|
||||
Self.searches.forEach { url, query in
|
||||
for (url, query) in Self.searches {
|
||||
let parser = URLParser(url: URL(string: url)!)
|
||||
XCTAssertEqual(parser.destination, .search)
|
||||
XCTAssertEqual(parser.searchQuery, query)
|
||||
@@ -127,7 +127,7 @@ final class URLParserTests: XCTestCase {
|
||||
"watch?v=IUTGFQpKaPU&t=30s": 30
|
||||
]
|
||||
|
||||
samples.forEach { url, time in
|
||||
for (url, time) in samples {
|
||||
XCTAssertEqual(
|
||||
URLParser(url: URL(string: url)!).time,
|
||||
time
|
||||
|
||||
@@ -53,7 +53,6 @@ struct ChannelPlaylistCell: View {
|
||||
|
||||
Text("\(playlist.videosCount ?? playlist.videos.count) videos")
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
.frame(height: 20)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
enum Constants {
|
||||
static let yatteeProtocol = "yattee://"
|
||||
static let overlayAnimation = Animation.linear(duration: 0.2)
|
||||
|
||||
static var isAppleTV: Bool {
|
||||
@@ -98,6 +97,20 @@ enum Constants {
|
||||
#endif
|
||||
}
|
||||
|
||||
static var defaultNavigationStyle: NavigationStyle {
|
||||
#if os(macOS)
|
||||
return .sidebar
|
||||
#elseif os(iOS)
|
||||
if isIPad {
|
||||
return .sidebar
|
||||
} else {
|
||||
return .tab
|
||||
}
|
||||
#else
|
||||
return .tab
|
||||
#endif
|
||||
}
|
||||
|
||||
static func seekIcon(_ type: String, _ interval: TimeInterval) -> String {
|
||||
let interval = Int(interval)
|
||||
let allVersions = [10, 15, 30, 45, 60, 75, 90]
|
||||
|
||||
@@ -81,7 +81,6 @@ struct FavoriteItemView: View {
|
||||
}
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
|
||||
.onAppear {
|
||||
if item.section == .history {
|
||||
reloadVisibleWatches()
|
||||
@@ -165,7 +164,7 @@ struct FavoriteItemView: View {
|
||||
.prefix(favoritesModel.limit(item))
|
||||
)
|
||||
let last = watches.last
|
||||
watches.forEach { watch in
|
||||
for watch in watches {
|
||||
player.loadHistoryVideoDetails(watch) {
|
||||
guard let video = player.historyVideo(watch.videoID), itemVisible(.init(video: video)) else { return }
|
||||
visibleWatches.append(watch)
|
||||
|
||||
@@ -4,8 +4,6 @@ import Siesta
|
||||
|
||||
struct OpenURLHandler {
|
||||
static var firstHandle = true
|
||||
static let yatteeProtocol = "yattee://"
|
||||
|
||||
var accounts: AccountsModel { .shared }
|
||||
var navigation: NavigationModel { .shared }
|
||||
var recents: RecentsModel { .shared }
|
||||
|
||||
@@ -142,7 +142,6 @@ struct PlaybackSettings: View {
|
||||
}
|
||||
.animation(nil, value: player.activeBackend)
|
||||
.frame(alignment: .topLeading)
|
||||
|
||||
.ignoresSafeArea(.all, edges: .bottom)
|
||||
.backport
|
||||
.playbackSettingsPresentationDetents()
|
||||
@@ -235,7 +234,6 @@ struct PlaybackSettings: View {
|
||||
#if os(iOS)
|
||||
.padding(12)
|
||||
.frame(width: 40, height: 40)
|
||||
|
||||
.background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.accentColor, lineWidth: 1))
|
||||
.contentShape(Rectangle())
|
||||
#endif
|
||||
@@ -261,7 +259,6 @@ struct PlaybackSettings: View {
|
||||
#if os(iOS)
|
||||
.padding(12)
|
||||
.frame(width: 40, height: 40)
|
||||
|
||||
.background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.accentColor, lineWidth: 1))
|
||||
.contentShape(Rectangle())
|
||||
#endif
|
||||
|
||||
@@ -57,7 +57,6 @@ import SwiftUI
|
||||
}
|
||||
.indicator(.activity)
|
||||
.frame(width: Self.thumbnailWidth, height: Self.thumbnailHeight)
|
||||
|
||||
.mask(RoundedRectangle(cornerRadius: 6))
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ struct ChaptersView: View {
|
||||
}
|
||||
|
||||
#if !os(tvOS)
|
||||
private func chapterViews(for chaptersToShow: ArraySlice<Chapter>, opacity: Double = 1.0, clickable: Bool = true, scrollViewProxy: ScrollViewProxy? = nil) -> some View {
|
||||
private func chapterViews(for chaptersToShow: ArraySlice<Chapter>, opacity: Double = 1.0, clickable: Bool = true, scrollViewProxy _: ScrollViewProxy? = nil) -> some View {
|
||||
ForEach(Array(chaptersToShow.indices), id: \.self) { index in
|
||||
let chapter = chaptersToShow[index]
|
||||
ChapterView(chapter: chapter, chapterIndex: index, showThumbnail: showThumbnails)
|
||||
|
||||
@@ -88,7 +88,7 @@ struct VideoDescription: View {
|
||||
var formattedString: AttributedString {
|
||||
var attrString = AttributedString(description)
|
||||
let words = description.unicodeScalars.split(whereSeparator: separators.contains).map(String.init)
|
||||
words.forEach { word in
|
||||
for word in words {
|
||||
if word.hasPrefix("https://") || word.hasPrefix("http://"), let url = URL(string: String(word)) {
|
||||
if let range = attrString.range(of: word) {
|
||||
attrString[range].link = url
|
||||
|
||||
@@ -263,7 +263,6 @@ struct VideoPlayerView: View {
|
||||
#else
|
||||
GeometryReader { geometry in
|
||||
player.playerBackendView
|
||||
|
||||
.modifier(
|
||||
VideoPlayerSizeModifier(
|
||||
geometry: geometry,
|
||||
|
||||
@@ -198,7 +198,7 @@ struct PlaylistFormView: View {
|
||||
}
|
||||
}
|
||||
#else
|
||||
Button(self.visibility.name) {
|
||||
Button(visibility.name) {
|
||||
self.visibility = self.visibility.next()
|
||||
}
|
||||
.contextMenu {
|
||||
|
||||
@@ -61,23 +61,23 @@ struct HistorySettings: View {
|
||||
Toggle("Save history of played videos", isOn: $saveHistory)
|
||||
Toggle("Show recents in sidebar", isOn: $showRecents)
|
||||
#if os(macOS)
|
||||
HStack {
|
||||
Toggle("Limit recents shown", isOn: $limitRecents)
|
||||
.frame(minWidth: 140, alignment: .leading)
|
||||
.disabled(!showRecents)
|
||||
Spacer()
|
||||
counterButtons(for: $limitRecentsAmount)
|
||||
.disabled(!limitRecents)
|
||||
}
|
||||
HStack {
|
||||
Toggle("Limit recents shown", isOn: $limitRecents)
|
||||
.frame(minWidth: 140, alignment: .leading)
|
||||
.disabled(!showRecents)
|
||||
Spacer()
|
||||
counterButtons(for: $limitRecentsAmount)
|
||||
.disabled(!limitRecents)
|
||||
}
|
||||
#else
|
||||
Toggle("Limit recents shown", isOn: $limitRecents)
|
||||
.disabled(!showRecents)
|
||||
HStack {
|
||||
Text("Recents shown")
|
||||
Spacer()
|
||||
counterButtons(for: $limitRecentsAmount)
|
||||
.disabled(!limitRecents)
|
||||
}
|
||||
Toggle("Limit recents shown", isOn: $limitRecents)
|
||||
.disabled(!showRecents)
|
||||
HStack {
|
||||
Text("Recents shown")
|
||||
Spacer()
|
||||
counterButtons(for: $limitRecentsAmount)
|
||||
.disabled(!limitRecents)
|
||||
}
|
||||
#endif
|
||||
Toggle("Show progress of watching on thumbnails", isOn: $showWatchingProgress)
|
||||
.disabled(!saveHistory)
|
||||
@@ -196,7 +196,7 @@ struct HistorySettings: View {
|
||||
private func counterButtons(for _value: Binding<Int>) -> some View {
|
||||
var value: Binding<Int> {
|
||||
Binding(
|
||||
get: { return _value.wrappedValue },
|
||||
get: { _value.wrappedValue },
|
||||
set: {
|
||||
if $0 < 1 {
|
||||
_value.wrappedValue = 1
|
||||
|
||||
@@ -68,7 +68,7 @@ struct HomeSettings: View {
|
||||
}
|
||||
.help("Add to Favorites")
|
||||
#if !os(tvOS)
|
||||
.buttonStyle(.borderless)
|
||||
.buttonStyle(.borderless)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +261,6 @@ struct PlayerControlsSettings: View {
|
||||
TextField("Duration", text: value)
|
||||
.frame(width: textFieldWidth, alignment: .trailing)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
.labelsHidden()
|
||||
#if !os(macOS)
|
||||
.keyboardType(.numberPad)
|
||||
|
||||
@@ -48,7 +48,6 @@ struct QualityProfileForm: View {
|
||||
|
||||
.onAppear(perform: initializeForm)
|
||||
.onChange(of: backend, perform: { _ in backendChanged(self.backend); updateActiveFormats(); validate() })
|
||||
|
||||
.onChange(of: name, perform: { _ in validate() })
|
||||
.onChange(of: resolution, perform: { _ in validate() })
|
||||
.onChange(of: orderedFormats, perform: { _ in validate() })
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Defaults
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
static let matrixURL = URL(string: "https://tinyurl.com/matrix-yattee")!
|
||||
static let discordURL = URL(string: "https://yattee.stream/discord")!
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import Defaults
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
#endif
|
||||
|
||||
struct SponsorBlockSettings: View {
|
||||
@ObservedObject private var settings = SettingsModel.shared
|
||||
@@ -55,24 +57,27 @@ struct SponsorBlockSettings: View {
|
||||
Section(header: SettingsHeader(text: "Categories to Skip".localized())) {
|
||||
categoryRows
|
||||
}
|
||||
colorSection
|
||||
|
||||
Button {
|
||||
settings.presentAlert(
|
||||
Alert(
|
||||
title: Text("Restore Default Colors?"),
|
||||
message: Text("This action will reset all custom colors back to their original defaults. " +
|
||||
"Any custom color changes you've made will be lost."),
|
||||
primaryButton: .destructive(Text("Restore")) {
|
||||
resetColors()
|
||||
},
|
||||
secondaryButton: .cancel()
|
||||
#if os(iOS)
|
||||
colorSection
|
||||
|
||||
Button {
|
||||
settings.presentAlert(
|
||||
Alert(
|
||||
title: Text("Restore Default Colors?"),
|
||||
message: Text("This action will reset all custom colors back to their original defaults. " +
|
||||
"Any custom color changes you've made will be lost."),
|
||||
primaryButton: .destructive(Text("Restore")) {
|
||||
resetColors()
|
||||
},
|
||||
secondaryButton: .cancel()
|
||||
)
|
||||
)
|
||||
)
|
||||
} label: {
|
||||
Text("Restore Default Colors …")
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
} label: {
|
||||
Text("Restore Default Colors …")
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
#endif
|
||||
|
||||
Section(footer: categoriesDetails) {
|
||||
EmptyView()
|
||||
@@ -80,21 +85,23 @@ struct SponsorBlockSettings: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var colorSection: some View {
|
||||
Section(header: SettingsHeader(text: "Colors for Categories")) {
|
||||
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
||||
LazyVStack(alignment: .leading) {
|
||||
ColorPicker(
|
||||
SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
|
||||
selection: Binding(
|
||||
get: { getColor(for: category) },
|
||||
set: { setColor($0, for: category) }
|
||||
#if os(iOS)
|
||||
private var colorSection: some View {
|
||||
Section(header: SettingsHeader(text: "Colors for Categories")) {
|
||||
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
||||
LazyVStack(alignment: .leading) {
|
||||
ColorPicker(
|
||||
SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
|
||||
selection: Binding(
|
||||
get: { getColor(for: category) },
|
||||
set: { setColor($0, for: category) }
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private var categoryRows: some View {
|
||||
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
||||
@@ -145,25 +152,27 @@ struct SponsorBlockSettings: View {
|
||||
return Color("AppRedColor") // Fallback color if no match found
|
||||
}
|
||||
|
||||
private func setColor(_ color: Color, for category: String) {
|
||||
let uiColor = UIColor(color)
|
||||
#if canImport(UIKit)
|
||||
private func setColor(_ color: Color, for category: String) {
|
||||
let uiColor = UIColor(color)
|
||||
|
||||
// swiftlint:disable no_cgfloat
|
||||
var red: CGFloat = 0
|
||||
var green: CGFloat = 0
|
||||
var blue: CGFloat = 0
|
||||
var alpha: CGFloat = 0
|
||||
// swiftlint:enable no_cgfloat
|
||||
// swiftlint:disable no_cgfloat
|
||||
var red: CGFloat = 0
|
||||
var green: CGFloat = 0
|
||||
var blue: CGFloat = 0
|
||||
var alpha: CGFloat = 0
|
||||
// swiftlint:enable no_cgfloat
|
||||
|
||||
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
|
||||
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
|
||||
|
||||
let r = Int(red * 255.0)
|
||||
let g = Int(green * 255.0)
|
||||
let b = Int(blue * 255.0)
|
||||
let r = Int(red * 255.0)
|
||||
let g = Int(green * 255.0)
|
||||
let b = Int(blue * 255.0)
|
||||
|
||||
let rgbValue = (r << 16) | (g << 8) | b
|
||||
sponsorBlockColors[category] = String(format: "#%06x", rgbValue)
|
||||
}
|
||||
let rgbValue = (r << 16) | (g << 8) | b
|
||||
sponsorBlockColors[category] = String(format: "#%06x", rgbValue)
|
||||
}
|
||||
#endif
|
||||
|
||||
private func resetColors() {
|
||||
sponsorBlockColors = SponsorBlockColors.dictionary
|
||||
|
||||
3
Shared/Strings.swift
Normal file
3
Shared/Strings.swift
Normal file
@@ -0,0 +1,3 @@
|
||||
enum Strings {
|
||||
static let yatteeProtocol = "yattee://"
|
||||
}
|
||||
@@ -176,7 +176,7 @@ struct URLParser {
|
||||
private func removePrefixes(_ value: String, _ prefixes: [String]) -> String {
|
||||
var value = value
|
||||
|
||||
prefixes.forEach { prefix in
|
||||
for prefix in prefixes {
|
||||
if value.hasPrefix(prefix) {
|
||||
value.removeFirst(prefix.count)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ struct ShareButton<LabelView: View>: View {
|
||||
|
||||
private var youtubeActions: some View {
|
||||
Group {
|
||||
if let url = accounts.api.shareURL(contentItem, frontendURL: "https://www.youtube.com") {
|
||||
if let url = accounts.api.shareURL(contentItem, frontendURLString: "https://www.youtube.com") {
|
||||
Button(labelForShareURL("YouTube")) {
|
||||
shareAction(url)
|
||||
}
|
||||
@@ -87,7 +87,7 @@ struct ShareButton<LabelView: View>: View {
|
||||
shareAction(
|
||||
accounts.api.shareURL(
|
||||
contentItem,
|
||||
frontendURL: "https://www.youtube.com",
|
||||
frontendURLString: "https://www.youtube.com",
|
||||
time: player.backend.currentTime
|
||||
)!
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ extension UIView {
|
||||
}
|
||||
|
||||
private func viewsInHierarchy<ViewType: UIView>(views: inout [ViewType]) {
|
||||
subviews.forEach { eachSubView in
|
||||
for eachSubView in subviews {
|
||||
if let matchingView = eachSubView as? ViewType {
|
||||
views.append(matchingView)
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
3709528A29283E14001ECA40 /* NoDocumentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3709528929283E14001ECA40 /* NoDocumentsView.swift */; };
|
||||
37095E82291DC85400301883 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37095E81291DC85400301883 /* ShareViewController.swift */; };
|
||||
37095E89291DC85400301883 /* Open in Yattee.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 37095E7F291DC85400301883 /* Open in Yattee.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
37095E8D291DD5DA00301883 /* URLBookmarkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F5E8B5291BE9D0006C15F5 /* URLBookmarkModel.swift */; };
|
||||
370B79C9286279810045DB77 /* NSObject+Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370B79C8286279810045DB77 /* NSObject+Swizzle.swift */; };
|
||||
370B79CC286279BA0045DB77 /* UIViewController+HideHomeIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370B79CB286279BA0045DB77 /* UIViewController+HideHomeIndicator.swift */; };
|
||||
370E990A2A1EA8C500D144E9 /* WatchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370E99092A1EA8C500D144E9 /* WatchModel.swift */; };
|
||||
@@ -378,6 +377,12 @@
|
||||
3761ABFD26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3761ABFC26F0F8DE00AA496F /* EnvironmentValues.swift */; };
|
||||
3761ABFE26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3761ABFC26F0F8DE00AA496F /* EnvironmentValues.swift */; };
|
||||
3761ABFF26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3761ABFC26F0F8DE00AA496F /* EnvironmentValues.swift */; };
|
||||
3762C46D2BF66CDD008E50B8 /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3761ABFC26F0F8DE00AA496F /* EnvironmentValues.swift */; };
|
||||
3762C4772BF66F04008E50B8 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3762C4762BF66F04008E50B8 /* Strings.swift */; };
|
||||
3762C4782BF66F04008E50B8 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3762C4762BF66F04008E50B8 /* Strings.swift */; };
|
||||
3762C4792BF66F04008E50B8 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3762C4762BF66F04008E50B8 /* Strings.swift */; };
|
||||
3762C47A2BF66F04008E50B8 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3762C4762BF66F04008E50B8 /* Strings.swift */; };
|
||||
3762C47D2BF66FF7008E50B8 /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = 3762C47C2BF66FF7008E50B8 /* Defaults */; };
|
||||
3763495126DFF59D00B9A393 /* AppSidebarRecents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3763495026DFF59D00B9A393 /* AppSidebarRecents.swift */; };
|
||||
3763495226DFF59D00B9A393 /* AppSidebarRecents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3763495026DFF59D00B9A393 /* AppSidebarRecents.swift */; };
|
||||
37635FE4291EA6CF00C11E79 /* AccentButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37635FE3291EA6CF00C11E79 /* AccentButton.swift */; };
|
||||
@@ -1059,8 +1064,6 @@
|
||||
37FD77002932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||
37FD77012932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||
37FD77022932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||
37FD77032932C5EC00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||
37FD77042932C5FC00D91A5F /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754B01428B7F84D009717C8 /* Constants.swift */; };
|
||||
37FEF11327EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||
37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||
@@ -1265,6 +1268,7 @@
|
||||
375EC971289F2ABF00751258 /* MultiselectRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiselectRow.swift; sourceTree = "<group>"; };
|
||||
375F740F289DC35A00747050 /* PlayerBackendView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerBackendView.swift; sourceTree = "<group>"; };
|
||||
3761ABFC26F0F8DE00AA496F /* EnvironmentValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnvironmentValues.swift; sourceTree = "<group>"; };
|
||||
3762C4762BF66F04008E50B8 /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
||||
3763495026DFF59D00B9A393 /* AppSidebarRecents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSidebarRecents.swift; sourceTree = "<group>"; };
|
||||
37635FE3291EA6CF00C11E79 /* AccentButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccentButton.swift; sourceTree = "<group>"; };
|
||||
3763C988290C7A50004D3B5F /* OpenVideosView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenVideosView.swift; sourceTree = "<group>"; };
|
||||
@@ -1542,6 +1546,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3762C47D2BF66FF7008E50B8 /* Defaults in Frameworks */,
|
||||
378CC2E32B669489006309F4 /* Logging in Frameworks */,
|
||||
377F9F85294417FA0043F856 /* SwiftyJSON in Frameworks */,
|
||||
377F9F83294417B40043F856 /* Cache in Frameworks */,
|
||||
@@ -2276,6 +2281,7 @@
|
||||
371AAE2726CEBF4700901972 /* Videos */,
|
||||
371AAE2826CEC7D900901972 /* Views */,
|
||||
3754B01428B7F84D009717C8 /* Constants.swift */,
|
||||
3762C4762BF66F04008E50B8 /* Strings.swift */,
|
||||
375168D52700FAFF008F96A6 /* Debounce.swift */,
|
||||
372915E52687E3B900F5A35B /* Defaults.swift */,
|
||||
37D2E0D328B67EFC00F64D52 /* Delay.swift */,
|
||||
@@ -2501,6 +2507,7 @@
|
||||
377F9F82294417B40043F856 /* Cache */,
|
||||
377F9F84294417FA0043F856 /* SwiftyJSON */,
|
||||
378CC2E22B669489006309F4 /* Logging */,
|
||||
3762C47C2BF66FF7008E50B8 /* Defaults */,
|
||||
);
|
||||
productName = "Open in Yattee";
|
||||
productReference = 37095E7F291DC85400301883 /* Open in Yattee.appex */;
|
||||
@@ -3000,10 +3007,9 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3738535729451E0C00D2D0CB /* BookmarksCacheModel.swift in Sources */,
|
||||
37FD77042932C5FC00D91A5F /* Constants.swift in Sources */,
|
||||
3762C46D2BF66CDD008E50B8 /* EnvironmentValues.swift in Sources */,
|
||||
37095E82291DC85400301883 /* ShareViewController.swift in Sources */,
|
||||
37FD77032932C5EC00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */,
|
||||
37095E8D291DD5DA00301883 /* URLBookmarkModel.swift in Sources */,
|
||||
3762C47A2BF66F04008E50B8 /* Strings.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -3330,6 +3336,7 @@
|
||||
37D4B0E42671614900C925CA /* YatteeApp.swift in Sources */,
|
||||
37C3A241272359900087A57A /* Double+Format.swift in Sources */,
|
||||
3784CDE227772EE40055BBF2 /* Watch.swift in Sources */,
|
||||
3762C4772BF66F04008E50B8 /* Strings.swift in Sources */,
|
||||
37FB285E272225E800A57617 /* ContentItemView.swift in Sources */,
|
||||
3797758B2689345500DD52A8 /* Store.swift in Sources */,
|
||||
3773B80D2ADC076800B5FEF3 /* FramePreferenceKey.swift in Sources */,
|
||||
@@ -3401,6 +3408,7 @@
|
||||
37192D5828B179D60012EEDD /* ChaptersView.swift in Sources */,
|
||||
37E75CCC2B6AEB01003A6237 /* RecentlyOpenedExporter.swift in Sources */,
|
||||
3784CDE327772EE40055BBF2 /* Watch.swift in Sources */,
|
||||
3762C4782BF66F04008E50B8 /* Strings.swift in Sources */,
|
||||
371AC0B7294D1D6E0085989E /* PlayingIndicatorView.swift in Sources */,
|
||||
3773B8182ADC081300B5FEF3 /* VisualEffectBlur-macOS.swift in Sources */,
|
||||
37E80F3D287B107F00561799 /* VideoDetailsOverlay.swift in Sources */,
|
||||
@@ -3826,6 +3834,7 @@
|
||||
37769250294630110055EC18 /* ChannelAvatarView.swift in Sources */,
|
||||
37030FFD27B0398000ECDDAA /* MPVClient.swift in Sources */,
|
||||
378E9C4229455A5800B2D696 /* ChannelsView.swift in Sources */,
|
||||
3762C4792BF66F04008E50B8 /* Strings.swift in Sources */,
|
||||
37192D5928B179D60012EEDD /* ChaptersView.swift in Sources */,
|
||||
37B767DD2677C3CA0098BAA8 /* PlayerModel.swift in Sources */,
|
||||
373CFAF12697A78B003CB2C6 /* AddToPlaylistView.swift in Sources */,
|
||||
@@ -4062,7 +4071,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Open in Yattee/Open in Yattee.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Open in Yattee/Info.plist";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Open in Yattee";
|
||||
@@ -4093,7 +4102,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Open in Yattee/Info.plist";
|
||||
@@ -4124,7 +4133,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
@@ -4144,7 +4153,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
@@ -4308,7 +4317,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "iOS/Yattee (iOS).entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -4361,7 +4370,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION=1";
|
||||
@@ -4413,7 +4422,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@@ -4452,7 +4461,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = 78Z5H3M6RJ;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
@@ -4487,7 +4496,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4511,7 +4520,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4537,7 +4546,7 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4562,7 +4571,7 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4588,7 +4597,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -4628,7 +4637,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
"DEVELOPMENT_TEAM[sdk=appletvos*]" = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -4669,7 +4678,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -4693,7 +4702,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 181;
|
||||
CURRENT_PROJECT_VERSION = 182;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -5003,7 +5012,7 @@
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/cxfksword/MPVKit.git";
|
||||
requirement = {
|
||||
kind = upToNextMinorVersion;
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.38.0;
|
||||
};
|
||||
};
|
||||
@@ -5110,6 +5119,11 @@
|
||||
package = 375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */;
|
||||
productName = KeychainAccess;
|
||||
};
|
||||
3762C47C2BF66FF7008E50B8 /* Defaults */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 372915E22687E33E00F5A35B /* XCRemoteSwiftPackageReference "Defaults" */;
|
||||
productName = Defaults;
|
||||
};
|
||||
3765917B27237D21009F956E /* PINCache */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 3765917827237D07009F956E /* XCRemoteSwiftPackageReference "PINCache" */;
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
"location" : "https://github.com/pinterest/PINCache",
|
||||
"state" : {
|
||||
"branch" : "master",
|
||||
"revision" : "f856226e8bee58d75cb6be1707ae0cb2f5801150"
|
||||
"revision" : "2fb85948463292c2e824148cf17dc62a4c217a94"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -78,8 +78,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/pinterest/PINOperation.git",
|
||||
"state" : {
|
||||
"revision" : "40504c156a68b20f98f7ddc73a115cbb7893be25",
|
||||
"version" : "1.2.2"
|
||||
"revision" : "a74f978733bdaf982758bfa23d70a189f4b4c1b6",
|
||||
"version" : "1.2.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -105,8 +105,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SDWebImage/SDWebImage",
|
||||
"state" : {
|
||||
"revision" : "f6afa0132961d593f07970d84e2d8b588c29ea04",
|
||||
"version" : "5.19.1"
|
||||
"revision" : "5642d1ffe3dbe628592443bd14154e31929727b4",
|
||||
"version" : "5.19.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -182,5 +182,5 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 3
|
||||
"version" : 2
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
#endif
|
||||
return true
|
||||
}
|
||||
|
||||
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
||||
|
||||
func application(_: UIApplication, open url: URL, options _: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
|
||||
if url.scheme == "yattee" {
|
||||
OpenURLHandler.handle(url)
|
||||
OpenURLHandler(navigationStyle: Constants.defaultNavigationStyle).handle(url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -153,7 +153,6 @@ struct InstancesSettings: View {
|
||||
}
|
||||
}
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
.onAppear {
|
||||
selectedInstanceID = instances.first?.id
|
||||
frontendURL = selectedInstanceFrontendURL
|
||||
|
||||
@@ -31,7 +31,7 @@ struct VerticalScrollingFixWrapper<Content>: View where Content: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VerticalScrollingFixViewRepresentable(content: self.content())
|
||||
VerticalScrollingFixViewRepresentable(content: content())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user