mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 05:23:41 +00:00
Popular videos tab
This commit is contained in:
parent
850f4e6a02
commit
9d7abda63f
@ -2,12 +2,12 @@ import SwiftUI
|
||||
|
||||
struct ChannelView: View {
|
||||
@ObservedObject private var provider = ChannelVideosProvider()
|
||||
@ObservedObject var state: AppState
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
var body: some View {
|
||||
VideosView(state: state, tabSelection: $tabSelection, videos: videos)
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
}
|
||||
|
||||
var listRowInsets: EdgeInsets {
|
||||
|
@ -2,12 +2,12 @@ import SwiftUI
|
||||
|
||||
struct PopularVideosView: View {
|
||||
@ObservedObject private var provider = PopularVideosProvider()
|
||||
@ObservedObject var state: AppState
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
var body: some View {
|
||||
VideosView(state: state, tabSelection: $tabSelection, videos: videos)
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
.task {
|
||||
async {
|
||||
provider.load()
|
||||
|
@ -2,14 +2,14 @@ import SwiftUI
|
||||
|
||||
struct SearchView: View {
|
||||
@ObservedObject private var provider = SearchedVideosProvider()
|
||||
@ObservedObject var state: AppState
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
@State var query = ""
|
||||
@State private var query = ""
|
||||
|
||||
var body: some View {
|
||||
VideosView(state: state, tabSelection: $tabSelection, videos: videos)
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
.searchable(text: $query)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import AVKit
|
||||
|
||||
class StreamAVPlayerViewController: AVPlayerViewController {
|
||||
final class StreamAVPlayerViewController: AVPlayerViewController {
|
||||
var state: PlayerState?
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
|
@ -2,12 +2,12 @@ import SwiftUI
|
||||
|
||||
struct SubscriptionsView: View {
|
||||
@ObservedObject private var provider = SubscriptionVideosProvider()
|
||||
@ObservedObject var state: AppState
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
var body: some View {
|
||||
VideosView(state: state, tabSelection: $tabSelection, videos: videos)
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
.task {
|
||||
async {
|
||||
provider.load()
|
||||
|
29
Apple TV/TrendingCategorySelectionView.swift
Normal file
29
Apple TV/TrendingCategorySelectionView.swift
Normal file
@ -0,0 +1,29 @@
|
||||
import SwiftUI
|
||||
|
||||
struct TrendingCategorySelectionView: View {
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
|
||||
@Binding var selectedCategory: TrendingCategory
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VisualEffectView(effect: UIBlurEffect(style: .dark))
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Spacer()
|
||||
|
||||
ForEach(TrendingCategory.allCases) { category in
|
||||
Button(category.name) {
|
||||
selectedCategory = category
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
}
|
||||
.frame(width: 800)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
}
|
||||
}
|
34
Apple TV/TrendingCountrySelectionView.swift
Normal file
34
Apple TV/TrendingCountrySelectionView.swift
Normal file
@ -0,0 +1,34 @@
|
||||
import SwiftUI
|
||||
|
||||
struct TrendingCountrySelectionView: View {
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
@ObservedObject var provider: TrendingCountriesProvider
|
||||
|
||||
@State private var query: String = ""
|
||||
@Binding var selectedCountry: Country
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VisualEffectView(effect: UIBlurEffect(style: .dark))
|
||||
|
||||
ScrollView(.vertical) {
|
||||
ForEach(countries) { country in
|
||||
Button(country.name) {
|
||||
selectedCountry = country
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
}
|
||||
.frame(width: 800)
|
||||
}
|
||||
.searchable(text: $query)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
}
|
||||
|
||||
var countries: [Country] {
|
||||
provider.load(query)
|
||||
|
||||
return provider.countries
|
||||
}
|
||||
}
|
52
Apple TV/TrendingView.swift
Normal file
52
Apple TV/TrendingView.swift
Normal file
@ -0,0 +1,52 @@
|
||||
import SwiftUI
|
||||
|
||||
struct TrendingView: View {
|
||||
@EnvironmentObject private var state: AppState
|
||||
@EnvironmentObject private var trendingState: TrendingState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
@ObservedObject private var countriesProvider = TrendingCountriesProvider()
|
||||
@ObservedObject private var videosProvider = TrendingVideosProvider()
|
||||
|
||||
@State private var selectingCategory = false
|
||||
@State private var selectingCountry = false
|
||||
|
||||
var body: some View {
|
||||
Section {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
HStack(alignment: .top) {
|
||||
Spacer()
|
||||
|
||||
Button(trendingState.category.name) {
|
||||
selectingCategory.toggle()
|
||||
}
|
||||
.fullScreenCover(isPresented: $selectingCategory) {
|
||||
TrendingCategorySelectionView(selectedCategory: $trendingState.category)
|
||||
}
|
||||
|
||||
Text(trendingState.country.flag)
|
||||
.font(.system(size: 60))
|
||||
|
||||
Button(trendingState.country.rawValue) {
|
||||
selectingCountry.toggle()
|
||||
}
|
||||
.fullScreenCover(isPresented: $selectingCountry) {
|
||||
TrendingCountrySelectionView(provider: countriesProvider, selectedCountry: $trendingState.country)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.scaleEffect(0.85)
|
||||
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var videos: [Video] {
|
||||
videosProvider.load(category: trendingState.category, country: trendingState.country)
|
||||
|
||||
return videosProvider.videos
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct VideosView: View {
|
||||
@ObservedObject var state: AppState
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
|
13
Apple TV/VisualEffectView.swift
Normal file
13
Apple TV/VisualEffectView.swift
Normal file
@ -0,0 +1,13 @@
|
||||
import SwiftUI
|
||||
|
||||
struct VisualEffectView: UIViewRepresentable {
|
||||
var effect: UIVisualEffect?
|
||||
|
||||
func makeUIView(context _: UIViewRepresentableContext<Self>) -> UIVisualEffectView {
|
||||
UIVisualEffectView()
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIVisualEffectView, context _: UIViewRepresentableContext<Self>) {
|
||||
uiView.effect = effect
|
||||
}
|
||||
}
|
11
Model/TrendingCategory.swift
Normal file
11
Model/TrendingCategory.swift
Normal file
@ -0,0 +1,11 @@
|
||||
enum TrendingCategory: String, CaseIterable, Identifiable {
|
||||
case `default`, music, gaming, movies
|
||||
|
||||
var id: TrendingCategory.RawValue {
|
||||
rawValue
|
||||
}
|
||||
|
||||
var name: String {
|
||||
rawValue.capitalized
|
||||
}
|
||||
}
|
18
Model/TrendingCountriesProvider.swift
Normal file
18
Model/TrendingCountriesProvider.swift
Normal file
@ -0,0 +1,18 @@
|
||||
import Alamofire
|
||||
import Foundation
|
||||
import SwiftyJSON
|
||||
|
||||
final class TrendingCountriesProvider: DataProvider {
|
||||
@Published var countries = [Country]()
|
||||
|
||||
private var query: String = ""
|
||||
|
||||
func load(_ query: String) {
|
||||
guard query != self.query else {
|
||||
return
|
||||
}
|
||||
|
||||
self.query = query
|
||||
countries = Country.searchByName(query)
|
||||
}
|
||||
}
|
6
Model/TrendingState.swift
Normal file
6
Model/TrendingState.swift
Normal file
@ -0,0 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
final class TrendingState: ObservableObject {
|
||||
@Published var category: TrendingCategory = .default
|
||||
@Published var country: Country = .pl
|
||||
}
|
31
Model/TrendingVideosProvider.swift
Normal file
31
Model/TrendingVideosProvider.swift
Normal file
@ -0,0 +1,31 @@
|
||||
import Alamofire
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import SwiftyJSON
|
||||
|
||||
final class TrendingVideosProvider: DataProvider {
|
||||
@Published var videos = [Video]()
|
||||
|
||||
var currentCategory: TrendingCategory?
|
||||
var currentCountry: Country?
|
||||
|
||||
func load(category: TrendingCategory, country: Country) {
|
||||
if category == currentCategory, country == currentCountry {
|
||||
return
|
||||
}
|
||||
|
||||
DataProvider.request("trending?type=\(category.name)®ion=\(country.rawValue)").responseJSON { response in
|
||||
switch response.result {
|
||||
case let .success(value):
|
||||
self.videos = JSON(value).arrayValue.map { Video($0) }
|
||||
case let .failure(error):
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
currentCategory = category
|
||||
currentCountry = country
|
||||
|
||||
videos = []
|
||||
}
|
||||
}
|
@ -7,9 +7,30 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
3705B17C267B4D9A00704544 /* VisualEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B17B267B4D9A00704544 /* VisualEffectView.swift */; };
|
||||
3705B17E267B4DDE00704544 /* TrendingCategorySelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B17D267B4DDE00704544 /* TrendingCategorySelectionView.swift */; };
|
||||
3705B180267B4DFB00704544 /* TrendingCountrySelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B17F267B4DFB00704544 /* TrendingCountrySelectionView.swift */; };
|
||||
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
||||
3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
||||
3705B184267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
||||
37141668267A83F9006CA35D /* StreamAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141667267A83F9006CA35D /* StreamAVPlayerViewController.swift */; };
|
||||
37141669267A83F9006CA35D /* StreamAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141667267A83F9006CA35D /* StreamAVPlayerViewController.swift */; };
|
||||
3714166A267A83F9006CA35D /* StreamAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141667267A83F9006CA35D /* StreamAVPlayerViewController.swift */; };
|
||||
3714166F267A8ACC006CA35D /* TrendingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714166E267A8ACC006CA35D /* TrendingView.swift */; };
|
||||
37141670267A8ACC006CA35D /* TrendingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714166E267A8ACC006CA35D /* TrendingView.swift */; };
|
||||
37141671267A8ACC006CA35D /* TrendingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714166E267A8ACC006CA35D /* TrendingView.swift */; };
|
||||
37141673267A8E10006CA35D /* Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141672267A8E10006CA35D /* Country.swift */; };
|
||||
37141674267A8E10006CA35D /* Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141672267A8E10006CA35D /* Country.swift */; };
|
||||
37141675267A8E10006CA35D /* Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141672267A8E10006CA35D /* Country.swift */; };
|
||||
37141677267A9AAD006CA35D /* TrendingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141676267A9AAD006CA35D /* TrendingState.swift */; };
|
||||
37141678267A9AAD006CA35D /* TrendingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141676267A9AAD006CA35D /* TrendingState.swift */; };
|
||||
37141679267A9AAD006CA35D /* TrendingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37141676267A9AAD006CA35D /* TrendingState.swift */; };
|
||||
3714167B267AA1CF006CA35D /* TrendingCountriesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714167A267AA1CF006CA35D /* TrendingCountriesProvider.swift */; };
|
||||
3714167C267AA1CF006CA35D /* TrendingCountriesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714167A267AA1CF006CA35D /* TrendingCountriesProvider.swift */; };
|
||||
3714167D267AA1CF006CA35D /* TrendingCountriesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714167A267AA1CF006CA35D /* TrendingCountriesProvider.swift */; };
|
||||
3714167F267AB55D006CA35D /* TrendingVideosProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714167E267AB55D006CA35D /* TrendingVideosProvider.swift */; };
|
||||
37141680267AB55D006CA35D /* TrendingVideosProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714167E267AB55D006CA35D /* TrendingVideosProvider.swift */; };
|
||||
37141681267AB55D006CA35D /* TrendingVideosProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3714167E267AB55D006CA35D /* TrendingVideosProvider.swift */; };
|
||||
3741B5302676213400125C5E /* PlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3741B52F2676213400125C5E /* PlayerViewController.swift */; };
|
||||
377FC7D3267A080300A6BBAF /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 377FC7D2267A080300A6BBAF /* Alamofire */; };
|
||||
377FC7D5267A080300A6BBAF /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 377FC7D4267A080300A6BBAF /* SwiftyJSON */; };
|
||||
@ -134,7 +155,16 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
3705B17B267B4D9A00704544 /* VisualEffectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualEffectView.swift; sourceTree = "<group>"; };
|
||||
3705B17D267B4DDE00704544 /* TrendingCategorySelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCategorySelectionView.swift; sourceTree = "<group>"; };
|
||||
3705B17F267B4DFB00704544 /* TrendingCountrySelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCountrySelectionView.swift; sourceTree = "<group>"; };
|
||||
3705B181267B4E4900704544 /* TrendingCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCategory.swift; sourceTree = "<group>"; };
|
||||
37141667267A83F9006CA35D /* StreamAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamAVPlayerViewController.swift; sourceTree = "<group>"; };
|
||||
3714166E267A8ACC006CA35D /* TrendingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingView.swift; sourceTree = "<group>"; };
|
||||
37141672267A8E10006CA35D /* Country.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Country.swift; sourceTree = "<group>"; };
|
||||
37141676267A9AAD006CA35D /* TrendingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingState.swift; sourceTree = "<group>"; };
|
||||
3714167A267AA1CF006CA35D /* TrendingCountriesProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCountriesProvider.swift; sourceTree = "<group>"; };
|
||||
3714167E267AB55D006CA35D /* TrendingVideosProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingVideosProvider.swift; sourceTree = "<group>"; };
|
||||
3741B52F2676213400125C5E /* PlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = "<group>"; };
|
||||
37AAF27D26737323007FC770 /* PopularVideosView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopularVideosView.swift; sourceTree = "<group>"; };
|
||||
37AAF27F26737550007FC770 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
|
||||
@ -269,8 +299,9 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
37D4B0C32671614700C925CA /* ContentView.swift */,
|
||||
37AAF2932674086B007FC770 /* TabSelection.swift */,
|
||||
37141672267A8E10006CA35D /* Country.swift */,
|
||||
37D4B0C22671614700C925CA /* PearvidiousApp.swift */,
|
||||
37AAF2932674086B007FC770 /* TabSelection.swift */,
|
||||
37D4B0C42671614800C925CA /* Assets.xcassets */,
|
||||
);
|
||||
path = Shared;
|
||||
@ -308,17 +339,21 @@
|
||||
37D4B159267164AE00C925CA /* Apple TV */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
37AAF29F26741C97007FC770 /* SubscriptionsView.swift */,
|
||||
37AAF27D26737323007FC770 /* PopularVideosView.swift */,
|
||||
37AAF2892673AB89007FC770 /* ChannelView.swift */,
|
||||
37AAF27F26737550007FC770 /* SearchView.swift */,
|
||||
37D4B1822671681B00C925CA /* PlayerView.swift */,
|
||||
3741B52F2676213400125C5E /* PlayerViewController.swift */,
|
||||
37AAF27D26737323007FC770 /* PopularVideosView.swift */,
|
||||
37AAF27F26737550007FC770 /* SearchView.swift */,
|
||||
37141667267A83F9006CA35D /* StreamAVPlayerViewController.swift */,
|
||||
37AAF29F26741C97007FC770 /* SubscriptionsView.swift */,
|
||||
3705B17D267B4DDE00704544 /* TrendingCategorySelectionView.swift */,
|
||||
3705B17F267B4DFB00704544 /* TrendingCountrySelectionView.swift */,
|
||||
3714166E267A8ACC006CA35D /* TrendingView.swift */,
|
||||
37AAF29926740A01007FC770 /* VideosView.swift */,
|
||||
37D4B18B26717B3800C925CA /* VideoThumbnailView.swift */,
|
||||
37D4B1AE26729DEB00C925CA /* Info.plist */,
|
||||
3705B17B267B4D9A00704544 /* VisualEffectView.swift */,
|
||||
37D4B15E267164AF00C925CA /* Assets.xcassets */,
|
||||
37D4B1AE26729DEB00C925CA /* Info.plist */,
|
||||
);
|
||||
path = "Apple TV";
|
||||
sourceTree = "<group>";
|
||||
@ -335,18 +370,22 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
37AAF28F26740715007FC770 /* AppState.swift */,
|
||||
37B767DA2677C3CA0098BAA8 /* PlayerState.swift */,
|
||||
37AAF29B26741B5F007FC770 /* SubscriptionVideosProvider.swift */,
|
||||
37D4B19226717CE100C925CA /* PopularVideosProvider.swift */,
|
||||
37AAF28B2673ABD3007FC770 /* ChannelVideosProvider.swift */,
|
||||
37AAF2812673791F007FC770 /* SearchedVideosProvider.swift */,
|
||||
37D4B1B32672A30700C925CA /* VideoDetailsProvider.swift */,
|
||||
37D4B1AF2672A01000C925CA /* DataProvider.swift */,
|
||||
37D4B19626717E1500C925CA /* Video.swift */,
|
||||
37CEE4C02677B697005A1EFE /* Stream.swift */,
|
||||
37CEE4B42677B628005A1EFE /* StreamType.swift */,
|
||||
37CEE4B82677B63F005A1EFE /* StreamResolution.swift */,
|
||||
37CEE4BC2677B670005A1EFE /* AudioVideoStream.swift */,
|
||||
37AAF28B2673ABD3007FC770 /* ChannelVideosProvider.swift */,
|
||||
37D4B1AF2672A01000C925CA /* DataProvider.swift */,
|
||||
37B767DA2677C3CA0098BAA8 /* PlayerState.swift */,
|
||||
37D4B19226717CE100C925CA /* PopularVideosProvider.swift */,
|
||||
37AAF2812673791F007FC770 /* SearchedVideosProvider.swift */,
|
||||
37CEE4C02677B697005A1EFE /* Stream.swift */,
|
||||
37CEE4B82677B63F005A1EFE /* StreamResolution.swift */,
|
||||
37CEE4B42677B628005A1EFE /* StreamType.swift */,
|
||||
37AAF29B26741B5F007FC770 /* SubscriptionVideosProvider.swift */,
|
||||
3714167A267AA1CF006CA35D /* TrendingCountriesProvider.swift */,
|
||||
37141676267A9AAD006CA35D /* TrendingState.swift */,
|
||||
37D4B19626717E1500C925CA /* Video.swift */,
|
||||
37D4B1B32672A30700C925CA /* VideoDetailsProvider.swift */,
|
||||
3714167E267AB55D006CA35D /* TrendingVideosProvider.swift */,
|
||||
3705B181267B4E4900704544 /* TrendingCategory.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
@ -602,9 +641,13 @@
|
||||
37141668267A83F9006CA35D /* StreamAVPlayerViewController.swift in Sources */,
|
||||
377FC7E6267A085600A6BBAF /* PlayerView.swift in Sources */,
|
||||
37CEE4C12677B697005A1EFE /* Stream.swift in Sources */,
|
||||
37141677267A9AAD006CA35D /* TrendingState.swift in Sources */,
|
||||
37D4B0E62671614900C925CA /* ContentView.swift in Sources */,
|
||||
377FC7DC267A081800A6BBAF /* PopularVideosView.swift in Sources */,
|
||||
3714167F267AB55D006CA35D /* TrendingVideosProvider.swift in Sources */,
|
||||
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||
37CEE4B52677B628005A1EFE /* StreamType.swift in Sources */,
|
||||
3714166F267A8ACC006CA35D /* TrendingView.swift in Sources */,
|
||||
377FC7E3267A084A00A6BBAF /* VideoThumbnailView.swift in Sources */,
|
||||
37AAF2822673791F007FC770 /* SearchedVideosProvider.swift in Sources */,
|
||||
37AAF29026740715007FC770 /* AppState.swift in Sources */,
|
||||
@ -617,7 +660,9 @@
|
||||
37C7A9042679059200E721B4 /* AVKeyValueStatus+String.swift in Sources */,
|
||||
37B767DB2677C3CA0098BAA8 /* PlayerState.swift in Sources */,
|
||||
37D4B1B42672A30700C925CA /* VideoDetailsProvider.swift in Sources */,
|
||||
37141673267A8E10006CA35D /* Country.swift in Sources */,
|
||||
37AAF2A026741C97007FC770 /* SubscriptionsView.swift in Sources */,
|
||||
3714167B267AA1CF006CA35D /* TrendingCountriesProvider.swift in Sources */,
|
||||
377FC7DF267A082200A6BBAF /* VideosView.swift in Sources */,
|
||||
37D4B19726717E1500C925CA /* Video.swift in Sources */,
|
||||
37D4B0E42671614900C925CA /* PearvidiousApp.swift in Sources */,
|
||||
@ -635,9 +680,13 @@
|
||||
37141669267A83F9006CA35D /* StreamAVPlayerViewController.swift in Sources */,
|
||||
377FC7E7267A085600A6BBAF /* PlayerView.swift in Sources */,
|
||||
37CEE4C22677B697005A1EFE /* Stream.swift in Sources */,
|
||||
37141678267A9AAD006CA35D /* TrendingState.swift in Sources */,
|
||||
37D4B0E72671614900C925CA /* ContentView.swift in Sources */,
|
||||
377FC7DD267A081A00A6BBAF /* PopularVideosView.swift in Sources */,
|
||||
37141680267AB55D006CA35D /* TrendingVideosProvider.swift in Sources */,
|
||||
3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||
37CEE4B62677B628005A1EFE /* StreamType.swift in Sources */,
|
||||
37141670267A8ACC006CA35D /* TrendingView.swift in Sources */,
|
||||
377FC7E2267A084A00A6BBAF /* VideoThumbnailView.swift in Sources */,
|
||||
37AAF2832673791F007FC770 /* SearchedVideosProvider.swift in Sources */,
|
||||
37AAF29126740715007FC770 /* AppState.swift in Sources */,
|
||||
@ -650,7 +699,9 @@
|
||||
37C7A906267905AF00E721B4 /* AVKeyValueStatus+String.swift in Sources */,
|
||||
37B767DC2677C3CA0098BAA8 /* PlayerState.swift in Sources */,
|
||||
37D4B1B52672A30700C925CA /* VideoDetailsProvider.swift in Sources */,
|
||||
37141674267A8E10006CA35D /* Country.swift in Sources */,
|
||||
37AAF2A126741C97007FC770 /* SubscriptionsView.swift in Sources */,
|
||||
3714167C267AA1CF006CA35D /* TrendingCountriesProvider.swift in Sources */,
|
||||
377FC7DE267A082100A6BBAF /* VideosView.swift in Sources */,
|
||||
37D4B19826717E1500C925CA /* Video.swift in Sources */,
|
||||
37D4B0E52671614900C925CA /* PearvidiousApp.swift in Sources */,
|
||||
@ -684,10 +735,14 @@
|
||||
3714166A267A83F9006CA35D /* StreamAVPlayerViewController.swift in Sources */,
|
||||
37D4B19526717CE100C925CA /* PopularVideosProvider.swift in Sources */,
|
||||
37AAF29E26741B5F007FC770 /* SubscriptionVideosProvider.swift in Sources */,
|
||||
37141679267A9AAD006CA35D /* TrendingState.swift in Sources */,
|
||||
37D4B1842671684E00C925CA /* PlayerView.swift in Sources */,
|
||||
37D4B1802671650A00C925CA /* PearvidiousApp.swift in Sources */,
|
||||
37141681267AB55D006CA35D /* TrendingVideosProvider.swift in Sources */,
|
||||
37D4B1B22672A01000C925CA /* DataProvider.swift in Sources */,
|
||||
37141671267A8ACC006CA35D /* TrendingView.swift in Sources */,
|
||||
37AAF29226740715007FC770 /* AppState.swift in Sources */,
|
||||
3705B17C267B4D9A00704544 /* VisualEffectView.swift in Sources */,
|
||||
3741B5302676213400125C5E /* PlayerViewController.swift in Sources */,
|
||||
37B767DD2677C3CA0098BAA8 /* PlayerState.swift in Sources */,
|
||||
37C7A905267905AE00E721B4 /* AVKeyValueStatus+String.swift in Sources */,
|
||||
@ -699,11 +754,16 @@
|
||||
37CEE4C32677B697005A1EFE /* Stream.swift in Sources */,
|
||||
37AAF28A2673AB89007FC770 /* ChannelView.swift in Sources */,
|
||||
37AAF28E2673ABD3007FC770 /* ChannelVideosProvider.swift in Sources */,
|
||||
3705B180267B4DFB00704544 /* TrendingCountrySelectionView.swift in Sources */,
|
||||
37141675267A8E10006CA35D /* Country.swift in Sources */,
|
||||
37D4B19926717E1500C925CA /* Video.swift in Sources */,
|
||||
3714167D267AA1CF006CA35D /* TrendingCountriesProvider.swift in Sources */,
|
||||
3705B184267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||
37AAF2A226741C97007FC770 /* SubscriptionsView.swift in Sources */,
|
||||
37D4B1812671653A00C925CA /* ContentView.swift in Sources */,
|
||||
37AAF2842673791F007FC770 /* SearchedVideosProvider.swift in Sources */,
|
||||
37CEE4BB2677B63F005A1EFE /* StreamResolution.swift in Sources */,
|
||||
3705B17E267B4DDE00704544 /* TrendingCategorySelectionView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1,32 +1,39 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@StateObject private var state = AppState()
|
||||
@ObservedObject private var state = AppState()
|
||||
@StateObject private var trendingState = TrendingState()
|
||||
|
||||
@State private var tabSelection: TabSelection = .subscriptions
|
||||
@State private var tabSelection = TabSelection.popular
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
TabView(selection: $tabSelection) {
|
||||
SubscriptionsView(state: state, tabSelection: $tabSelection)
|
||||
SubscriptionsView(tabSelection: $tabSelection)
|
||||
.tabItem { Text("Subscriptions") }
|
||||
.tag(TabSelection.subscriptions)
|
||||
|
||||
PopularVideosView(state: state, tabSelection: $tabSelection)
|
||||
PopularVideosView(tabSelection: $tabSelection)
|
||||
.tabItem { Text("Popular") }
|
||||
.tag(TabSelection.popular)
|
||||
|
||||
if state.showingChannel {
|
||||
ChannelView(state: state, tabSelection: $tabSelection)
|
||||
ChannelView(tabSelection: $tabSelection)
|
||||
.tabItem { Text("\(state.channel) Channel") }
|
||||
.tag(TabSelection.channel)
|
||||
}
|
||||
|
||||
SearchView(state: state, tabSelection: $tabSelection)
|
||||
TrendingView(tabSelection: $tabSelection)
|
||||
.tabItem { Text("Trending") }
|
||||
.tag(TabSelection.trending)
|
||||
|
||||
SearchView(tabSelection: $tabSelection)
|
||||
.tabItem { Image(systemName: "magnifyingglass") }
|
||||
.tag(TabSelection.search)
|
||||
}
|
||||
}
|
||||
.environmentObject(state)
|
||||
.environmentObject(trendingState)
|
||||
}
|
||||
}
|
||||
|
||||
|
547
Shared/Country.swift
Normal file
547
Shared/Country.swift
Normal file
@ -0,0 +1,547 @@
|
||||
// swiftlint:disable switch_case_on_newline
|
||||
|
||||
enum Country: String, CaseIterable, Identifiable {
|
||||
var id: String {
|
||||
rawValue
|
||||
}
|
||||
|
||||
case af = "AF"
|
||||
case ax = "AX"
|
||||
case al = "AL"
|
||||
case dz = "DZ"
|
||||
case `as` = "AS"
|
||||
case ad = "AD"
|
||||
case ao = "AO"
|
||||
case ai = "AI"
|
||||
case aq = "AQ"
|
||||
case ag = "AG"
|
||||
case ar = "AR"
|
||||
case am = "AM"
|
||||
case aw = "AW"
|
||||
case au = "AU"
|
||||
case at = "AT"
|
||||
case az = "AZ"
|
||||
case bs = "BS"
|
||||
case bh = "BH"
|
||||
case bd = "BD"
|
||||
case bb = "BB"
|
||||
case by = "BY"
|
||||
case be = "BE"
|
||||
case bz = "BZ"
|
||||
case bj = "BJ"
|
||||
case bm = "BM"
|
||||
case bt = "BT"
|
||||
case bo = "BO"
|
||||
case bq = "BQ"
|
||||
case ba = "BA"
|
||||
case bw = "BW"
|
||||
case bv = "BV"
|
||||
case br = "BR"
|
||||
case io = "IO"
|
||||
case bn = "BN"
|
||||
case bg = "BG"
|
||||
case bf = "BF"
|
||||
case bi = "BI"
|
||||
case cv = "CV"
|
||||
case kh = "KH"
|
||||
case cm = "CM"
|
||||
case ca = "CA"
|
||||
case ky = "KY"
|
||||
case cf = "CF"
|
||||
case td = "TD"
|
||||
case cl = "CL"
|
||||
case cn = "CN"
|
||||
case cx = "CX"
|
||||
case cc = "CC"
|
||||
case co = "CO"
|
||||
case km = "KM"
|
||||
case cg = "CG"
|
||||
case cd = "CD"
|
||||
case ck = "CK"
|
||||
case cr = "CR"
|
||||
case ci = "CI"
|
||||
case hr = "HR"
|
||||
case cu = "CU"
|
||||
case cw = "CW"
|
||||
case cy = "CY"
|
||||
case cz = "CZ"
|
||||
case dk = "DK"
|
||||
case dj = "DJ"
|
||||
case dm = "DM"
|
||||
case `do` = "DO"
|
||||
case ec = "EC"
|
||||
case eg = "EG"
|
||||
case sv = "SV"
|
||||
case gq = "GQ"
|
||||
case er = "ER"
|
||||
case ee = "EE"
|
||||
case et = "ET"
|
||||
case fk = "FK"
|
||||
case fo = "FO"
|
||||
case fj = "FJ"
|
||||
case fi = "FI"
|
||||
case fr = "FR"
|
||||
case gf = "GF"
|
||||
case pf = "PF"
|
||||
case tf = "TF"
|
||||
case ga = "GA"
|
||||
case gm = "GM"
|
||||
case ge = "GE"
|
||||
case de = "DE"
|
||||
case gh = "GH"
|
||||
case gi = "GI"
|
||||
case gr = "GR"
|
||||
case gl = "GL"
|
||||
case gd = "GD"
|
||||
case gp = "GP"
|
||||
case gu = "GU"
|
||||
case gt = "GT"
|
||||
case gg = "GG"
|
||||
case gn = "GN"
|
||||
case gw = "GW"
|
||||
case gy = "GY"
|
||||
case ht = "HT"
|
||||
case hm = "HM"
|
||||
case va = "VA"
|
||||
case hn = "HN"
|
||||
case hk = "HK"
|
||||
case hu = "HU"
|
||||
case `is` = "IS"
|
||||
case `in` = "IN"
|
||||
case id = "ID"
|
||||
case ir = "IR"
|
||||
case iq = "IQ"
|
||||
case ie = "IE"
|
||||
case im = "IM"
|
||||
case il = "IL"
|
||||
case it = "IT"
|
||||
case jm = "JM"
|
||||
case jp = "JP"
|
||||
case je = "JE"
|
||||
case jo = "JO"
|
||||
case kz = "KZ"
|
||||
case ke = "KE"
|
||||
case ki = "KI"
|
||||
case kp = "KP"
|
||||
case kr = "KR"
|
||||
case kw = "KW"
|
||||
case kg = "KG"
|
||||
case la = "LA"
|
||||
case lv = "LV"
|
||||
case lb = "LB"
|
||||
case ls = "LS"
|
||||
case lr = "LR"
|
||||
case ly = "LY"
|
||||
case li = "LI"
|
||||
case lt = "LT"
|
||||
case lu = "LU"
|
||||
case mo = "MO"
|
||||
case mk = "MK"
|
||||
case mg = "MG"
|
||||
case mw = "MW"
|
||||
case my = "MY"
|
||||
case mv = "MV"
|
||||
case ml = "ML"
|
||||
case mt = "MT"
|
||||
case mh = "MH"
|
||||
case mq = "MQ"
|
||||
case mr = "MR"
|
||||
case mu = "MU"
|
||||
case yt = "YT"
|
||||
case mx = "MX"
|
||||
case fm = "FM"
|
||||
case md = "MD"
|
||||
case mc = "MC"
|
||||
case mn = "MN"
|
||||
case me = "ME"
|
||||
case ms = "MS"
|
||||
case ma = "MA"
|
||||
case mz = "MZ"
|
||||
case mm = "MM"
|
||||
case na = "NA"
|
||||
case nr = "NR"
|
||||
case np = "NP"
|
||||
case nl = "NL"
|
||||
case nc = "NC"
|
||||
case nz = "NZ"
|
||||
case ni = "NI"
|
||||
case ne = "NE"
|
||||
case ng = "NG"
|
||||
case nu = "NU"
|
||||
case nf = "NF"
|
||||
case mp = "MP"
|
||||
case no = "NO"
|
||||
case om = "OM"
|
||||
case pk = "PK"
|
||||
case pw = "PW"
|
||||
case ps = "PS"
|
||||
case pa = "PA"
|
||||
case pg = "PG"
|
||||
case py = "PY"
|
||||
case pe = "PE"
|
||||
case ph = "PH"
|
||||
case pn = "PN"
|
||||
case pl = "PL"
|
||||
case pt = "PT"
|
||||
case pr = "PR"
|
||||
case qa = "QA"
|
||||
case re = "RE"
|
||||
case ro = "RO"
|
||||
case ru = "RU"
|
||||
case rw = "RW"
|
||||
case bl = "BL"
|
||||
case sh = "SH"
|
||||
case kn = "KN"
|
||||
case lc = "LC"
|
||||
case mf = "MF"
|
||||
case pm = "PM"
|
||||
case vc = "VC"
|
||||
case ws = "WS"
|
||||
case sm = "SM"
|
||||
case st = "ST"
|
||||
case sa = "SA"
|
||||
case sn = "SN"
|
||||
case rs = "RS"
|
||||
case sc = "SC"
|
||||
case sl = "SL"
|
||||
case sg = "SG"
|
||||
case sx = "SX"
|
||||
case sk = "SK"
|
||||
case si = "SI"
|
||||
case sb = "SB"
|
||||
case so = "SO"
|
||||
case za = "ZA"
|
||||
case gs = "GS"
|
||||
case ss = "SS"
|
||||
case es = "ES"
|
||||
case lk = "LK"
|
||||
case sd = "SD"
|
||||
case sr = "SR"
|
||||
case sj = "SJ"
|
||||
case sz = "SZ"
|
||||
case se = "SE"
|
||||
case ch = "CH"
|
||||
case sy = "SY"
|
||||
case tw = "TW"
|
||||
case tj = "TJ"
|
||||
case tz = "TZ"
|
||||
case th = "TH"
|
||||
case tl = "TL"
|
||||
case tg = "TG"
|
||||
case tk = "TK"
|
||||
case to = "TO"
|
||||
case tt = "TT"
|
||||
case tn = "TN"
|
||||
case tr = "TR"
|
||||
case tm = "TM"
|
||||
case tc = "TC"
|
||||
case tv = "TV"
|
||||
case ug = "UG"
|
||||
case ua = "UA"
|
||||
case ae = "AE"
|
||||
case gb = "GB"
|
||||
case us = "US"
|
||||
case um = "UM"
|
||||
case uy = "UY"
|
||||
case uz = "UZ"
|
||||
case vu = "VU"
|
||||
case ve = "VE"
|
||||
case vn = "VN"
|
||||
case vg = "VG"
|
||||
case vi = "VI"
|
||||
case wf = "WF"
|
||||
case eh = "EH"
|
||||
case ye = "YE"
|
||||
case zm = "ZM"
|
||||
case zw = "ZW"
|
||||
}
|
||||
|
||||
extension Country {
|
||||
var name: String {
|
||||
switch self {
|
||||
case .af: return "Afghanistan"
|
||||
case .ax: return "Åland Islands"
|
||||
case .al: return "Albania"
|
||||
case .dz: return "Algeria"
|
||||
case .as: return "American Samoa"
|
||||
case .ad: return "Andorra"
|
||||
case .ao: return "Angola"
|
||||
case .ai: return "Anguilla"
|
||||
case .aq: return "Antarctica"
|
||||
case .ag: return "Antigua and Barbuda"
|
||||
case .ar: return "Argentina"
|
||||
case .am: return "Armenia"
|
||||
case .aw: return "Aruba"
|
||||
case .au: return "Australia"
|
||||
case .at: return "Austria"
|
||||
case .az: return "Azerbaijan"
|
||||
case .bs: return "Bahamas"
|
||||
case .bh: return "Bahrain"
|
||||
case .bd: return "Bangladesh"
|
||||
case .bb: return "Barbados"
|
||||
case .by: return "Belarus"
|
||||
case .be: return "Belgium"
|
||||
case .bz: return "Belize"
|
||||
case .bj: return "Benin"
|
||||
case .bm: return "Bermuda"
|
||||
case .bt: return "Bhutan"
|
||||
case .bo: return "Bolivia (Plurinational State of)"
|
||||
case .bq: return "Bonaire, Sint Eustatius and Saba"
|
||||
case .ba: return "Bosnia and Herzegovina"
|
||||
case .bw: return "Botswana"
|
||||
case .bv: return "Bouvet Island"
|
||||
case .br: return "Brazil"
|
||||
case .io: return "British Indian Ocean Territory"
|
||||
case .bn: return "Brunei Darussalam"
|
||||
case .bg: return "Bulgaria"
|
||||
case .bf: return "Burkina Faso"
|
||||
case .bi: return "Burundi"
|
||||
case .cv: return "Cabo Verde"
|
||||
case .kh: return "Cambodia"
|
||||
case .cm: return "Cameroon"
|
||||
case .ca: return "Canada"
|
||||
case .ky: return "Cayman Islands"
|
||||
case .cf: return "Central African Republic"
|
||||
case .td: return "Chad"
|
||||
case .cl: return "Chile"
|
||||
case .cn: return "China"
|
||||
case .cx: return "Christmas Island"
|
||||
case .cc: return "Cocos (Keeling) Islands"
|
||||
case .co: return "Colombia"
|
||||
case .km: return "Comoros"
|
||||
case .cg: return "Congo"
|
||||
case .cd: return "Congo (Democratic Republic of the)"
|
||||
case .ck: return "Cook Islands"
|
||||
case .cr: return "Costa Rica"
|
||||
case .ci: return "Côte d'Ivoire"
|
||||
case .hr: return "Croatia"
|
||||
case .cu: return "Cuba"
|
||||
case .cw: return "Curaçao"
|
||||
case .cy: return "Cyprus"
|
||||
case .cz: return "Czechia"
|
||||
case .dk: return "Denmark"
|
||||
case .dj: return "Djibouti"
|
||||
case .dm: return "Dominica"
|
||||
case .do: return "Dominican Republic"
|
||||
case .ec: return "Ecuador"
|
||||
case .eg: return "Egypt"
|
||||
case .sv: return "El Salvador"
|
||||
case .gq: return "Equatorial Guinea"
|
||||
case .er: return "Eritrea"
|
||||
case .ee: return "Estonia"
|
||||
case .et: return "Ethiopia"
|
||||
case .fk: return "Falkland Islands (Malvinas)"
|
||||
case .fo: return "Faroe Islands"
|
||||
case .fj: return "Fiji"
|
||||
case .fi: return "Finland"
|
||||
case .fr: return "France"
|
||||
case .gf: return "French Guiana"
|
||||
case .pf: return "French Polynesia"
|
||||
case .tf: return "French Southern Territories"
|
||||
case .ga: return "Gabon"
|
||||
case .gm: return "Gambia"
|
||||
case .ge: return "Georgia"
|
||||
case .de: return "Germany"
|
||||
case .gh: return "Ghana"
|
||||
case .gi: return "Gibraltar"
|
||||
case .gr: return "Greece"
|
||||
case .gl: return "Greenland"
|
||||
case .gd: return "Grenada"
|
||||
case .gp: return "Guadeloupe"
|
||||
case .gu: return "Guam"
|
||||
case .gt: return "Guatemala"
|
||||
case .gg: return "Guernsey"
|
||||
case .gn: return "Guinea"
|
||||
case .gw: return "Guinea-Bissau"
|
||||
case .gy: return "Guyana"
|
||||
case .ht: return "Haiti"
|
||||
case .hm: return "Heard Island and McDonald Islands"
|
||||
case .va: return "Holy See"
|
||||
case .hn: return "Honduras"
|
||||
case .hk: return "Hong Kong"
|
||||
case .hu: return "Hungary"
|
||||
case .is: return "Iceland"
|
||||
case .in: return "India"
|
||||
case .id: return "Indonesia"
|
||||
case .ir: return "Iran (Islamic Republic of)"
|
||||
case .iq: return "Iraq"
|
||||
case .ie: return "Ireland"
|
||||
case .im: return "Isle of Man"
|
||||
case .il: return "Israel"
|
||||
case .it: return "Italy"
|
||||
case .jm: return "Jamaica"
|
||||
case .jp: return "Japan"
|
||||
case .je: return "Jersey"
|
||||
case .jo: return "Jordan"
|
||||
case .kz: return "Kazakhstan"
|
||||
case .ke: return "Kenya"
|
||||
case .ki: return "Kiribati"
|
||||
case .kp: return "Korea (Democratic People's Republic of)"
|
||||
case .kr: return "Korea (Republic of)"
|
||||
case .kw: return "Kuwait"
|
||||
case .kg: return "Kyrgyzstan"
|
||||
case .la: return "Lao People's Democratic Republic"
|
||||
case .lv: return "Latvia"
|
||||
case .lb: return "Lebanon"
|
||||
case .ls: return "Lesotho"
|
||||
case .lr: return "Liberia"
|
||||
case .ly: return "Libya"
|
||||
case .li: return "Liechtenstein"
|
||||
case .lt: return "Lithuania"
|
||||
case .lu: return "Luxembourg"
|
||||
case .mo: return "Macao"
|
||||
case .mk: return "Macedonia (the former Yugoslav Republic of)"
|
||||
case .mg: return "Madagascar"
|
||||
case .mw: return "Malawi"
|
||||
case .my: return "Malaysia"
|
||||
case .mv: return "Maldives"
|
||||
case .ml: return "Mali"
|
||||
case .mt: return "Malta"
|
||||
case .mh: return "Marshall Islands"
|
||||
case .mq: return "Martinique"
|
||||
case .mr: return "Mauritania"
|
||||
case .mu: return "Mauritius"
|
||||
case .yt: return "Mayotte"
|
||||
case .mx: return "Mexico"
|
||||
case .fm: return "Micronesia (Federated States of)"
|
||||
case .md: return "Moldova (Republic of)"
|
||||
case .mc: return "Monaco"
|
||||
case .mn: return "Mongolia"
|
||||
case .me: return "Montenegro"
|
||||
case .ms: return "Montserrat"
|
||||
case .ma: return "Morocco"
|
||||
case .mz: return "Mozambique"
|
||||
case .mm: return "Myanmar"
|
||||
case .na: return "Namibia"
|
||||
case .nr: return "Nauru"
|
||||
case .np: return "Nepal"
|
||||
case .nl: return "Netherlands"
|
||||
case .nc: return "New Caledonia"
|
||||
case .nz: return "New Zealand"
|
||||
case .ni: return "Nicaragua"
|
||||
case .ne: return "Niger"
|
||||
case .ng: return "Nigeria"
|
||||
case .nu: return "Niue"
|
||||
case .nf: return "Norfolk Island"
|
||||
case .mp: return "Northern Mariana Islands"
|
||||
case .no: return "Norway"
|
||||
case .om: return "Oman"
|
||||
case .pk: return "Pakistan"
|
||||
case .pw: return "Palau"
|
||||
case .ps: return "Palestine, State of"
|
||||
case .pa: return "Panama"
|
||||
case .pg: return "Papua New Guinea"
|
||||
case .py: return "Paraguay"
|
||||
case .pe: return "Peru"
|
||||
case .ph: return "Philippines"
|
||||
case .pn: return "Pitcairn"
|
||||
case .pl: return "Poland"
|
||||
case .pt: return "Portugal"
|
||||
case .pr: return "Puerto Rico"
|
||||
case .qa: return "Qatar"
|
||||
case .re: return "Réunion"
|
||||
case .ro: return "Romania"
|
||||
case .ru: return "Russian Federation"
|
||||
case .rw: return "Rwanda"
|
||||
case .bl: return "Saint Barthélemy"
|
||||
case .sh: return "Saint Helena, Ascension and Tristan da Cunha"
|
||||
case .kn: return "Saint Kitts and Nevis"
|
||||
case .lc: return "Saint Lucia"
|
||||
case .mf: return "Saint Martin (French part)"
|
||||
case .pm: return "Saint Pierre and Miquelon"
|
||||
case .vc: return "Saint Vincent and the Grenadines"
|
||||
case .ws: return "Samoa"
|
||||
case .sm: return "San Marino"
|
||||
case .st: return "Sao Tome and Principe"
|
||||
case .sa: return "Saudi Arabia"
|
||||
case .sn: return "Senegal"
|
||||
case .rs: return "Serbia"
|
||||
case .sc: return "Seychelles"
|
||||
case .sl: return "Sierra Leone"
|
||||
case .sg: return "Singapore"
|
||||
case .sx: return "Sint Maarten (Dutch part)"
|
||||
case .sk: return "Slovakia"
|
||||
case .si: return "Slovenia"
|
||||
case .sb: return "Solomon Islands"
|
||||
case .so: return "Somalia"
|
||||
case .za: return "South Africa"
|
||||
case .gs: return "South Georgia and the South Sandwich Islands"
|
||||
case .ss: return "South Sudan"
|
||||
case .es: return "Spain"
|
||||
case .lk: return "Sri Lanka"
|
||||
case .sd: return "Sudan"
|
||||
case .sr: return "Suriname"
|
||||
case .sj: return "Svalbard and Jan Mayen"
|
||||
case .sz: return "Swaziland"
|
||||
case .se: return "Sweden"
|
||||
case .ch: return "Switzerland"
|
||||
case .sy: return "Syrian Arab Republic"
|
||||
case .tw: return "Taiwan, Province of China[a]"
|
||||
case .tj: return "Tajikistan"
|
||||
case .tz: return "Tanzania, United Republic of"
|
||||
case .th: return "Thailand"
|
||||
case .tl: return "Timor-Leste"
|
||||
case .tg: return "Togo"
|
||||
case .tk: return "Tokelau"
|
||||
case .to: return "Tonga"
|
||||
case .tt: return "Trinidad and Tobago"
|
||||
case .tn: return "Tunisia"
|
||||
case .tr: return "Turkey"
|
||||
case .tm: return "Turkmenistan"
|
||||
case .tc: return "Turks and Caicos Islands"
|
||||
case .tv: return "Tuvalu"
|
||||
case .ug: return "Uganda"
|
||||
case .ua: return "Ukraine"
|
||||
case .ae: return "United Arab Emirates"
|
||||
case .gb: return "United Kingdom of Great Britain and Northern Ireland"
|
||||
case .us: return "United States of America"
|
||||
case .um: return "United States Minor Outlying Islands"
|
||||
case .uy: return "Uruguay"
|
||||
case .uz: return "Uzbekistan"
|
||||
case .vu: return "Vanuatu"
|
||||
case .ve: return "Venezuela (Bolivarian Republic of)"
|
||||
case .vn: return "Viet Nam"
|
||||
case .vg: return "Virgin Islands (British)"
|
||||
case .vi: return "Virgin Islands (U.S.)"
|
||||
case .wf: return "Wallis and Futuna"
|
||||
case .eh: return "Western Sahara"
|
||||
case .ye: return "Yemen"
|
||||
case .zm: return "Zambia"
|
||||
case .zw: return "Zimbabwe"
|
||||
}
|
||||
}
|
||||
|
||||
var flag: String {
|
||||
let unicodeScalars = rawValue
|
||||
.unicodeScalars
|
||||
.map { $0.value + 0x1F1E6 - 65 }
|
||||
.compactMap(UnicodeScalar.init)
|
||||
var result = ""
|
||||
result.unicodeScalars.append(contentsOf: unicodeScalars)
|
||||
return result
|
||||
}
|
||||
|
||||
static func searchByName(_ name: String) -> [Country] {
|
||||
let countries = filteredCountries { stringFolding($0) == stringFolding(name) }
|
||||
|
||||
return countries.isEmpty ? searchByPartialName(name) : countries
|
||||
}
|
||||
|
||||
static func searchByPartialName(_ name: String) -> [Country] {
|
||||
guard name.count >= 2 else {
|
||||
return []
|
||||
}
|
||||
|
||||
return filteredCountries { stringFolding($0).contains(name) }
|
||||
}
|
||||
|
||||
private static func stringFolding(_ string: String) -> String {
|
||||
string.folding(options: [.diacriticInsensitive, .caseInsensitive], locale: .current)
|
||||
}
|
||||
|
||||
private static func filteredCountries(_ predicate: (String) -> Bool) -> [Country] {
|
||||
Country.allCases.map { $0.name }
|
||||
.filter(predicate)
|
||||
.compactMap { string in Country.allCases.first { $0.name == string } }
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import Foundation
|
||||
|
||||
enum TabSelection {
|
||||
case subscriptions, popular, channel, search
|
||||
case subscriptions, popular, trending, channel, search
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user