2021-07-12 02:22:49 +05:30
import Foundation
2022-12-16 14:05:10 +05:30
import Siesta
2021-07-12 02:22:49 +05:30
import SwiftUI
2021-09-25 13:48:22 +05:30
final class NavigationModel : ObservableObject {
2022-11-25 02:06:05 +05:30
static var shared = NavigationModel ( )
var player = PlayerModel . shared
var recents = RecentsModel . shared
var search = SearchModel . shared
2022-08-15 18:19:12 +05:30
2021-08-30 03:06:18 +05:30
enum TabSelection : Hashable {
2022-11-09 19:04:04 +05:30
case home
2022-11-13 04:31:04 +05:30
case documents
2021-10-06 01:50:09 +05:30
case subscriptions
case popular
case trending
case playlists
case channel ( String )
case playlist ( String )
case recentlyOpened ( String )
case nowPlaying
case search
2022-06-26 18:47:18 +05:30
#if os ( tvOS )
case settings
#endif
2021-10-25 03:06:24 +05:30
2022-03-28 00:08:59 +05:30
var stringValue : String {
switch self {
2022-11-09 19:04:04 +05:30
case . home :
2022-03-28 00:08:59 +05:30
return " favorites "
case . subscriptions :
return " subscriptions "
case . popular :
return " popular "
case . trending :
return " trending "
case . playlists :
return " playlists "
case let . channel ( string ) :
return " channel \( string ) "
case let . playlist ( string ) :
return " playlist \( string ) "
case . recentlyOpened :
return " recentlyOpened "
case . search :
return " search "
2022-06-26 18:47:18 +05:30
#if os ( tvOS )
2023-04-22 18:38:33 +05:30
case . settings :
2022-06-26 18:47:18 +05:30
return " settings "
#endif
2022-03-28 00:08:59 +05:30
default :
return " "
}
}
2021-10-25 03:06:24 +05:30
var playlistID : Playlist . ID ? {
if case let . playlist ( id ) = self {
return id
}
return nil
}
2021-08-30 03:06:18 +05:30
}
2023-05-27 02:48:55 +05:30
@ Published var tabSelection : TabSelection ! { didSet {
if oldValue = = tabSelection { multipleTapHandler ( ) }
2023-09-24 01:19:41 +05:30
if tabSelection = = nil , let item = recents . presentedItem {
2023-09-24 14:44:24 +05:30
Delay . by ( 0.2 ) { [ weak self ] in
2023-09-24 01:19:41 +05:30
self ? . tabSelection = . recentlyOpened ( item . tag )
}
}
2023-05-27 02:48:55 +05:30
} }
2021-07-12 02:22:49 +05:30
2021-09-28 23:36:05 +05:30
@ Published var presentingAddToPlaylist = false
@ Published var videoToAddToPlaylist : Video !
2021-08-30 03:06:18 +05:30
@ Published var presentingPlaylistForm = false
@ Published var editedPlaylist : Playlist !
@ Published var presentingUnsubscribeAlert = false
@ Published var channelToUnsubscribe : Channel !
2021-10-23 04:34:03 +05:30
@ Published var presentingChannel = false
@ Published var presentingPlaylist = false
2021-09-01 02:47:50 +05:30
@ Published var sidebarSectionChanged = false
2022-12-22 01:46:47 +05:30
@ Published var presentingPlaybackSettings = false
2022-11-10 22:41:28 +05:30
@ Published var presentingOpenVideos = false
2021-09-25 13:48:22 +05:30
@ Published var presentingSettings = false
2022-12-12 03:45:56 +05:30
@ Published var presentingAccounts = false
2021-10-18 04:36:00 +05:30
@ Published var presentingWelcomeScreen = false
2023-05-25 17:58:29 +05:30
@ Published var presentingHomeSettings = false
2021-09-25 13:48:22 +05:30
2023-04-22 14:26:42 +05:30
@ Published var presentingChannelSheet = false
@ Published var channelPresentedInSheet : Channel !
2022-06-26 17:27:02 +05:30
@ Published var presentingShareSheet = false
@ Published var shareURL : URL ?
2022-06-25 04:18:57 +05:30
@ Published var alert = Alert ( title : Text ( " Error " ) )
2022-06-18 18:09:49 +05:30
@ Published var presentingAlert = false
2022-11-11 23:20:13 +05:30
@ Published var presentingAlertInOpenVideos = false
2022-06-25 04:18:57 +05:30
#if os ( macOS )
@ Published var presentingAlertInVideoPlayer = false
#endif
2022-06-18 18:09:49 +05:30
2022-11-11 23:20:13 +05:30
@ Published var presentingFileImporter = false
2024-02-02 04:24:16 +05:30
@ Published var presentingSettingsImportSheet = false
@ Published var presentingSettingsFileImporter = false
@ Published var settingsImportURL : URL ?
2022-11-25 02:06:05 +05:30
func openChannel ( _ channel : Channel , navigationStyle : NavigationStyle ) {
2022-04-16 23:14:07 +05:30
guard channel . id != Video . fixtureChannelID else {
return
}
2022-11-25 02:06:05 +05:30
hideKeyboard ( )
2022-08-20 03:25:02 +05:30
let presentingPlayer = player . presentingPlayer
2022-11-25 02:06:05 +05:30
presentingChannel = false
2022-05-29 23:56:56 +05:30
2021-12-19 22:47:04 +05:30
#if os ( macOS )
2022-01-06 21:05:45 +05:30
Windows . main . open ( )
2021-12-19 22:47:04 +05:30
#endif
2021-12-17 22:04:55 +05:30
2022-07-10 23:21:46 +05:30
let recent = RecentItem ( from : channel )
recents . add ( RecentItem ( from : channel ) )
2023-04-22 14:26:42 +05:30
let navigateToChannel = {
2022-08-20 03:25:02 +05:30
#if os ( iOS )
2023-04-22 14:26:42 +05:30
self . player . hide ( )
2022-08-20 03:25:02 +05:30
#endif
2023-04-22 14:26:42 +05:30
if navigationStyle = = . sidebar {
self . sidebarSectionChanged . toggle ( )
self . tabSelection = . recentlyOpened ( recent . tag )
} else {
2022-08-25 22:39:55 +05:30
withAnimation ( Constants . overlayAnimation ) {
2022-11-25 02:06:05 +05:30
self . presentingChannel = true
2022-08-20 03:25:02 +05:30
}
2022-06-30 13:35:32 +05:30
}
2022-01-06 22:25:56 +05:30
}
2023-04-22 14:26:42 +05:30
#if os ( iOS )
if presentingPlayer {
presentChannelInSheet ( channel )
} else {
navigateToChannel ( )
}
2023-05-23 02:31:54 +05:30
#elseif os ( tvOS )
Delay . by ( 0.01 ) {
navigateToChannel ( )
}
2023-04-22 14:26:42 +05:30
#else
navigateToChannel ( )
#endif
2022-01-06 22:25:56 +05:30
}
2022-11-25 02:06:05 +05:30
func openChannelPlaylist ( _ playlist : ChannelPlaylist , navigationStyle : NavigationStyle ) {
presentingChannel = false
presentingPlaylist = false
2022-05-30 00:39:57 +05:30
2022-01-06 22:25:56 +05:30
let recent = RecentItem ( from : playlist )
#if os ( macOS )
Windows . main . open ( )
#else
player . hide ( )
#endif
2022-11-25 02:06:05 +05:30
hideKeyboard ( )
2022-11-27 16:12:16 +05:30
presentingChannel = false
2022-08-20 03:25:02 +05:30
let presentingPlayer = player . presentingPlayer
player . hide ( )
2022-08-10 00:44:05 +05:30
2022-11-25 02:06:05 +05:30
DispatchQueue . main . asyncAfter ( deadline : . now ( ) + 0.2 ) { [ weak self ] in
guard let self else { return }
self . recents . add ( recent )
2022-06-30 13:35:32 +05:30
if navigationStyle = = . sidebar {
2022-11-25 02:06:05 +05:30
self . sidebarSectionChanged . toggle ( )
self . tabSelection = . recentlyOpened ( recent . tag )
2022-06-30 13:35:32 +05:30
} else {
2022-08-20 03:25:02 +05:30
var delay = 0.0
#if os ( iOS )
if presentingPlayer { delay = 1.0 }
#endif
DispatchQueue . main . asyncAfter ( deadline : . now ( ) + delay ) {
2022-08-25 22:39:55 +05:30
withAnimation ( Constants . overlayAnimation ) {
2022-11-25 02:06:05 +05:30
self . presentingPlaylist = true
2022-08-20 03:25:02 +05:30
}
2022-07-09 05:51:04 +05:30
}
2022-06-30 13:35:32 +05:30
}
2022-01-06 22:25:56 +05:30
}
2022-06-25 04:18:57 +05:30
}
2022-11-25 02:06:05 +05:30
func openSearchQuery ( _ searchQuery : String ? ) {
presentingChannel = false
presentingPlaylist = false
tabSelection = . search
2022-06-25 04:18:57 +05:30
2022-11-25 02:06:05 +05:30
hideKeyboard ( )
2022-08-10 00:44:05 +05:30
2022-08-20 03:25:02 +05:30
let presentingPlayer = player . presentingPlayer
player . hide ( )
2022-09-28 19:57:01 +05:30
if let searchQuery {
2022-06-25 04:18:57 +05:30
let recent = RecentItem ( from : searchQuery )
recents . add ( recent )
2022-01-06 22:25:56 +05:30
2022-08-20 03:25:02 +05:30
var delay = 0.0
#if os ( iOS )
if presentingPlayer { delay = 1.0 }
#endif
2022-11-25 02:06:05 +05:30
DispatchQueue . main . asyncAfter ( deadline : . now ( ) + delay ) { [ weak self ] in
guard let self else { return }
self . search . queryText = searchQuery
self . search . changeQuery { query in query . query = searchQuery }
2021-12-17 22:04:55 +05:30
}
}
2022-06-25 04:18:57 +05:30
#if os ( macOS )
DispatchQueue . main . asyncAfter ( deadline : . now ( ) + 0.5 ) {
Windows . main . focus ( )
}
#endif
2021-12-17 22:04:55 +05:30
}
2021-09-29 04:31:49 +05:30
var tabSelectionBinding : Binding < TabSelection > {
Binding < TabSelection > (
2021-07-12 02:22:49 +05:30
get : {
2021-12-20 05:06:12 +05:30
self . tabSelection ? ? . search
2021-07-12 02:22:49 +05:30
} ,
2021-09-01 02:47:50 +05:30
set : { newValue in
2021-09-29 04:31:49 +05:30
self . tabSelection = newValue
2021-07-12 02:22:49 +05:30
}
)
}
2021-08-30 03:06:18 +05:30
2021-09-28 23:36:05 +05:30
func presentAddToPlaylist ( _ video : Video ) {
videoToAddToPlaylist = video
presentingAddToPlaylist = true
}
2021-08-30 03:06:18 +05:30
func presentEditPlaylistForm ( _ playlist : Playlist ? ) {
editedPlaylist = playlist
presentingPlaylistForm = editedPlaylist != nil
}
func presentNewPlaylistForm ( ) {
editedPlaylist = nil
presentingPlaylistForm = true
}
2022-12-11 20:45:42 +05:30
func presentUnsubscribeAlert ( _ channel : Channel , subscriptions : SubscribedChannelsModel ) {
2021-08-30 03:06:18 +05:30
channelToUnsubscribe = channel
2022-06-25 04:51:05 +05:30
alert = Alert (
title : Text (
" Are you sure you want to unsubscribe from \( channelToUnsubscribe . name ) ? "
) ,
primaryButton : . destructive ( Text ( " Unsubscribe " ) ) { [ weak self ] in
if let id = self ? . channelToUnsubscribe . id {
subscriptions . unsubscribe ( id )
}
} ,
secondaryButton : . cancel ( )
)
presentingAlert = true
2021-08-30 03:06:18 +05:30
}
2022-03-26 19:52:29 +05:30
2022-12-11 20:30:20 +05:30
func hideViewsAboveBrowser ( ) {
player . hide ( )
presentingChannel = false
presentingPlaylist = false
presentingOpenVideos = false
2024-02-02 04:24:16 +05:30
presentingFileImporter = false
presentingSettingsImportSheet = false
2022-12-11 20:30:20 +05:30
}
2022-03-26 19:52:29 +05:30
func hideKeyboard ( ) {
#if os ( iOS )
UIApplication . shared . sendAction ( #selector ( UIResponder . resignFirstResponder ) , to : nil , from : nil , for : nil )
#endif
}
2022-06-18 18:09:49 +05:30
2022-07-02 02:58:32 +05:30
func presentAlert ( title : String , message : String ? = nil ) {
let message = message . isNil ? nil : Text ( message ! )
2024-02-02 04:24:16 +05:30
let alert = Alert ( title : Text ( title ) , message : message )
presentAlert ( alert )
2022-06-18 18:09:49 +05:30
}
2022-06-26 17:27:02 +05:30
2022-12-16 14:05:10 +05:30
func presentRequestErrorAlert ( _ error : RequestError ) {
let errorDescription = String ( format : " Verify you have stable connection with the server you are using (%@) " , AccountsModel . shared . current . instance . longDescription )
presentAlert ( title : " Connection Error " , message : " \( error . userMessage ) \n \n \( errorDescription ) " )
}
2022-08-21 21:09:06 +05:30
func presentAlert ( _ alert : Alert ) {
2024-02-02 04:24:16 +05:30
guard ! presentingSettings else {
SettingsModel . shared . presentAlert ( alert )
return
}
2022-08-21 21:09:06 +05:30
self . alert = alert
presentingAlert = true
}
2022-06-26 17:27:02 +05:30
func presentShareSheet ( _ url : URL ) {
shareURL = url
presentingShareSheet = true
}
2023-04-22 14:26:42 +05:30
func presentChannelInSheet ( _ channel : Channel ) {
channelPresentedInSheet = channel
presentingChannelSheet = true
}
2023-05-27 02:48:55 +05:30
func multipleTapHandler ( ) {
switch tabSelection {
case . search :
self . search . focused = true
default :
print ( " not implemented " )
}
}
2024-02-02 04:24:16 +05:30
func presentSettingsImportSheet ( _ url : URL , forceSettings : Bool = false ) {
guard ! presentingSettings , ! forceSettings else {
ImportExportSettingsModel . shared . reset ( )
SettingsModel . shared . presentSettingsImportSheet ( url )
return
}
settingsImportURL = url
presentingSettingsImportSheet = true
}
2021-07-12 02:22:49 +05:30
}
2021-08-30 03:06:18 +05:30
2021-09-25 13:48:22 +05:30
typealias TabSelection = NavigationModel . TabSelection