mirror of
https://github.com/yattee/yattee.git
synced 2025-12-14 20:18:15 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7b35925b4 | ||
|
|
5bac92fdbf | ||
|
|
bf2c9a9e43 | ||
|
|
f8d79bb08c | ||
|
|
b9ad5bc633 | ||
|
|
f1e132a909 | ||
|
|
d58026bcef | ||
|
|
4697aa9696 | ||
|
|
dbf3537f22 | ||
|
|
474e280faa | ||
|
|
04fe18ac4c | ||
|
|
66665db344 | ||
|
|
38612eae52 | ||
|
|
80c1f63e35 | ||
|
|
f4fb31e9e2 | ||
|
|
44ff68b3c1 | ||
|
|
737f762bfb | ||
|
|
2844838485 | ||
|
|
f39accdf7e |
34
.github/workflows/bump-build.yml
vendored
Normal file
34
.github/workflows/bump-build.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Bump build number
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
APP_NAME: Yattee
|
||||
|
||||
jobs:
|
||||
bump_build:
|
||||
name: Bump build number
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.0'
|
||||
bundler-cache: true
|
||||
- uses: maierj/fastlane-action@v3.0.0
|
||||
with:
|
||||
lane: bump_build
|
||||
- run: echo "BUILD_NUMBER=$(cat Yattee.xcodeproj/project.pbxproj | grep -m 1 CURRENT_PROJECT_VERSION | cut -d' ' -f3 | sed 's/;//g')" >> $GITHUB_ENV
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.GIT_AUTHORIZATION }}
|
||||
branch: actions/bump-build-to-${{ env.BUILD_NUMBER }}
|
||||
base: main
|
||||
title: Bump build number to ${{ env.BUILD_NUMBER }}
|
||||
|
||||
|
||||
34
.github/workflows/release.yml
vendored
34
.github/workflows/release.yml
vendored
@@ -20,29 +20,7 @@ env:
|
||||
TESTFLIGHT_EXTERNAL_GROUPS: ${{ secrets.TESTFLIGHT_EXTERNAL_GROUPS }}
|
||||
|
||||
jobs:
|
||||
bump_build:
|
||||
name: Bump build number
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.0'
|
||||
bundler-cache: true
|
||||
- uses: maierj/fastlane-action@v3.0.0
|
||||
with:
|
||||
lane: bump_build
|
||||
- name: Push changes
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GIT_AUTHORIZATION }}
|
||||
branch: ${{ github.ref }}
|
||||
testflight:
|
||||
needs: bump_build
|
||||
strategy:
|
||||
matrix:
|
||||
lane: ['mac beta', 'ios beta', 'tvos beta']
|
||||
@@ -50,8 +28,6 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: main
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.0'
|
||||
@@ -69,13 +45,10 @@ jobs:
|
||||
path: fastlane/builds/**/*.ipa
|
||||
if-no-files-found: ignore
|
||||
mac_notarized:
|
||||
needs: bump_build
|
||||
name: Build and notarize macOS app
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: main
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.0'
|
||||
@@ -101,21 +74,16 @@ jobs:
|
||||
path: ${{ env.ZIP_PATH }}
|
||||
if-no-files-found: error
|
||||
release:
|
||||
needs: ['bump_build', 'testflight', 'mac_notarized']
|
||||
needs: ['testflight', 'mac_notarized']
|
||||
name: Create GitHub release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: main
|
||||
- run: echo "BUILD_NUMBER=$(cat Yattee.xcodeproj/project.pbxproj | grep -m 1 CURRENT_PROJECT_VERSION | cut -d' ' -f3 | sed 's/;//g')" >> $GITHUB_ENV
|
||||
- run: echo "VERSION_NUMBER=$(cat Yattee.xcodeproj/project.pbxproj | grep -m 1 MARKETING_VERSION | cut -d' ' -f3 | sed 's/;//g')" >> $GITHUB_ENV
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: artifacts
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
working-directory: artifacts
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
artifacts: artifacts/**/*.ipa,artifacts/**/*.zip
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
137
|
||||
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,10 +1,11 @@
|
||||
## Build 137
|
||||
## Build 138
|
||||
* Added pagination/infinite scroll for channel contents (Invidious and Piped)
|
||||
* Added support for channel tabs for Invidious (previously available only for Piped)
|
||||
* New browsing setting: "Show unwatched feed badges"
|
||||
* Other minor changes and improvements
|
||||
|
||||
### Previous Builds
|
||||
* Added filter to hide Short videos, available via view menu/toolbar button
|
||||
* Added localizations: Arabic, Portugese, Portuguese (Brazil)
|
||||
* Fixed reported crashes
|
||||
* Other minor changes and improvements
|
||||
|
||||
### Previous Builds
|
||||
|
||||
* Fixed issue with loading channels in Favorites with Invidious
|
||||
* Other minor changes and improvements
|
||||
|
||||
@@ -109,17 +109,22 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
content.json.arrayValue.map(self.extractChannel)
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("channels/*"), requestMethods: [.get]) { (content: Entity<JSON>) -> Channel in
|
||||
self.extractChannel(from: content.json)
|
||||
configureTransformer(pathPattern("channels/*"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPage in
|
||||
self.extractChannelPage(from: content.json, forceNotLast: true)
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("channels/*/videos"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPage in
|
||||
self.extractChannelPage(from: content.json)
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("channels/*/latest"), requestMethods: [.get]) { (content: Entity<JSON>) -> [Video] in
|
||||
content.json.dictionaryValue["videos"]?.arrayValue.map(self.extractVideo) ?? []
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("channels/*/playlists"), requestMethods: [.get]) { (content: Entity<JSON>) -> [ContentItem] in
|
||||
let playlists = (content.json.dictionaryValue["playlists"]?.arrayValue ?? []).compactMap { self.extractChannelPlaylist(from: $0) }
|
||||
return ContentItem.array(of: playlists)
|
||||
["latest", "playlists", "streams", "shorts", "channels", "videos"].forEach { type in
|
||||
configureTransformer(pathPattern("channels/*/\(type)"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPage in
|
||||
self.extractChannelPage(from: content.json)
|
||||
}
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("playlists/*"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPlaylist in
|
||||
@@ -266,11 +271,18 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
.onCompletion { _ in onCompletion() }
|
||||
}
|
||||
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data _: String?) -> Resource {
|
||||
if contentType == .playlists {
|
||||
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)/playlists"))
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data _: String?, page: String?) -> Resource {
|
||||
if page.isNil, contentType == .videos {
|
||||
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)"))
|
||||
}
|
||||
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)"))
|
||||
|
||||
var resource = resource(baseURL: account.url, path: basePathAppending("channels/\(id)/\(contentType.invidiousID)"))
|
||||
|
||||
if let page, !page.isEmpty {
|
||||
resource = resource.withParam("continuation", page)
|
||||
}
|
||||
|
||||
return resource
|
||||
}
|
||||
|
||||
func channelByName(_: String) -> Resource? {
|
||||
@@ -504,6 +516,14 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
thumbnailURL = "\(accountUrlComponents.scheme ?? "https"):\(thumbnailURL)"
|
||||
}
|
||||
|
||||
let tabs = json["tabs"].arrayValue.compactMap { name in
|
||||
if let name = name.string, let type = Channel.ContentType.from(name) {
|
||||
return Channel.Tab(contentType: type, data: "")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return Channel(
|
||||
app: .invidious,
|
||||
id: json["authorId"].stringValue,
|
||||
@@ -514,7 +534,8 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
subscriptionsCount: json["subCount"].int,
|
||||
subscriptionsText: json["subCountText"].string,
|
||||
totalViews: json["totalViews"].int,
|
||||
videos: json.dictionaryValue["latestVideos"]?.arrayValue.map(extractVideo) ?? []
|
||||
videos: json.dictionaryValue["latestVideos"]?.arrayValue.map(extractVideo) ?? [],
|
||||
tabs: tabs
|
||||
)
|
||||
}
|
||||
|
||||
@@ -552,6 +573,33 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
}
|
||||
}
|
||||
|
||||
private static var contentItemsKeys = ["items", "videos", "latestVideos", "playlists", "relatedChannels"]
|
||||
|
||||
private func extractChannelPage(from json: JSON, forceNotLast: Bool = false) -> ChannelPage {
|
||||
let nextPage = json.dictionaryValue["continuation"]?.string
|
||||
var contentItems = [ContentItem]()
|
||||
|
||||
var items = [ContentItem]()
|
||||
|
||||
if let key = Self.contentItemsKeys.first(where: { json.dictionaryValue.keys.contains($0) }),
|
||||
let items = json.dictionaryValue[key]
|
||||
{
|
||||
contentItems = extractContentItems(from: items)
|
||||
}
|
||||
|
||||
var last = false
|
||||
if !forceNotLast {
|
||||
last = nextPage?.isEmpty ?? true
|
||||
}
|
||||
|
||||
return ChannelPage(
|
||||
results: contentItems,
|
||||
channel: extractChannel(from: json),
|
||||
nextPage: nextPage,
|
||||
last: last
|
||||
)
|
||||
}
|
||||
|
||||
private func extractStreams(from json: JSON) -> [Stream] {
|
||||
let hls = extractHLSStreams(from: json)
|
||||
if json["liveNow"].boolValue {
|
||||
@@ -668,4 +716,33 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func extractContentItems(from json: JSON) -> [ContentItem] {
|
||||
json.arrayValue.compactMap { extractContentItem(from: $0) }
|
||||
}
|
||||
|
||||
private func extractContentItem(from json: JSON) -> ContentItem? {
|
||||
let type = json.dictionaryValue["type"]?.string
|
||||
|
||||
if type == "channel" {
|
||||
return ContentItem(channel: extractChannel(from: json))
|
||||
} else if type == "playlist" {
|
||||
return ContentItem(playlist: extractChannelPlaylist(from: json))
|
||||
} else if type == "video" {
|
||||
return ContentItem(video: extractVideo(from: json))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
extension Channel.ContentType {
|
||||
var invidiousID: String {
|
||||
switch self {
|
||||
case .livestreams:
|
||||
return "streams"
|
||||
default:
|
||||
return rawValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ final class PeerTubeAPI: Service, ObservableObject, VideosAPI {
|
||||
.onCompletion { _ in onCompletion() }
|
||||
}
|
||||
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data _: String?) -> Resource {
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data _: String?, page _: String?) -> Resource {
|
||||
if contentType == .playlists {
|
||||
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)/playlists"))
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import SwiftyJSON
|
||||
final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
static var disallowedVideoCodecs = ["av01"]
|
||||
static var authorizedEndpoints = ["subscriptions", "subscribe", "unsubscribe", "user/playlists"]
|
||||
static var contentItemsKeys = ["items", "content", "relatedStreams"]
|
||||
|
||||
@Published var account: Account!
|
||||
|
||||
@@ -40,8 +41,25 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
$0.headers["Authorization"] = self.account.token
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("channel/*")) { (content: Entity<JSON>) -> Channel? in
|
||||
self.extractChannel(from: content.json)
|
||||
configureTransformer(pathPattern("channel/*")) { (content: Entity<JSON>) -> ChannelPage in
|
||||
let nextPage = content.json.dictionaryValue["nextpage"]?.string
|
||||
let channel = self.extractChannel(from: content.json)
|
||||
return ChannelPage(
|
||||
results: self.extractContentItems(from: self.contentItemsDictionary(from: content.json)),
|
||||
channel: channel,
|
||||
nextPage: nextPage,
|
||||
last: nextPage.isNil
|
||||
)
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("/nextpage/channel/*")) { (content: Entity<JSON>) -> ChannelPage in
|
||||
let nextPage = content.json.dictionaryValue["nextpage"]?.string
|
||||
return ChannelPage(
|
||||
results: self.extractContentItems(from: self.contentItemsDictionary(from: content.json)),
|
||||
channel: self.extractChannel(from: content.json),
|
||||
nextPage: nextPage,
|
||||
last: nextPage.isNil
|
||||
)
|
||||
}
|
||||
|
||||
configureTransformer(pathPattern("channels/tabs*")) { (content: Entity<JSON>) -> [ContentItem] in
|
||||
@@ -159,13 +177,23 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
resource(baseURL: account.url, path: "login")
|
||||
}
|
||||
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data: String?) -> Resource {
|
||||
if contentType == .videos {
|
||||
return resource(baseURL: account.url, path: "channel/\(id)")
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data: String?, page: String?) -> Resource {
|
||||
let path = page.isNil ? "channel" : "nextpage/channel"
|
||||
|
||||
var channel: Siesta.Resource
|
||||
|
||||
if contentType == .videos || data.isNil {
|
||||
channel = resource(baseURL: account.url, path: "\(path)/\(id)")
|
||||
} else {
|
||||
channel = resource(baseURL: account.url, path: "channels/tabs")
|
||||
.withParam("data", data)
|
||||
}
|
||||
|
||||
return resource(baseURL: account.url, path: "channels/tabs")
|
||||
.withParam("data", data)
|
||||
if let page, !page.isEmpty {
|
||||
channel = channel.withParam("nextpage", page)
|
||||
}
|
||||
|
||||
return channel
|
||||
}
|
||||
|
||||
func channelByName(_ name: String) -> Resource? {
|
||||
@@ -700,4 +728,14 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
return Chapter(title: title, image: image, start: start)
|
||||
}
|
||||
}
|
||||
|
||||
private func contentItemsDictionary(from content: JSON) -> JSON {
|
||||
if let key = Self.contentItemsKeys.first(where: { content.dictionaryValue.keys.contains($0) }),
|
||||
let items = content.dictionaryValue[key]
|
||||
{
|
||||
return items
|
||||
}
|
||||
|
||||
return .null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ protocol VideosAPI {
|
||||
|
||||
static func withAnonymousAccountForInstanceURL(_ url: URL) -> Self
|
||||
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data: String?) -> Resource
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data: String?, page: String?) -> Resource
|
||||
func channelByName(_ name: String) -> Resource?
|
||||
func channelByUsername(_ username: String) -> Resource?
|
||||
func channelVideos(_ id: String) -> Resource
|
||||
@@ -72,8 +72,8 @@ protocol VideosAPI {
|
||||
}
|
||||
|
||||
extension VideosAPI {
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data: String? = nil) -> Resource {
|
||||
channel(id, contentType: contentType, data: data)
|
||||
func channel(_ id: String, contentType: Channel.ContentType, data: String? = nil, page: String? = nil) -> Resource {
|
||||
channel(id, contentType: contentType, data: data, page: page)
|
||||
}
|
||||
|
||||
func loadDetails(
|
||||
|
||||
@@ -34,11 +34,11 @@ struct ChannelsCacheModel: CacheModel {
|
||||
store(channel)
|
||||
}
|
||||
|
||||
func retrieve(_ cacheKey: String) -> Channel? {
|
||||
func retrieve(_ cacheKey: String) -> ChannelPage? {
|
||||
logger.debug("retrieving cache for \(cacheKey)")
|
||||
|
||||
if let json = try? storage?.object(forKey: cacheKey) {
|
||||
return Channel.from(json)
|
||||
return ChannelPage(channel: Channel.from(json))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -110,12 +110,12 @@ final class SubscribedChannelsModel: ObservableObject, CacheModel {
|
||||
if let json = try? storage?.object(forKey: channelsCacheKey(account)),
|
||||
let channels = json.dictionaryValue["channels"]
|
||||
{
|
||||
return channels.arrayValue.map { json in
|
||||
return channels.arrayValue.compactMap { json in
|
||||
let channel = Channel.from(json)
|
||||
if !channel.hasExtendedDetails,
|
||||
let cache = ChannelsCacheModel.shared.retrieve(channel.cacheKey)
|
||||
{
|
||||
return cache
|
||||
return cache.channel
|
||||
}
|
||||
|
||||
return channel
|
||||
|
||||
@@ -11,6 +11,15 @@ struct Channel: Identifiable, Hashable {
|
||||
case shorts
|
||||
case channels
|
||||
|
||||
static func from(_ name: String) -> Self? {
|
||||
let rawValueMatch = allCases.first { $0.rawValue == name }
|
||||
guard rawValueMatch.isNil else { return rawValueMatch! }
|
||||
|
||||
if name == "streams" { return .livestreams }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var id: String {
|
||||
rawValue
|
||||
}
|
||||
@@ -53,6 +62,10 @@ struct Channel: Identifiable, Hashable {
|
||||
return "person.3"
|
||||
}
|
||||
}
|
||||
|
||||
var alwaysAvailable: Bool {
|
||||
self == .videos || self == .playlists
|
||||
}
|
||||
}
|
||||
|
||||
struct Tab: Identifiable, Hashable {
|
||||
@@ -110,7 +123,6 @@ struct Channel: Identifiable, Hashable {
|
||||
}
|
||||
|
||||
func hasData(for contentType: ContentType) -> Bool {
|
||||
guard contentType != .videos, contentType != .playlists else { return true }
|
||||
return tabs.contains { $0.contentType == contentType }
|
||||
}
|
||||
|
||||
@@ -132,7 +144,7 @@ struct Channel: Identifiable, Hashable {
|
||||
}
|
||||
|
||||
var thumbnailURLOrCached: URL? {
|
||||
thumbnailURL ?? ChannelsCacheModel.shared.retrieve(cacheKey)?.thumbnailURL
|
||||
thumbnailURL ?? ChannelsCacheModel.shared.retrieve(cacheKey)?.channel?.thumbnailURL
|
||||
}
|
||||
|
||||
var json: JSON {
|
||||
|
||||
8
Model/ChannelPage.swift
Normal file
8
Model/ChannelPage.swift
Normal file
@@ -0,0 +1,8 @@
|
||||
import Foundation
|
||||
|
||||
struct ChannelPage {
|
||||
var results = [ContentItem]()
|
||||
var channel: Channel?
|
||||
var nextPage: String?
|
||||
var last = false
|
||||
}
|
||||
@@ -115,7 +115,7 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
}
|
||||
|
||||
func calculateUnwatchedFeed() {
|
||||
guard let account = accounts.current, accounts.signedIn else { return }
|
||||
guard let account = accounts.current, accounts.signedIn, Defaults[.showUnwatchedFeedBadges] else { return }
|
||||
let feed = cacheModel.retrieveFeed(account: account)
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self else { return }
|
||||
|
||||
@@ -11,11 +11,12 @@ struct ChannelVideosView: View {
|
||||
@State private var shareURL: URL?
|
||||
@State private var subscriptionToggleButtonDisabled = false
|
||||
|
||||
@State private var page: ChannelPage?
|
||||
@State private var contentType = Channel.ContentType.videos
|
||||
@StateObject private var contentTypeItems = Store<[ContentItem]>()
|
||||
|
||||
@State private var descriptionExpanded = false
|
||||
@StateObject private var store = Store<Channel>()
|
||||
@StateObject private var store = Store<ChannelPage>()
|
||||
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
@@ -35,14 +36,10 @@ struct ChannelVideosView: View {
|
||||
@Default(.hideShorts) private var hideShorts
|
||||
|
||||
var presentedChannel: Channel? {
|
||||
store.item ?? channel ?? recents.presentedChannel
|
||||
store.item?.channel ?? channel ?? recents.presentedChannel
|
||||
}
|
||||
|
||||
var contentItems: [ContentItem] {
|
||||
guard contentType != .videos else {
|
||||
return ContentItem.array(of: presentedChannel?.videos ?? [])
|
||||
}
|
||||
|
||||
return contentTypeItems.collection
|
||||
}
|
||||
|
||||
@@ -63,6 +60,8 @@ struct ChannelVideosView: View {
|
||||
viewsLabel
|
||||
|
||||
subscriptionToggleButton
|
||||
favoriteButton
|
||||
.labelStyle(.iconOnly)
|
||||
}
|
||||
contentTypePicker
|
||||
.pickerStyle(.automatic)
|
||||
@@ -99,6 +98,7 @@ struct ChannelVideosView: View {
|
||||
banner
|
||||
}
|
||||
}
|
||||
.environment(\.loadMoreContentHandler) { loadNextPage() }
|
||||
.environment(\.inChannelView, true)
|
||||
.environment(\.listingStyle, channelPlaylistListingStyle)
|
||||
.environment(\.hideShorts, hideShorts)
|
||||
@@ -159,9 +159,7 @@ struct ChannelVideosView: View {
|
||||
}
|
||||
|
||||
ToolbarItem {
|
||||
if let presentedChannel {
|
||||
FavoriteButton(item: FavoriteItem(section: .channel(accounts.app.appType.rawValue, presentedChannel.id, presentedChannel.name)))
|
||||
}
|
||||
favoriteButton
|
||||
}
|
||||
|
||||
ToolbarItem {
|
||||
@@ -180,14 +178,10 @@ struct ChannelVideosView: View {
|
||||
store.replace(cache)
|
||||
}
|
||||
|
||||
resource?.loadIfNeeded()?.onSuccess { response in
|
||||
if let channel: Channel = response.typedContent() {
|
||||
ChannelsCacheModel.shared.store(channel)
|
||||
}
|
||||
}
|
||||
load()
|
||||
}
|
||||
.onChange(of: contentType) { _ in
|
||||
resource?.load()
|
||||
load()
|
||||
}
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
@@ -211,8 +205,14 @@ struct ChannelVideosView: View {
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder var favoriteButton: some View {
|
||||
if let presentedChannel {
|
||||
FavoriteButton(item: FavoriteItem(section: .channel(accounts.app.appType.rawValue, presentedChannel.id, presentedChannel.name)))
|
||||
}
|
||||
}
|
||||
|
||||
var thumbnail: some View {
|
||||
ChannelAvatarView(channel: store.item)
|
||||
ChannelAvatarView(channel: store.item?.channel)
|
||||
#if os(tvOS)
|
||||
.frame(width: 80, height: 80, alignment: .trailing)
|
||||
#else
|
||||
@@ -232,7 +232,7 @@ struct ChannelVideosView: View {
|
||||
|
||||
var subscriptionsLabel: some View {
|
||||
Group {
|
||||
if let subscribers = store.item?.subscriptionsString {
|
||||
if let subscribers = store.item?.channel?.subscriptionsString {
|
||||
HStack(spacing: 0) {
|
||||
Text(subscribers)
|
||||
Image(systemName: "person.2.fill")
|
||||
@@ -251,7 +251,7 @@ struct ChannelVideosView: View {
|
||||
|
||||
var viewsLabel: some View {
|
||||
HStack(spacing: 0) {
|
||||
if let views = store.item?.totalViewsString {
|
||||
if let views = store.item?.channel?.totalViewsString {
|
||||
Text(views)
|
||||
|
||||
Image(systemName: "eye.fill")
|
||||
@@ -322,7 +322,7 @@ struct ChannelVideosView: View {
|
||||
Picker("Content type", selection: $contentType) {
|
||||
if let channel = presentedChannel {
|
||||
ForEach(Channel.ContentType.allCases, id: \.self) { type in
|
||||
if channel.hasData(for: type) {
|
||||
if typeAvailable(type) {
|
||||
Label(type.description, systemImage: type.systemImage).tag(type)
|
||||
}
|
||||
}
|
||||
@@ -330,16 +330,20 @@ struct ChannelVideosView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func typeAvailable(_ type: Channel.ContentType) -> Bool {
|
||||
type.alwaysAvailable || (presentedChannel?.hasData(for: type) ?? false)
|
||||
}
|
||||
|
||||
private var resource: Resource? {
|
||||
guard let channel = presentedChannel else { return nil }
|
||||
|
||||
let data = contentType != .videos ? channel.tabs.first(where: { $0.contentType == contentType })?.data : nil
|
||||
let resource = accounts.api.channel(channel.id, contentType: contentType, data: data)
|
||||
|
||||
if contentType == .videos {
|
||||
resource.addObserver(store)
|
||||
} else {
|
||||
resource.addObserver(contentTypeItems)
|
||||
}
|
||||
resource.addObserver(contentTypeItems)
|
||||
|
||||
return resource
|
||||
}
|
||||
@@ -418,6 +422,42 @@ struct ChannelVideosView: View {
|
||||
Label("Mark channel feed as unwatched", systemImage: "checkmark.circle")
|
||||
}
|
||||
}
|
||||
|
||||
func load() {
|
||||
resource?.load().onSuccess { response in
|
||||
if let page: ChannelPage = response.typedContent() {
|
||||
if let channel = page.channel {
|
||||
ChannelsCacheModel.shared.store(channel)
|
||||
}
|
||||
self.page = page
|
||||
self.contentTypeItems.replace(page.results)
|
||||
}
|
||||
}
|
||||
.onFailure { error in
|
||||
navigation.presentAlert(title: "Could not load channel data", message: error.userMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func loadNextPage() {
|
||||
guard let channel = presentedChannel, let pageToLoad = page, !pageToLoad.last else {
|
||||
return
|
||||
}
|
||||
|
||||
var next = pageToLoad.nextPage
|
||||
if contentType == .videos, !pageToLoad.last {
|
||||
next = next ?? ""
|
||||
}
|
||||
|
||||
let data = contentType != .videos ? channel.tabs.first(where: { $0.contentType == contentType })?.data : nil
|
||||
accounts.api.channel(channel.id, contentType: contentType, data: data, page: next).load().onSuccess { response in
|
||||
if let page: ChannelPage = response.typedContent() {
|
||||
self.page = page
|
||||
let keys = self.contentTypeItems.collection.map(\.cacheKey)
|
||||
let items = self.contentTypeItems.collection + page.results.filter { !keys.contains($0.cacheKey) }
|
||||
self.contentTypeItems.replace(items)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChannelVideosView_Previews: PreviewProvider {
|
||||
|
||||
@@ -51,6 +51,7 @@ extension Defaults.Keys {
|
||||
#if os(iOS)
|
||||
static let lockPortraitWhenBrowsing = Key<Bool>("lockPortraitWhenBrowsing", default: UIDevice.current.userInterfaceIdiom == .phone)
|
||||
#endif
|
||||
static let showUnwatchedFeedBadges = Key<Bool>("showUnwatchedFeedBadges", default: false)
|
||||
static let expandChannelDescription = Key<Bool>("expandChannelDescription", default: false)
|
||||
static let channelOnThumbnail = Key<Bool>("channelOnThumbnail", default: false)
|
||||
static let timeOnThumbnail = Key<Bool>("timeOnThumbnail", default: true)
|
||||
|
||||
@@ -74,9 +74,10 @@ struct FavoriteItemView: View {
|
||||
case let .channel(_, id, name):
|
||||
var channel = Channel(app: .invidious, id: id, name: name)
|
||||
if let cache = ChannelsCacheModel.shared.retrieve(channel.cacheKey),
|
||||
!cache.videos.isEmpty
|
||||
let cacheChannel = cache.channel,
|
||||
!cacheChannel.videos.isEmpty
|
||||
{
|
||||
contentItems = ContentItem.array(of: cache.videos)
|
||||
contentItems = ContentItem.array(of: cacheChannel.videos)
|
||||
}
|
||||
|
||||
onSuccess = { response in
|
||||
|
||||
@@ -8,6 +8,8 @@ struct AppSidebarSubscriptions: View {
|
||||
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
|
||||
@ObservedObject private var accounts = AccountsModel.shared
|
||||
|
||||
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
|
||||
|
||||
var body: some View {
|
||||
Section(header: Text("Subscriptions")) {
|
||||
ForEach(subscriptions.all) { channel in
|
||||
@@ -26,7 +28,7 @@ struct AppSidebarSubscriptions: View {
|
||||
Spacer()
|
||||
}
|
||||
.backport
|
||||
.badge(feedCount.unwatchedByChannelText(channel))
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil)
|
||||
}
|
||||
.contextMenu {
|
||||
if subscriptions.isSubscribing(channel.id) {
|
||||
|
||||
@@ -13,6 +13,7 @@ struct AppTabNavigation: View {
|
||||
@Default(.showDocuments) private var showDocuments
|
||||
@Default(.showOpenActionsToolbarItem) private var showOpenActionsToolbarItem
|
||||
@Default(.visibleSections) private var visibleSections
|
||||
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
|
||||
|
||||
let persistenceController = PersistenceController.shared
|
||||
|
||||
@@ -95,7 +96,7 @@ struct AppTabNavigation: View {
|
||||
}
|
||||
.tag(TabSelection.subscriptions)
|
||||
.backport
|
||||
.badge(feedCount.unwatchedText)
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedText : nil)
|
||||
}
|
||||
|
||||
private var subscriptionsVisible: Bool {
|
||||
|
||||
@@ -12,6 +12,7 @@ struct Sidebar: View {
|
||||
#if os(iOS)
|
||||
@Default(.showDocuments) private var showDocuments
|
||||
#endif
|
||||
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
|
||||
|
||||
var body: some View {
|
||||
ScrollViewReader { scrollView in
|
||||
@@ -79,7 +80,7 @@ struct Sidebar: View {
|
||||
.accessibility(label: Text("Subscriptions"))
|
||||
}
|
||||
.backport
|
||||
.badge(feedCount.unwatchedText)
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedText : nil)
|
||||
.contextMenu {
|
||||
playUnwatchedButton
|
||||
toggleWatchedButton
|
||||
|
||||
@@ -7,6 +7,7 @@ struct BrowsingSettings: View {
|
||||
@Default(.roundedThumbnails) private var roundedThumbnails
|
||||
#endif
|
||||
@Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts
|
||||
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
|
||||
#if os(iOS)
|
||||
@Default(.homeRecentDocumentsItems) private var homeRecentDocumentsItems
|
||||
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
|
||||
@@ -223,6 +224,12 @@ struct BrowsingSettings: View {
|
||||
#endif
|
||||
|
||||
Toggle("Show anonymous accounts", isOn: $accountPickerDisplaysAnonymousAccounts)
|
||||
Toggle("Show unwatched feed badges", isOn: $showUnwatchedFeedBadges)
|
||||
.onChange(of: showUnwatchedFeedBadges) { newValue in
|
||||
if newValue {
|
||||
FeedModel.shared.calculateUnwatchedFeed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Toggle("Open channels with description expanded", isOn: $expandChannelDescription)
|
||||
|
||||
@@ -243,7 +243,7 @@ struct SettingsView: View {
|
||||
private var windowHeight: Double {
|
||||
switch selection {
|
||||
case .browsing:
|
||||
return 820
|
||||
return 840
|
||||
case .player:
|
||||
return 450
|
||||
case .controls:
|
||||
|
||||
@@ -9,6 +9,7 @@ struct ChannelsView: View {
|
||||
@ObservedObject private var feedCount = UnwatchedFeedCountModel.shared
|
||||
|
||||
@Default(.showCacheStatus) private var showCacheStatus
|
||||
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
@@ -26,7 +27,7 @@ struct ChannelsView: View {
|
||||
}
|
||||
}
|
||||
.backport
|
||||
.badge(feedCount.unwatchedByChannelText(channel))
|
||||
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil)
|
||||
}
|
||||
.contextMenu {
|
||||
if subscriptions.isSubscribing(channel.id) {
|
||||
|
||||
@@ -21,27 +21,27 @@ struct ShareButton<LabelView: View>: View {
|
||||
|
||||
@ViewBuilder var body: some View {
|
||||
// TODO: this should work with other content item types
|
||||
Menu {
|
||||
if let video = contentItem.video,
|
||||
!video.localStreamIsFile
|
||||
{
|
||||
if video.localStreamIsRemoteURL {
|
||||
remoteURLAction
|
||||
} else {
|
||||
instanceActions
|
||||
Divider()
|
||||
if !accounts.isEmpty {
|
||||
youtubeActions
|
||||
if let video = contentItem.video {
|
||||
Menu {
|
||||
if !video.localStreamIsFile {
|
||||
if video.localStreamIsRemoteURL {
|
||||
remoteURLAction
|
||||
} else {
|
||||
instanceActions
|
||||
Divider()
|
||||
if !accounts.isEmpty {
|
||||
youtubeActions
|
||||
}
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
label
|
||||
}
|
||||
} label: {
|
||||
label
|
||||
.menuStyle(.borderlessButton)
|
||||
#if os(macOS)
|
||||
.frame(maxWidth: 60)
|
||||
#endif
|
||||
}
|
||||
.menuStyle(.borderlessButton)
|
||||
#if os(macOS)
|
||||
.frame(maxWidth: 60)
|
||||
#endif
|
||||
}
|
||||
|
||||
private var instanceActions: some View {
|
||||
|
||||
@@ -493,3 +493,12 @@
|
||||
"Share%@link" = "مشاركة الرابط %@";
|
||||
"Instance of current account" = "مثيل الحساب الحالي";
|
||||
"Seek gesture sensitivity" = "إطار حساسية الإيماءات";
|
||||
"Video" = "";
|
||||
"Audio" = "";
|
||||
"Honor orientation lock" = "";
|
||||
"Proxy videos" = "";
|
||||
"Seek gesture speed" = "";
|
||||
"Seek with horizontal swipe on video" = "";
|
||||
"System controls show buttons for %@" = "";
|
||||
"Wiki" = "";
|
||||
"Sample Rate" = "";
|
||||
|
||||
@@ -498,3 +498,7 @@
|
||||
"Default Profile" = "Výchozí profil";
|
||||
"Copy%@link" = "Zkopírovat%@odkaz";
|
||||
"Share%@link" = "Sdílet%@odkaz";
|
||||
"Verified" = "";
|
||||
"Shorts" = "";
|
||||
"Channel" = "";
|
||||
"Live Streams" = "";
|
||||
|
||||
@@ -124,3 +124,381 @@
|
||||
"Browsing" = "Navegando por";
|
||||
"Buffering stream..." = "Cargando flujo de datos...";
|
||||
"Cellular" = "Celular";
|
||||
"Save" = "";
|
||||
"Search history is empty" = "";
|
||||
"Address" = "";
|
||||
"Could not refresh Subscriptions" = "";
|
||||
"You can use automatic profile selection based on current device status or switch it in video playback settings controls." = "";
|
||||
"URL to Open" = "";
|
||||
"Could not delete document" = "";
|
||||
"Show Favorites" = "";
|
||||
"Current Location" = "";
|
||||
"Show Home" = "";
|
||||
"Are you sure you want to remove this document?" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Today" = "";
|
||||
"Opening audio stream..." = "";
|
||||
"Open Video" = "";
|
||||
"I want to ask a question" = "";
|
||||
"Save history of played videos" = "";
|
||||
"Promoting a product or service that is directly related to the creator themselves. This usually includes merchandise or promotion of monetized platforms." = "";
|
||||
"Show only icons" = "";
|
||||
"FPS" = "";
|
||||
"Enter links to open, one per line" = "";
|
||||
"Sample Rate" = "";
|
||||
"Playback Mode" = "";
|
||||
"Channels" = "";
|
||||
"For custom locations you can configure Frontend URL in Locations settings" = "";
|
||||
"Cached time" = "";
|
||||
"Could not find any links to open in your clipboard" = "";
|
||||
"Orientation" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Offtopic in Music Videos" = "";
|
||||
"Public Manifest" = "";
|
||||
"This will remove all your custom profiles and return their default values. This cannot be reverted." = "";
|
||||
"Left" = "";
|
||||
"Video Details" = "";
|
||||
"Only for local files and URLs" = "";
|
||||
"\"%@\" will be irreversibly removed from this device." = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Small" = "";
|
||||
"Now Playing" = "";
|
||||
"Stream & Player" = "";
|
||||
"Picture in Picture" = "";
|
||||
"Visibility" = "";
|
||||
"Edit Favorites…" = "";
|
||||
"Center" = "";
|
||||
"Wiki" = "";
|
||||
"Live Streams" = "";
|
||||
"Make default" = "";
|
||||
"Dropped frames" = "";
|
||||
"Show icons and text when space permits" = "";
|
||||
"Hardware decoder" = "";
|
||||
"Show Open Videos quick actions" = "";
|
||||
"Upload date" = "";
|
||||
"Home" = "";
|
||||
"Switch to public locations" = "";
|
||||
"Verified" = "";
|
||||
"History" = "";
|
||||
"Locations Manifest" = "";
|
||||
"Playlist is empty\n\nTap and hold on a video and then \n\"Add to Playlist\"" = "";
|
||||
"Play Now" = "";
|
||||
"Enter link to open" = "";
|
||||
"Share..." = "";
|
||||
"Restore default profiles..." = "";
|
||||
"Round corners" = "";
|
||||
"SponsorBlock" = "";
|
||||
"Statistics" = "";
|
||||
"Matrix Channel" = "";
|
||||
"More info can be found in:" = "";
|
||||
"Resolution" = "";
|
||||
"Open Videos" = "";
|
||||
"Show progress of watching on thumbnails" = "";
|
||||
"Medium quality" = "";
|
||||
"Welcome" = "";
|
||||
"Could not open Files" = "";
|
||||
"Add Channels, Playlists and Searches to Favorites using" = "";
|
||||
"Restart" = "";
|
||||
"Shorts" = "";
|
||||
"Not available" = "";
|
||||
"Pages buttons" = "";
|
||||
"No documents" = "";
|
||||
|
||||
/* Loading stream OSD */
|
||||
"Opening %@ stream..." = "";
|
||||
"Documents" = "";
|
||||
"Thumbnails" = "";
|
||||
"Password" = "";
|
||||
"Show playback statistics" = "";
|
||||
"Remove Location" = "";
|
||||
"Inspector visibility" = "";
|
||||
"Open \"Playlists\" tab to create new one" = "";
|
||||
"Show Inspector" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Week" = "";
|
||||
"Recent Documents" = "";
|
||||
"Segments typically found at the start of a video that include an animation, still frame or clip which are also seen in other videos by the same creator." = "";
|
||||
"Restart the app to apply the settings above." = "";
|
||||
"Show sidebar when space permits" = "";
|
||||
"Share %@ link with time" = "";
|
||||
"Rate & Captions" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Outro" = "";
|
||||
"Always" = "";
|
||||
"Show anonymous accounts" = "";
|
||||
"Play in PiP" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Sponsor" = "";
|
||||
"Rate" = "";
|
||||
"Reload manifest" = "";
|
||||
"Playback queue is empty" = "";
|
||||
"Videos" = "";
|
||||
|
||||
/* Selected video was played on given date */
|
||||
"Watched %@" = "";
|
||||
"You have no playlists\n\nTap on \"New Playlist\" to create one" = "";
|
||||
"I like this app!" = "";
|
||||
|
||||
/* Video sort order in search */
|
||||
"Rating" = "";
|
||||
"Actions buttons" = "";
|
||||
"Files" = "";
|
||||
"Sign In Required" = "";
|
||||
"Buttons labels" = "";
|
||||
"Next" = "";
|
||||
"Default Profile" = "";
|
||||
"Paste" = "";
|
||||
"Regular Size" = "";
|
||||
"File" = "";
|
||||
"Right" = "";
|
||||
"Reset search filters" = "";
|
||||
"Channel" = "";
|
||||
"Open Files" = "";
|
||||
"You can find information about using Yattee in the Wiki pages." = "";
|
||||
"Lock portrait mode" = "";
|
||||
"Shuffle" = "";
|
||||
|
||||
/* Loading stream OSD */
|
||||
"Loading streams..." = "";
|
||||
"Public Locations" = "";
|
||||
"Yattee" = "";
|
||||
"No results" = "";
|
||||
"Driver" = "";
|
||||
"Remove from history" = "";
|
||||
"Red" = "";
|
||||
"Are you sure you want to remove %@ location?" = "";
|
||||
"Share" = "";
|
||||
"Share %@ link" = "";
|
||||
"Reset watched status when playing again" = "";
|
||||
"Show sidebar" = "";
|
||||
"You need to create an instance and accounts\nto access %@ section" = "";
|
||||
"Refresh" = "";
|
||||
"I am lost" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Medium" = "";
|
||||
"Typically near or at the end of the video when the credits pop up and/or endcards are shown." = "";
|
||||
"This information will be processed only on your device and used to connect you to the server in the specified country." = "";
|
||||
"Part of a video promoting a product or service not directly related to the creator. The creator will receive payment or compensation in the form of money or free products." = "";
|
||||
"You have no Playlists" = "";
|
||||
"System controls show buttons for %@" = "";
|
||||
"No chapters information available" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Month" = "";
|
||||
"Shuffle All" = "";
|
||||
"Large layout is not suitable for all devices and using it may cause controls not to fit on the screen." = "";
|
||||
"Music" = "";
|
||||
"Name" = "";
|
||||
"New Playlist" = "";
|
||||
"Quality Profile" = "";
|
||||
"Queue" = "";
|
||||
"You can switch between profiles in playback settings controls." = "";
|
||||
"Could not load streams" = "";
|
||||
"Settings" = "";
|
||||
"Show history" = "";
|
||||
"unknown" = "";
|
||||
"%@ formats" = "";
|
||||
"Quality" = "";
|
||||
"Any format" = "";
|
||||
"Honor orientation lock" = "";
|
||||
"I found a bug /" = "";
|
||||
"I have a feature request" = "";
|
||||
"LIVE" = "";
|
||||
|
||||
/* Video duration filter in search */
|
||||
"Long" = "";
|
||||
"Low quality" = "";
|
||||
"Lowest" = "";
|
||||
"Movies" = "";
|
||||
"MPV Documentation" = "";
|
||||
"Pause when entering background" = "";
|
||||
"Pause when player is closed" = "";
|
||||
"Play" = "";
|
||||
"Play All" = "";
|
||||
"Preferred Formats" = "";
|
||||
"Profiles" = "";
|
||||
"Queue is empty" = "";
|
||||
"Recents" = "";
|
||||
"Remove from Playlist" = "";
|
||||
"Remove from the queue" = "";
|
||||
"Replies" = "";
|
||||
"Reset" = "";
|
||||
"Save history of searches, channels and playlists" = "";
|
||||
"Search" = "";
|
||||
"Seek gesture sensitivity" = "";
|
||||
"Select location closest to you:" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Self-promotion" = "";
|
||||
"Show keywords" = "";
|
||||
"Show channel name" = "";
|
||||
"Show video length" = "";
|
||||
"Sort" = "";
|
||||
"Sort: %@" = "";
|
||||
"Trending" = "";
|
||||
|
||||
/* Player controls layout size for TV */
|
||||
"TV" = "";
|
||||
"You need to select an account\nto access %@ section" = "";
|
||||
"Unlisted" = "";
|
||||
"Could not open playlist" = "";
|
||||
"Could not extract video ID" = "";
|
||||
"Highest" = "";
|
||||
"Highest quality" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Hour" = "";
|
||||
"If you are interested what's coming in future updates, you can track project Milestones." = "";
|
||||
"If you are reporting a bug, include all relevant details (especially: app version, used device and system version, steps to reproduce)." = "";
|
||||
"Info" = "";
|
||||
"Instance of current account" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Interaction" = "";
|
||||
"Interface" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Intro" = "";
|
||||
"Issues Tracker" = "";
|
||||
|
||||
/* Selected video has just finished playing */
|
||||
"Just watched" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Large" = "";
|
||||
"Loading..." = "";
|
||||
"Locations" = "";
|
||||
"Low" = "";
|
||||
"Mark as watched" = "";
|
||||
"Mark video as watched after playing" = "";
|
||||
"Mark watched videos with" = "";
|
||||
"Matrix Chat" = "";
|
||||
"Milestones" = "";
|
||||
"No description" = "";
|
||||
"No Playlists" = "";
|
||||
"Not Playing" = "";
|
||||
"Normal" = "";
|
||||
"Nothing" = "";
|
||||
"Only when signed in" = "";
|
||||
"Open Settings" = "";
|
||||
"Player" = "";
|
||||
"Pause" = "";
|
||||
"Play Last" = "";
|
||||
"Play Music" = "";
|
||||
"Play Next" = "";
|
||||
"Playlist" = "";
|
||||
"Playlist \"%@\" will be deleted.\nIt cannot be reverted." = "";
|
||||
"Playlists" = "";
|
||||
"Popular" = "";
|
||||
"Proxy videos" = "";
|
||||
"Regular size" = "";
|
||||
"Related" = "";
|
||||
|
||||
/* Video sort order in search */
|
||||
"Relevance" = "";
|
||||
"Remove" = "";
|
||||
"Remove from Favorites" = "";
|
||||
"Rotate to portrait when exiting fullscreen" = "";
|
||||
"Search..." = "";
|
||||
"Sections" = "";
|
||||
"Seek gesture speed" = "";
|
||||
"Seek with horizontal swipe on video" = "";
|
||||
|
||||
/* Video duration filter in search */
|
||||
"Short" = "";
|
||||
"Show account username" = "";
|
||||
"Sidebar" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Smaller" = "";
|
||||
"Source" = "";
|
||||
"SponsorBlock API Instance" = "";
|
||||
"Subscribe" = "";
|
||||
|
||||
/* Subscriptions title */
|
||||
"Subscriptions" = "";
|
||||
"Switch to other public location" = "";
|
||||
"System controls buttons" = "";
|
||||
"That's nice to hear. It is fun to deliver apps other people want to use. You can consider donating to the project or help by contributing to new features development." = "";
|
||||
"Unsubscribe" = "";
|
||||
"URL" = "";
|
||||
"Used to create links from videos, channels and playlists" = "";
|
||||
"Username" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Very Large" = "";
|
||||
|
||||
/* Video sort order in search */
|
||||
"Views" = "";
|
||||
"Watched" = "";
|
||||
"When partially watched video is played" = "";
|
||||
"Wi-Fi" = "";
|
||||
"Yattee %@ (build %@)" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Year" = "";
|
||||
|
||||
|
||||
"Public" = "";
|
||||
"Private" = "";
|
||||
"Playing Next" = "";
|
||||
"Current Playlist" = "";
|
||||
"Stream FPS" = "";
|
||||
"Keep last played video in the queue after restart" = "";
|
||||
"It can be changed later in settings. You can use your own locations too." = "";
|
||||
"Press and hold remote button to open captions and quality menus" = "";
|
||||
"Comments are disabled" = "";
|
||||
"No comments" = "";
|
||||
"Share Logs..." = "";
|
||||
"Open logs in Finder" = "";
|
||||
"Could not open video" = "";
|
||||
"Channel could not be found" = "";
|
||||
"Could not extract channel information" = "";
|
||||
"Could not extract SID from received cookies: %@" = "";
|
||||
"Could not update your token." = "";
|
||||
"Could not refresh Trending" = "";
|
||||
"This URL could not be opened" = "";
|
||||
"Could not refresh Popular" = "";
|
||||
"Could not create share link" = "";
|
||||
"This video could not be opened" = "";
|
||||
"No locations available at the moment" = "";
|
||||
"Could not refresh Playlists" = "";
|
||||
|
||||
/* Selected video is being played */
|
||||
"Watching now" = "";
|
||||
"If you want this app to be available in your language, join translation project." = "";
|
||||
"Translations" = "";
|
||||
"Increase rate" = "";
|
||||
"Could not extract playlist ID" = "";
|
||||
"Could not load video" = "";
|
||||
"Playback" = "";
|
||||
"Restart/Play next" = "";
|
||||
"This cannot be reverted" = "";
|
||||
"This cannot be reverted. You might need to switch between views or restart the app to see changes." = "";
|
||||
"Could not open channel" = "";
|
||||
"Recent History" = "";
|
||||
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
|
||||
"Pages toolbar position" = "";
|
||||
"Video actions buttons" = "";
|
||||
"Video" = "";
|
||||
"Show Open Videos toolbar button" = "";
|
||||
"Show Documents" = "";
|
||||
"Clear Queue before opening" = "";
|
||||
"Open" = "";
|
||||
"Add" = "";
|
||||
"Hide" = "";
|
||||
"Format" = "";
|
||||
"Audio" = "";
|
||||
"Codec" = "";
|
||||
"Size" = "";
|
||||
"Remove…" = "";
|
||||
"Playback history is empty" = "";
|
||||
"Copy%@link" = "";
|
||||
"Share%@link" = "";
|
||||
|
||||
@@ -462,3 +462,43 @@
|
||||
"Playback Mode" = "Mode Playback";
|
||||
"Add" = "Ajouter";
|
||||
"Hide" = "Cacher";
|
||||
"Size" = "";
|
||||
"Address" = "";
|
||||
"Could not delete document" = "";
|
||||
"Could not find any links to open in your clipboard" = "";
|
||||
"Center" = "";
|
||||
"Locations Manifest" = "";
|
||||
"Actions buttons" = "";
|
||||
"Sample Rate" = "";
|
||||
"FPS" = "";
|
||||
"Remove…" = "";
|
||||
"Live Streams" = "";
|
||||
"\"%@\" will be irreversibly removed from this device." = "";
|
||||
"Remove Location" = "";
|
||||
"Open Video" = "";
|
||||
"Video actions buttons" = "";
|
||||
"Documents" = "";
|
||||
"Show Open Videos toolbar button" = "";
|
||||
"File" = "";
|
||||
"Are you sure you want to remove this document?" = "";
|
||||
"Left" = "";
|
||||
"Shorts" = "";
|
||||
"Copy%@link" = "";
|
||||
"Verified" = "";
|
||||
"Show sidebar" = "";
|
||||
"Driver" = "";
|
||||
"Show Open Videos quick actions" = "";
|
||||
"Format" = "";
|
||||
"Are you sure you want to remove %@ location?" = "";
|
||||
"Show only icons" = "";
|
||||
"Audio" = "";
|
||||
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
|
||||
"Channel" = "";
|
||||
"Inspector visibility" = "";
|
||||
"Video" = "";
|
||||
"Right" = "";
|
||||
"Show icons and text when space permits" = "";
|
||||
"Codec" = "";
|
||||
"Default Profile" = "";
|
||||
"Playback history is empty" = "";
|
||||
"Share%@link" = "";
|
||||
|
||||
@@ -407,3 +407,98 @@
|
||||
"No comments" = "कोई टिप्पणी नहीं";
|
||||
"No chapters information available" = "कोई अध्याय जानकारी उपलब्ध नहीं";
|
||||
"Comments are disabled" = "टिप्पणियाँ अक्षम हैं";
|
||||
"Open Video" = "";
|
||||
"Reload manifest" = "";
|
||||
"Pages buttons" = "";
|
||||
"Open Files" = "";
|
||||
"Channels" = "";
|
||||
"Locations Manifest" = "";
|
||||
"Could not delete document" = "";
|
||||
"Show Inspector" = "";
|
||||
"Could not load streams" = "";
|
||||
"Address" = "";
|
||||
"Playback Mode" = "";
|
||||
"Left" = "";
|
||||
"Show icons and text when space permits" = "";
|
||||
"FPS" = "";
|
||||
"Buttons labels" = "";
|
||||
"Remove…" = "";
|
||||
"Driver" = "";
|
||||
"Show only icons" = "";
|
||||
"Could not load video" = "";
|
||||
"Are you sure you want to remove this document?" = "";
|
||||
"Hide" = "";
|
||||
"\"%@\" will be irreversibly removed from this device." = "";
|
||||
"Could not open Files" = "";
|
||||
"Video Details" = "";
|
||||
"Open" = "";
|
||||
"Open Videos" = "";
|
||||
"Show Documents" = "";
|
||||
"Inspector visibility" = "";
|
||||
"Add" = "";
|
||||
"Show Favorites" = "";
|
||||
"Clear Queue before opening" = "";
|
||||
"If you want this app to be available in your language, join translation project." = "";
|
||||
"Documents" = "";
|
||||
"Playback history is empty" = "";
|
||||
"Show sidebar" = "";
|
||||
"Live Streams" = "";
|
||||
"Enter links to open, one per line" = "";
|
||||
"Verified" = "";
|
||||
"No documents" = "";
|
||||
"Show Open Videos toolbar button" = "";
|
||||
"Could not refresh Subscriptions" = "";
|
||||
"Remove Location" = "";
|
||||
"Only for local files and URLs" = "";
|
||||
"Codec" = "";
|
||||
"File" = "";
|
||||
"Could not extract playlist ID" = "";
|
||||
"Paste" = "";
|
||||
"Could not extract SID from received cookies: %@" = "";
|
||||
"Files" = "";
|
||||
"Show Home" = "";
|
||||
"Could not extract channel information" = "";
|
||||
"Enter link to open" = "";
|
||||
"Home" = "";
|
||||
"No locations available at the moment" = "";
|
||||
"Could not find any links to open in your clipboard" = "";
|
||||
"Audio" = "";
|
||||
"Actions buttons" = "";
|
||||
"Share" = "";
|
||||
"Always" = "";
|
||||
"Format" = "";
|
||||
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
|
||||
"Share%@link" = "";
|
||||
"Could not open video" = "";
|
||||
"Center" = "";
|
||||
"Size" = "";
|
||||
"Recent Documents" = "";
|
||||
"This video could not be opened" = "";
|
||||
"Video" = "";
|
||||
"URL to Open" = "";
|
||||
"Edit Favorites…" = "";
|
||||
"Video actions buttons" = "";
|
||||
"Right" = "";
|
||||
"Shorts" = "";
|
||||
"For custom locations you can configure Frontend URL in Locations settings" = "";
|
||||
"Could not create share link" = "";
|
||||
"Sample Rate" = "";
|
||||
"Translations" = "";
|
||||
"Open logs in Finder" = "";
|
||||
"Could not refresh Playlists" = "";
|
||||
"Could not update your token." = "";
|
||||
"Could not refresh Trending" = "";
|
||||
"Could not open playlist" = "";
|
||||
"This URL could not be opened" = "";
|
||||
"Could not open channel" = "";
|
||||
"Channel could not be found" = "";
|
||||
"Could not refresh Popular" = "";
|
||||
"Could not extract video ID" = "";
|
||||
"Channel" = "";
|
||||
"Are you sure you want to remove %@ location?" = "";
|
||||
"Recent History" = "";
|
||||
"Show Open Videos quick actions" = "";
|
||||
"Pages toolbar position" = "";
|
||||
"Default Profile" = "";
|
||||
"Copy%@link" = "";
|
||||
"Share Logs..." = "";
|
||||
|
||||
@@ -405,3 +405,98 @@
|
||||
"No chapters information available" = "Ingen tilgjengelig kapittelinfo";
|
||||
"Comments are disabled" = "Kommentarer er avskrudd";
|
||||
"Press and hold remote button to open captions and quality menus" = "Trykk og hold fjernknappen for å åpne meny for undertekster og kvalitet";
|
||||
"Paste" = "";
|
||||
"Codec" = "";
|
||||
"Open Videos" = "";
|
||||
"Files" = "";
|
||||
"Open Video" = "";
|
||||
"Show only icons" = "";
|
||||
"Show Open Videos toolbar button" = "";
|
||||
"Channels" = "";
|
||||
"Buttons labels" = "";
|
||||
"Could not open Files" = "";
|
||||
"Reload manifest" = "";
|
||||
"Right" = "";
|
||||
"Show Favorites" = "";
|
||||
"Only for local files and URLs" = "";
|
||||
"Enter link to open" = "";
|
||||
"Left" = "";
|
||||
"Are you sure you want to remove this document?" = "";
|
||||
"Recent Documents" = "";
|
||||
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
|
||||
"Address" = "";
|
||||
"File" = "";
|
||||
"Share" = "";
|
||||
"Could not delete document" = "";
|
||||
"Are you sure you want to remove %@ location?" = "";
|
||||
"Size" = "";
|
||||
"Always" = "";
|
||||
"Video actions buttons" = "";
|
||||
"Edit Favorites…" = "";
|
||||
"Sample Rate" = "";
|
||||
"Show Inspector" = "";
|
||||
"Remove Location" = "";
|
||||
"Format" = "";
|
||||
"Verified" = "";
|
||||
"Show icons and text when space permits" = "";
|
||||
"Could not extract video ID" = "";
|
||||
"Open Files" = "";
|
||||
"Driver" = "";
|
||||
"Show Open Videos quick actions" = "";
|
||||
"Enter links to open, one per line" = "";
|
||||
"No locations available at the moment" = "";
|
||||
"Video Details" = "";
|
||||
"Add" = "";
|
||||
"Show Home" = "";
|
||||
"Pages buttons" = "";
|
||||
"Center" = "";
|
||||
"Shorts" = "";
|
||||
"Open" = "";
|
||||
"Locations Manifest" = "";
|
||||
"FPS" = "";
|
||||
"Inspector visibility" = "";
|
||||
"Show Documents" = "";
|
||||
"Open logs in Finder" = "";
|
||||
"Documents" = "";
|
||||
"Could not update your token." = "";
|
||||
"Remove…" = "";
|
||||
"Hide" = "";
|
||||
"Actions buttons" = "";
|
||||
"Audio" = "";
|
||||
"Could not extract SID from received cookies: %@" = "";
|
||||
"Playback Mode" = "";
|
||||
"Clear Queue before opening" = "";
|
||||
"Could not create share link" = "";
|
||||
"Could not refresh Playlists" = "";
|
||||
"Could not refresh Subscriptions" = "";
|
||||
"Translations" = "";
|
||||
"This URL could not be opened" = "";
|
||||
"For custom locations you can configure Frontend URL in Locations settings" = "";
|
||||
"Could not refresh Trending" = "";
|
||||
"If you want this app to be available in your language, join translation project." = "";
|
||||
"This video could not be opened" = "";
|
||||
"Could not open channel" = "";
|
||||
"Could not open playlist" = "";
|
||||
"Could not load streams" = "";
|
||||
"Could not open video" = "";
|
||||
"Could not extract channel information" = "";
|
||||
"Could not load video" = "";
|
||||
"Could not extract playlist ID" = "";
|
||||
"Could not refresh Popular" = "";
|
||||
"Channel could not be found" = "";
|
||||
"Live Streams" = "";
|
||||
"Channel" = "";
|
||||
"No documents" = "";
|
||||
"\"%@\" will be irreversibly removed from this device." = "";
|
||||
"Recent History" = "";
|
||||
"Home" = "";
|
||||
"Pages toolbar position" = "";
|
||||
"URL to Open" = "";
|
||||
"Video" = "";
|
||||
"Could not find any links to open in your clipboard" = "";
|
||||
"Show sidebar" = "";
|
||||
"Default Profile" = "";
|
||||
"Playback history is empty" = "";
|
||||
"Copy%@link" = "";
|
||||
"Share%@link" = "";
|
||||
"Share Logs..." = "";
|
||||
|
||||
@@ -111,3 +111,394 @@
|
||||
"Find Other" = "Letar annat";
|
||||
"Finding something to play..." = "Letar något att spela...";
|
||||
"10 seconds forwards/backwards" = "10 sekunder framåt/bakåt";
|
||||
"Low" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Large" = "";
|
||||
"Interface" = "";
|
||||
"Increase rate" = "";
|
||||
"If you are reporting a bug, include all relevant details (especially: app version, used device and system version, steps to reproduce)." = "";
|
||||
"Playlist \"%@\" will be deleted.\nIt cannot be reverted." = "";
|
||||
"You need to select an account\nto access %@ section" = "";
|
||||
"Playlists" = "";
|
||||
|
||||
/* Video date filter in search
|
||||
Video duration filter in search */
|
||||
"Any" = "";
|
||||
"Password" = "";
|
||||
"Play All" = "";
|
||||
"That's nice to hear. It is fun to deliver apps other people want to use. You can consider donating to the project or help by contributing to new features development." = "";
|
||||
"Quality Profile" = "";
|
||||
"Popular" = "";
|
||||
"Promoting a product or service that is directly related to the creator themselves. This usually includes merchandise or promotion of monetized platforms." = "";
|
||||
"Now Playing" = "";
|
||||
|
||||
/* Loading stream OSD */
|
||||
"Loading streams..." = "";
|
||||
"Typically near or at the end of the video when the credits pop up and/or endcards are shown." = "";
|
||||
"Picture in Picture" = "";
|
||||
"Playlist" = "";
|
||||
"Queue is empty" = "";
|
||||
"Search history is empty" = "";
|
||||
"Pause" = "";
|
||||
"LIVE" = "";
|
||||
"Play Next" = "";
|
||||
"Play Music" = "";
|
||||
"Channels" = "";
|
||||
"Show icons and text when space permits" = "";
|
||||
"Instance of current account" = "";
|
||||
"You can find information about using Yattee in the Wiki pages." = "";
|
||||
"Driver" = "";
|
||||
|
||||
/* Selected video has just finished playing */
|
||||
"Just watched" = "";
|
||||
"Preferred Formats" = "";
|
||||
"Play in PiP" = "";
|
||||
"Pause when entering background" = "";
|
||||
"You need to create an instance and accounts\nto access %@ section" = "";
|
||||
"This information will be processed only on your device and used to connect you to the server in the specified country." = "";
|
||||
"Are you sure you want to remove %@ location?" = "";
|
||||
"Trending" = "";
|
||||
"Regular Size" = "";
|
||||
"Public Manifest" = "";
|
||||
"Player" = "";
|
||||
"Info" = "";
|
||||
"Sort" = "";
|
||||
"Unlisted" = "";
|
||||
"System controls buttons" = "";
|
||||
"Show Open Videos quick actions" = "";
|
||||
"Orientation" = "";
|
||||
"Not Playing" = "";
|
||||
"Restore default profiles..." = "";
|
||||
"More info can be found in:" = "";
|
||||
"Rate" = "";
|
||||
"Restart the app to apply the settings above." = "";
|
||||
|
||||
/* Player controls layout size for TV */
|
||||
"TV" = "";
|
||||
"Recent History" = "";
|
||||
"Remove from Favorites" = "";
|
||||
"No documents" = "";
|
||||
"Play Last" = "";
|
||||
"Documents" = "";
|
||||
"Could not load video" = "";
|
||||
"Could not open playlist" = "";
|
||||
"System controls show buttons for %@" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Intro" = "";
|
||||
"Next" = "";
|
||||
"Sort: %@" = "";
|
||||
"Locations" = "";
|
||||
"Could not extract video ID" = "";
|
||||
"Unsubscribe" = "";
|
||||
"Nothing" = "";
|
||||
"File" = "";
|
||||
"Restart" = "";
|
||||
"You have no Playlists" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Hour" = "";
|
||||
"Playback history is empty" = "";
|
||||
"Refresh" = "";
|
||||
"For custom locations you can configure Frontend URL in Locations settings" = "";
|
||||
"Remove" = "";
|
||||
"Default Profile" = "";
|
||||
"Buttons labels" = "";
|
||||
"Public Locations" = "";
|
||||
"I like this app!" = "";
|
||||
"Current Location" = "";
|
||||
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
|
||||
"Could not delete document" = "";
|
||||
"Video actions buttons" = "";
|
||||
"Show anonymous accounts" = "";
|
||||
"Show Documents" = "";
|
||||
"Center" = "";
|
||||
"Not available" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Offtopic in Music Videos" = "";
|
||||
"SponsorBlock API Instance" = "";
|
||||
"Remove Location" = "";
|
||||
"Resolution" = "";
|
||||
"Show Inspector" = "";
|
||||
"Low quality" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Outro" = "";
|
||||
"Lock portrait mode" = "";
|
||||
"Issues Tracker" = "";
|
||||
"Copy%@link" = "";
|
||||
"Switch to public locations" = "";
|
||||
"Private" = "";
|
||||
"Backend" = "";
|
||||
"For videos which feature music as the primary content." = "";
|
||||
"Formats will be selected in order as listed.\nHLS is an adaptive format (resolution setting does not apply)." = "";
|
||||
"Frontend URL" = "";
|
||||
"Fullscreen size" = "";
|
||||
"Gaming" = "";
|
||||
"Help" = "";
|
||||
"Hide sidebar" = "";
|
||||
"High" = "";
|
||||
"Highest" = "";
|
||||
"Highest quality" = "";
|
||||
"History" = "";
|
||||
"Honor orientation lock" = "";
|
||||
"I am lost" = "";
|
||||
"I found a bug /" = "";
|
||||
"I have a feature request" = "";
|
||||
"I want to ask a question" = "";
|
||||
"If you are interested what's coming in future updates, you can track project Milestones." = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Interaction" = "";
|
||||
"Large layout is not suitable for all devices and using it may cause controls not to fit on the screen." = "";
|
||||
"Loading..." = "";
|
||||
|
||||
/* Video duration filter in search */
|
||||
"Long" = "";
|
||||
"Lowest" = "";
|
||||
"Mark as watched" = "";
|
||||
"Mark video as watched after playing" = "";
|
||||
"Mark watched videos with" = "";
|
||||
"Matrix Channel" = "";
|
||||
"Matrix Chat" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Medium" = "";
|
||||
"Medium quality" = "";
|
||||
"Milestones" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Month" = "";
|
||||
"Movies" = "";
|
||||
"MPV Documentation" = "";
|
||||
"Music" = "";
|
||||
"Name" = "";
|
||||
"New Playlist" = "";
|
||||
"No description" = "";
|
||||
"No Playlists" = "";
|
||||
"No results" = "";
|
||||
"Normal" = "";
|
||||
"Only when signed in" = "";
|
||||
"Open \"Playlists\" tab to create new one" = "";
|
||||
"Open Settings" = "";
|
||||
|
||||
/* Loading stream OSD */
|
||||
"Opening %@ stream..." = "";
|
||||
"Opening audio stream..." = "";
|
||||
"Part of a video promoting a product or service not directly related to the creator. The creator will receive payment or compensation in the form of money or free products." = "";
|
||||
"Pause when player is closed" = "";
|
||||
"Play" = "";
|
||||
"Play Now" = "";
|
||||
"Playback" = "";
|
||||
"Profiles" = "";
|
||||
"Proxy videos" = "";
|
||||
"Quality" = "";
|
||||
"Queue" = "";
|
||||
|
||||
/* Video sort order in search */
|
||||
"Rating" = "";
|
||||
"Recents" = "";
|
||||
"Red" = "";
|
||||
"Regular size" = "";
|
||||
"Related" = "";
|
||||
|
||||
/* Video sort order in search */
|
||||
"Relevance" = "";
|
||||
"Remove from history" = "";
|
||||
"Remove from Playlist" = "";
|
||||
"Remove from the queue" = "";
|
||||
"Replies" = "";
|
||||
"Reset" = "";
|
||||
"Reset search filters" = "";
|
||||
"Reset watched status when playing again" = "";
|
||||
"Restart/Play next" = "";
|
||||
"Rotate to portrait when exiting fullscreen" = "";
|
||||
"Round corners" = "";
|
||||
"Save history of played videos" = "";
|
||||
"Save history of searches, channels and playlists" = "";
|
||||
"Search" = "";
|
||||
"Search..." = "";
|
||||
"Sections" = "";
|
||||
"Save" = "";
|
||||
"Seek gesture speed" = "";
|
||||
"Seek gesture sensitivity" = "";
|
||||
"Seek with horizontal swipe on video" = "";
|
||||
"Segments typically found at the start of a video that include an animation, still frame or clip which are also seen in other videos by the same creator." = "";
|
||||
"Select location closest to you:" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Self-promotion" = "";
|
||||
"Settings" = "";
|
||||
"Share %@ link" = "";
|
||||
"Share %@ link with time" = "";
|
||||
"Share..." = "";
|
||||
|
||||
/* Video duration filter in search */
|
||||
"Short" = "";
|
||||
"Show account username" = "";
|
||||
"Show channel name" = "";
|
||||
"Show history" = "";
|
||||
"Show keywords" = "";
|
||||
"Show playback statistics" = "";
|
||||
"Show progress of watching on thumbnails" = "";
|
||||
"Show sidebar when space permits" = "";
|
||||
"Show video length" = "";
|
||||
"Shuffle" = "";
|
||||
"Shuffle All" = "";
|
||||
"Sidebar" = "";
|
||||
"Sign In Required" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Small" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Smaller" = "";
|
||||
"Source" = "";
|
||||
"SponsorBlock" = "";
|
||||
"Subscribe" = "";
|
||||
|
||||
/* Subscriptions title */
|
||||
"Subscriptions" = "";
|
||||
"Switch to other public location" = "";
|
||||
"This cannot be reverted" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Sponsor" = "";
|
||||
"This cannot be reverted. You might need to switch between views or restart the app to see changes." = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Today" = "";
|
||||
"This will remove all your custom profiles and return their default values. This cannot be reverted." = "";
|
||||
"Thumbnails" = "";
|
||||
"unknown" = "";
|
||||
"Upload date" = "";
|
||||
"URL" = "";
|
||||
"Used to create links from videos, channels and playlists" = "";
|
||||
"Username" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Very Large" = "";
|
||||
"Videos" = "";
|
||||
|
||||
/* Video sort order in search */
|
||||
"Views" = "";
|
||||
"Watched" = "";
|
||||
|
||||
/* Selected video was played on given date */
|
||||
"Watched %@" = "";
|
||||
|
||||
/* Selected video is being played */
|
||||
"Watching now" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Week" = "";
|
||||
"Welcome" = "";
|
||||
"When partially watched video is played" = "";
|
||||
"Wi-Fi" = "";
|
||||
"Wiki" = "";
|
||||
"Yattee" = "";
|
||||
"Yattee %@ (build %@)" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Year" = "";
|
||||
"You can use automatic profile selection based on current device status or switch it in video playback settings controls." = "";
|
||||
"You have no playlists\n\nTap on \"New Playlist\" to create one" = "";
|
||||
|
||||
|
||||
"Public" = "";
|
||||
"Playback queue is empty" = "";
|
||||
"Playing Next" = "";
|
||||
"You can switch between profiles in playback settings controls." = "";
|
||||
"Add Channels, Playlists and Searches to Favorites using" = "";
|
||||
"Make default" = "";
|
||||
"Visibility" = "";
|
||||
"Current Playlist" = "";
|
||||
"Stream & Player" = "";
|
||||
"Statistics" = "";
|
||||
"Hardware decoder" = "";
|
||||
"Stream FPS" = "";
|
||||
"Cached time" = "";
|
||||
"Rate & Captions" = "";
|
||||
"Dropped frames" = "";
|
||||
"Any format" = "";
|
||||
"%@ formats" = "";
|
||||
"Keep last played video in the queue after restart" = "";
|
||||
"Playlist is empty\n\nTap and hold on a video and then \n\"Add to Playlist\"" = "";
|
||||
"It can be changed later in settings. You can use your own locations too." = "";
|
||||
"Press and hold remote button to open captions and quality menus" = "";
|
||||
"Comments are disabled" = "";
|
||||
"No comments" = "";
|
||||
"No chapters information available" = "";
|
||||
"Share Logs..." = "";
|
||||
"Open logs in Finder" = "";
|
||||
"Could not refresh Subscriptions" = "";
|
||||
"Could not load streams" = "";
|
||||
"Could not open video" = "";
|
||||
"Channel could not be found" = "";
|
||||
"Could not extract channel information" = "";
|
||||
"Could not extract SID from received cookies: %@" = "";
|
||||
"Could not update your token." = "";
|
||||
"Could not refresh Trending" = "";
|
||||
"This URL could not be opened" = "";
|
||||
"Could not open channel" = "";
|
||||
"Could not refresh Popular" = "";
|
||||
"Could not create share link" = "";
|
||||
"This video could not be opened" = "";
|
||||
"Could not extract playlist ID" = "";
|
||||
"No locations available at the moment" = "";
|
||||
"Could not refresh Playlists" = "";
|
||||
"If you want this app to be available in your language, join translation project." = "";
|
||||
"Translations" = "";
|
||||
"Recent Documents" = "";
|
||||
"Home" = "";
|
||||
"Show Home" = "";
|
||||
"Show Favorites" = "";
|
||||
"Inspector visibility" = "";
|
||||
"Edit Favorites…" = "";
|
||||
"Show Open Videos toolbar button" = "";
|
||||
"Files" = "";
|
||||
"Pages toolbar position" = "";
|
||||
"Video Details" = "";
|
||||
"Reload manifest" = "";
|
||||
"Clear Queue before opening" = "";
|
||||
"Open" = "";
|
||||
"Pages buttons" = "";
|
||||
"URL to Open" = "";
|
||||
"Enter link to open" = "";
|
||||
"Could not open Files" = "";
|
||||
"Paste" = "";
|
||||
"Open Videos" = "";
|
||||
"Enter links to open, one per line" = "";
|
||||
"Playback Mode" = "";
|
||||
"Add" = "";
|
||||
"Hide" = "";
|
||||
"Always" = "";
|
||||
"Only for local files and URLs" = "";
|
||||
"Right" = "";
|
||||
"Open Files" = "";
|
||||
"Share" = "";
|
||||
"Left" = "";
|
||||
"Format" = "";
|
||||
"Show only icons" = "";
|
||||
"Audio" = "";
|
||||
"Video" = "";
|
||||
"Codec" = "";
|
||||
"Size" = "";
|
||||
"FPS" = "";
|
||||
"Sample Rate" = "";
|
||||
"Could not find any links to open in your clipboard" = "";
|
||||
"Address" = "";
|
||||
"Remove…" = "";
|
||||
"Actions buttons" = "";
|
||||
"Show sidebar" = "";
|
||||
"Locations Manifest" = "";
|
||||
"Open Video" = "";
|
||||
"Share%@link" = "";
|
||||
"Are you sure you want to remove this document?" = "";
|
||||
"\"%@\" will be irreversibly removed from this device." = "";
|
||||
"Live Streams" = "";
|
||||
"Shorts" = "";
|
||||
"Verified" = "";
|
||||
"Channel" = "";
|
||||
|
||||
@@ -266,3 +266,239 @@
|
||||
"Sections" = "Bölümler";
|
||||
"Save history of searches, channels and playlists" = "Arama, kanal ve çalma listelerinin geçmişini kaydet";
|
||||
"Restore default profiles..." = "Varsayılan profilleri geri yükle...";
|
||||
"Visibility" = "";
|
||||
"Translations" = "";
|
||||
"Enter links to open, one per line" = "";
|
||||
"Open Videos" = "";
|
||||
"Playback Mode" = "";
|
||||
|
||||
/* Selected video was played on given date */
|
||||
"Watched %@" = "";
|
||||
"Yattee %@ (build %@)" = "";
|
||||
"That's nice to hear. It is fun to deliver apps other people want to use. You can consider donating to the project or help by contributing to new features development." = "";
|
||||
"Thumbnails" = "";
|
||||
"Dropped frames" = "";
|
||||
"SponsorBlock API Instance" = "";
|
||||
|
||||
/* Selected video is being played */
|
||||
"Watching now" = "";
|
||||
"Video Details" = "";
|
||||
"Live Streams" = "";
|
||||
"Typically near or at the end of the video when the credits pop up and/or endcards are shown." = "";
|
||||
"Default Profile" = "";
|
||||
|
||||
/* Player controls layout size for TV */
|
||||
"TV" = "";
|
||||
"Add" = "";
|
||||
"This URL could not be opened" = "";
|
||||
"Hide" = "";
|
||||
"Playing Next" = "";
|
||||
"Are you sure you want to remove this document?" = "";
|
||||
"Show channel name" = "";
|
||||
"Unlisted" = "";
|
||||
"Paste" = "";
|
||||
"Rate & Captions" = "";
|
||||
"Format" = "";
|
||||
"Right" = "";
|
||||
"Stream FPS" = "";
|
||||
"Cached time" = "";
|
||||
"Sign In Required" = "";
|
||||
"Could not create share link" = "";
|
||||
"Locations Manifest" = "";
|
||||
"When partially watched video is played" = "";
|
||||
"Open Video" = "";
|
||||
"Add Channels, Playlists and Searches to Favorites using" = "";
|
||||
"Always" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Year" = "";
|
||||
"Playback queue is empty" = "";
|
||||
"Show Favorites" = "";
|
||||
"Driver" = "";
|
||||
"Show progress of watching on thumbnails" = "";
|
||||
"Left" = "";
|
||||
"URL to Open" = "";
|
||||
"Subscribe" = "";
|
||||
"Yattee" = "";
|
||||
"Show Documents" = "";
|
||||
"Press and hold remote button to open captions and quality menus" = "";
|
||||
"No locations available at the moment" = "";
|
||||
"Show account username" = "";
|
||||
"Used to create links from videos, channels and playlists" = "";
|
||||
"Size" = "";
|
||||
"You have no playlists\n\nTap on \"New Playlist\" to create one" = "";
|
||||
"Sort: %@" = "";
|
||||
"Select location closest to you:" = "";
|
||||
"Playlist is empty\n\nTap and hold on a video and then \n\"Add to Playlist\"" = "";
|
||||
|
||||
/* Video duration filter in search */
|
||||
"Short" = "";
|
||||
"Home" = "";
|
||||
"Remove Location" = "";
|
||||
"Edit Favorites…" = "";
|
||||
"Show Open Videos toolbar button" = "";
|
||||
"Sample Rate" = "";
|
||||
"Private" = "";
|
||||
"Browsing" = "";
|
||||
"Documents" = "";
|
||||
"FPS" = "";
|
||||
"Only for local files and URLs" = "";
|
||||
"Show sidebar" = "";
|
||||
"Current Playlist" = "";
|
||||
"Center" = "";
|
||||
"Address" = "";
|
||||
"Video actions buttons" = "";
|
||||
"Keep last played video in the queue after restart" = "";
|
||||
"Remove…" = "";
|
||||
"Trending" = "";
|
||||
"Statistics" = "";
|
||||
"Copy%@link" = "";
|
||||
"Now Playing" = "";
|
||||
"Could not delete document" = "";
|
||||
"No comments" = "";
|
||||
"Could not open Files" = "";
|
||||
"You need to select an account\nto access %@ section" = "";
|
||||
"Reload manifest" = "";
|
||||
"Could not refresh Subscriptions" = "";
|
||||
|
||||
/* Subscriptions title */
|
||||
"Subscriptions" = "";
|
||||
"Upload date" = "";
|
||||
"This information will be processed only on your device and used to connect you to the server in the specified country." = "";
|
||||
"Shuffle" = "";
|
||||
"Buttons labels" = "";
|
||||
"Share %@ link" = "";
|
||||
"Could not load streams" = "";
|
||||
"Playback history is empty" = "";
|
||||
"Show icons and text when space permits" = "";
|
||||
"unknown" = "";
|
||||
"Share..." = "";
|
||||
|
||||
/* Video sort order in search */
|
||||
"Views" = "";
|
||||
"You need to create an instance and accounts\nto access %@ section" = "";
|
||||
"Verified" = "";
|
||||
"Open Files" = "";
|
||||
"Could not refresh Playlists" = "";
|
||||
"Actions buttons" = "";
|
||||
"Any format" = "";
|
||||
"Show playback statistics" = "";
|
||||
"Pages buttons" = "";
|
||||
"Videos" = "";
|
||||
"Codec" = "";
|
||||
"Comments are disabled" = "";
|
||||
"Audio" = "";
|
||||
|
||||
|
||||
"Public" = "";
|
||||
"Files" = "";
|
||||
"Show Home" = "";
|
||||
"Open" = "";
|
||||
|
||||
/* Loading stream OSD */
|
||||
"Opening %@ stream..." = "";
|
||||
"Clear Queue before opening" = "";
|
||||
"Copy %@ link with time" = "";
|
||||
"Show Inspector" = "";
|
||||
"Make default" = "";
|
||||
"Are you sure you want to remove %@ location?" = "";
|
||||
"No chapters information available" = "";
|
||||
"Share Logs..." = "";
|
||||
"Enter link to open" = "";
|
||||
"No documents" = "";
|
||||
"Inspector visibility" = "";
|
||||
"Could not update your token." = "";
|
||||
"Could not find any links to open in your clipboard" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Week" = "";
|
||||
"Sidebar" = "";
|
||||
"Show only icons" = "";
|
||||
"Current: %@\n%@" = "";
|
||||
"Show anonymous accounts" = "";
|
||||
"Could not open playlist" = "";
|
||||
"Round corners" = "";
|
||||
"URL" = "";
|
||||
"Recents" = "";
|
||||
"Show sidebar when space permits" = "";
|
||||
"System controls buttons" = "";
|
||||
"Could not extract channel information" = "";
|
||||
"Public Locations" = "";
|
||||
"You can find information about using Yattee in the Wiki pages." = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Very Large" = "";
|
||||
"Continue from %@" = "";
|
||||
"Copy %@ link" = "";
|
||||
"Seek gesture sensitivity" = "";
|
||||
"Show keywords" = "";
|
||||
"Wiki" = "";
|
||||
"Username" = "";
|
||||
"Could not extract video ID" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Smaller" = "";
|
||||
"Sort" = "";
|
||||
"This cannot be reverted" = "";
|
||||
"Public Manifest" = "";
|
||||
"You have no Playlists" = "";
|
||||
"Watched" = "";
|
||||
"Could not open video" = "";
|
||||
"Channel could not be found" = "";
|
||||
"Show video length" = "";
|
||||
"Source" = "";
|
||||
"Welcome" = "";
|
||||
"Wi-Fi" = "";
|
||||
"Could not open channel" = "";
|
||||
"This video could not be opened" = "";
|
||||
"Could not extract playlist ID" = "";
|
||||
"Could not load video" = "";
|
||||
"Decreased opacity" = "";
|
||||
"Shuffle All" = "";
|
||||
"Share %@ link with time" = "";
|
||||
"This cannot be reverted. You might need to switch between views or restart the app to see changes." = "";
|
||||
"Unsubscribe" = "";
|
||||
"Current Location" = "";
|
||||
"Stream & Player" = "";
|
||||
"Hardware decoder" = "";
|
||||
"Honor orientation lock" = "";
|
||||
"Seek with horizontal swipe on video" = "";
|
||||
"Segments typically found at the start of a video that include an animation, still frame or clip which are also seen in other videos by the same creator." = "";
|
||||
"Switch to public locations" = "";
|
||||
"%@ formats" = "";
|
||||
"Open logs in Finder" = "";
|
||||
"Could not refresh Popular" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Self-promotion" = "";
|
||||
|
||||
/* Player controls layout size */
|
||||
"Small" = "";
|
||||
|
||||
/* SponsorBlock category name */
|
||||
"Sponsor" = "";
|
||||
"System controls show buttons for %@" = "";
|
||||
"Show history" = "";
|
||||
"Could not extract SID from received cookies: %@" = "";
|
||||
"This will remove all your custom profiles and return their default values. This cannot be reverted." = "";
|
||||
"Switch to other public location" = "";
|
||||
"SponsorBlock" = "";
|
||||
"Seek gesture speed" = "";
|
||||
"If you want this app to be available in your language, join translation project." = "";
|
||||
"Could not refresh Trending" = "";
|
||||
|
||||
/* Video date filter in search */
|
||||
"Today" = "";
|
||||
"Shorts" = "";
|
||||
"Channel" = "";
|
||||
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
|
||||
"\"%@\" will be irreversibly removed from this device." = "";
|
||||
"Recent Documents" = "";
|
||||
"Recent History" = "";
|
||||
"Show Open Videos quick actions" = "";
|
||||
"Pages toolbar position" = "";
|
||||
"Video" = "";
|
||||
"Channels" = "";
|
||||
"Share" = "";
|
||||
"File" = "";
|
||||
"Share%@link" = "";
|
||||
|
||||
@@ -830,6 +830,9 @@
|
||||
37C7A1D6267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7A1D4267BFD9D0010EAD6 /* SponsorBlockSegment.swift */; };
|
||||
37C7A1D7267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7A1D4267BFD9D0010EAD6 /* SponsorBlockSegment.swift */; };
|
||||
37C7A1DA267CACF50010EAD6 /* TrendingCountry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B17F267B4DFB00704544 /* TrendingCountry.swift */; };
|
||||
37C7B21429ABD9F20013C196 /* ChannelPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7B21329ABD9F20013C196 /* ChannelPage.swift */; };
|
||||
37C7B21529ABD9F20013C196 /* ChannelPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7B21329ABD9F20013C196 /* ChannelPage.swift */; };
|
||||
37C7B21629ABD9F20013C196 /* ChannelPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7B21329ABD9F20013C196 /* ChannelPage.swift */; };
|
||||
37C89322294532220032AFD3 /* PlayerOverlayModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */; };
|
||||
37C89323294532220032AFD3 /* PlayerOverlayModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */; };
|
||||
37C89324294532220032AFD3 /* PlayerOverlayModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */; };
|
||||
@@ -1432,6 +1435,7 @@
|
||||
37C3A24C272360470087A57A /* ChannelPlaylist+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChannelPlaylist+Fixtures.swift"; sourceTree = "<group>"; };
|
||||
37C3A250272366440087A57A /* ChannelPlaylistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelPlaylistView.swift; sourceTree = "<group>"; };
|
||||
37C7A1D4267BFD9D0010EAD6 /* SponsorBlockSegment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockSegment.swift; sourceTree = "<group>"; };
|
||||
37C7B21329ABD9F20013C196 /* ChannelPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelPage.swift; sourceTree = "<group>"; };
|
||||
37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerOverlayModifier.swift; sourceTree = "<group>"; };
|
||||
37C8E700294FC97D00EEAB14 /* QueueView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueView.swift; sourceTree = "<group>"; };
|
||||
37CC3F44270CE30600608308 /* PlayerQueueItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerQueueItem.swift; sourceTree = "<group>"; };
|
||||
@@ -2380,6 +2384,7 @@
|
||||
377F9F79294403DC0043F856 /* Cache */,
|
||||
3776ADD5287381240078EBC4 /* Captions.swift */,
|
||||
37AAF28F26740715007FC770 /* Channel.swift */,
|
||||
37C7B21329ABD9F20013C196 /* ChannelPage.swift */,
|
||||
37C3A24427235DA70087A57A /* ChannelPlaylist.swift */,
|
||||
37520698285E8DD300CA655F /* Chapter.swift */,
|
||||
371B7E5B27596B8400D21217 /* Comment.swift */,
|
||||
@@ -3237,6 +3242,7 @@
|
||||
37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */,
|
||||
377ABC48286E5887009C986F /* Sequence+Unique.swift in Sources */,
|
||||
37520699285E8DD300CA655F /* Chapter.swift in Sources */,
|
||||
37C7B21429ABD9F20013C196 /* ChannelPage.swift in Sources */,
|
||||
37319F0527103F94004ECCD0 /* PlayerQueue.swift in Sources */,
|
||||
376B2E0726F920D600B1D64D /* SignInRequiredView.swift in Sources */,
|
||||
37C0697E2725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
||||
@@ -3462,6 +3468,7 @@
|
||||
37A362BB2953707F00BDF328 /* ClearQueueButton.swift in Sources */,
|
||||
3752069E285E910600CA655F /* ChapterView.swift in Sources */,
|
||||
37030FF827B0347C00ECDDAA /* MPVPlayerView.swift in Sources */,
|
||||
37C7B21529ABD9F20013C196 /* ChannelPage.swift in Sources */,
|
||||
378E50FC26FE8B9F00F49626 /* Instance.swift in Sources */,
|
||||
37169AA32729D98A0011DE61 /* InstancesBridge.swift in Sources */,
|
||||
37B044B826F7AB9000E1419D /* SettingsView.swift in Sources */,
|
||||
@@ -3882,6 +3889,7 @@
|
||||
378E50FD26FE8B9F00F49626 /* Instance.swift in Sources */,
|
||||
37169AA82729E2CC0011DE61 /* AccountsBridge.swift in Sources */,
|
||||
37C8E703294FC97D00EEAB14 /* QueueView.swift in Sources */,
|
||||
37C7B21629ABD9F20013C196 /* ChannelPage.swift in Sources */,
|
||||
3754B01728B7F84D009717C8 /* Constants.swift in Sources */,
|
||||
37BC50AE2778BCBA00510953 /* HistoryModel.swift in Sources */,
|
||||
37D526E02720AC4400ED2F5E /* VideosAPI.swift in Sources */,
|
||||
@@ -3977,7 +3985,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Open in Yattee/Open in Yattee.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Open in Yattee/Info.plist";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Open in Yattee";
|
||||
@@ -4008,7 +4016,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Open in Yattee/Info.plist";
|
||||
@@ -4039,7 +4047,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
@@ -4059,7 +4067,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
@@ -4219,7 +4227,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "iOS/Yattee (iOS).entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -4272,7 +4280,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION=1";
|
||||
@@ -4324,7 +4332,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@@ -4366,7 +4374,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = 78Z5H3M6RJ;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
@@ -4404,7 +4412,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4428,7 +4436,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4454,7 +4462,7 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4479,7 +4487,7 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -4505,7 +4513,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -4545,7 +4553,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
"DEVELOPMENT_TEAM[sdk=appletvos*]" = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -4586,7 +4594,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -4610,7 +4618,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 137;
|
||||
CURRENT_PROJECT_VERSION = 138;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
||||
@@ -24,9 +24,6 @@ DEVELOPER_APP_IDENTIFIER = ENV['DEVELOPER_APP_IDENTIFIER']
|
||||
GIT_AUTHORIZATION = ENV['GIT_AUTHORIZATION']
|
||||
TESTFLIGHT_EXTERNAL_GROUPS = ENV['TESTFLIGHT_EXTERNAL_GROUPS']
|
||||
|
||||
AS_CONNECT_BUILD_VERSION_FILENAME = 'AS_CONNECT_BUILD_VERSION'
|
||||
AS_CONNECT_BUILD_VERSION_PATH = "../#{AS_CONNECT_BUILD_VERSION_FILENAME}"
|
||||
|
||||
XCODEPROJ = "#{APP_NAME}.xcodeproj"
|
||||
|
||||
def delete_temp_keychain(name)
|
||||
@@ -57,30 +54,12 @@ end
|
||||
|
||||
desc "Bump build number and commit"
|
||||
lane :bump_build do
|
||||
as_connect_build_version = File.read(AS_CONNECT_BUILD_VERSION_PATH).to_i
|
||||
build = get_build_number(xcodeproj: XCODEPROJ).to_i
|
||||
increment_build_number(xcodeproj: XCODEPROJ)
|
||||
|
||||
puts "AS Connect build version: #{as_connect_build_version}"
|
||||
puts "Current build number: #{build}"
|
||||
|
||||
if build <= as_connect_build_version
|
||||
new_build_number = as_connect_build_version + 1
|
||||
|
||||
increment_build_number
|
||||
actual_build_number = get_build_number(xcodeproj: XCODEPROJ).to_i
|
||||
|
||||
puts "Bumped build number to #{actual_build_number}"
|
||||
|
||||
File.open(AS_CONNECT_BUILD_VERSION_PATH, 'w+') { |file| file.write("#{new_build_number}\n") }
|
||||
|
||||
commit_version_bump(
|
||||
message: "Bump build number to #{get_build_number(xcodeproj: XCODEPROJ)}",
|
||||
include: [AS_CONNECT_BUILD_VERSION_FILENAME],
|
||||
xcodeproj: XCODEPROJ
|
||||
)
|
||||
else
|
||||
puts "Current build number is higher than App Store Connect build version"
|
||||
end
|
||||
commit_version_bump(
|
||||
message: "Bump build number to #{get_build_number(xcodeproj: XCODEPROJ)}",
|
||||
xcodeproj: XCODEPROJ
|
||||
)
|
||||
end
|
||||
|
||||
desc "Bump version number and commit"
|
||||
|
||||
Reference in New Issue
Block a user