mirror of
https://github.com/yattee/yattee.git
synced 2024-11-10 00:08:21 +00:00
e35f8b7892
This gives a huge increase in perceived performance. The UI is now much more responsive since some tasks are run in the background and don't block the UI anymore.
258 lines
9.0 KiB
Swift
258 lines
9.0 KiB
Swift
import Defaults
|
|
import MediaPlayer
|
|
import PINCache
|
|
import SDWebImage
|
|
import SDWebImageWebPCoder
|
|
import Siesta
|
|
import SwiftUI
|
|
|
|
@main
|
|
struct YatteeApp: App {
|
|
static var version: String {
|
|
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "unknown"
|
|
}
|
|
|
|
static var build: String {
|
|
Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "unknown"
|
|
}
|
|
|
|
static var isForPreviews: Bool {
|
|
ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
|
|
}
|
|
|
|
static var logsDirectory: URL {
|
|
temporaryDirectory
|
|
}
|
|
|
|
static var settingsExportDirectory: URL {
|
|
temporaryDirectory
|
|
}
|
|
|
|
private static var temporaryDirectory: URL {
|
|
URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
}
|
|
|
|
#if os(macOS)
|
|
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
|
#elseif os(iOS)
|
|
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
|
#endif
|
|
|
|
@State private var configured = false
|
|
|
|
@StateObject private var accounts = AccountsModel.shared
|
|
@StateObject private var comments = CommentsModel.shared
|
|
@StateObject private var instances = InstancesModel.shared
|
|
@StateObject private var menu = MenuModel.shared
|
|
@StateObject private var navigation = NavigationModel.shared
|
|
@StateObject private var networkState = NetworkStateModel.shared
|
|
@StateObject private var player = PlayerModel.shared
|
|
@StateObject private var playlists = PlaylistsModel.shared
|
|
@StateObject private var recents = RecentsModel.shared
|
|
@StateObject private var settings = SettingsModel.shared
|
|
@StateObject private var subscriptions = SubscribedChannelsModel.shared
|
|
@StateObject private var thumbnails = ThumbnailsModel.shared
|
|
|
|
let persistenceController = PersistenceController.shared
|
|
|
|
var favorites: FavoritesModel { .shared }
|
|
var playerControls: PlayerControlsModel { .shared }
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
ContentView()
|
|
.onAppear(perform: configure)
|
|
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
|
.environment(\.navigationStyle, navigationStyle)
|
|
#if os(macOS)
|
|
.background(
|
|
HostingWindowFinder { window in
|
|
Windows.mainWindow = window
|
|
}
|
|
)
|
|
#else
|
|
.onReceive(
|
|
NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)
|
|
) { _ in
|
|
player.handleEnterForeground()
|
|
}
|
|
.onReceive(
|
|
NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)
|
|
) { _ in
|
|
player.handleEnterBackground()
|
|
}
|
|
#endif
|
|
#if os(iOS)
|
|
.handlesExternalEvents(preferring: Set(["*"]), allowing: Set(["*"]))
|
|
#endif
|
|
#if !os(tvOS)
|
|
.onOpenURL { url in
|
|
URLBookmarkModel.shared.saveBookmark(url)
|
|
OpenURLHandler(navigationStyle: navigationStyle).handle(url)
|
|
}
|
|
#endif
|
|
}
|
|
#if os(iOS)
|
|
.handlesExternalEvents(matching: Set(["*"]))
|
|
#endif
|
|
#if !os(tvOS)
|
|
.commands {
|
|
SidebarCommands()
|
|
|
|
CommandGroup(replacing: .newItem, addition: {})
|
|
|
|
MenuCommands(model: Binding<MenuModel>(get: { MenuModel.shared }, set: { _ in }))
|
|
}
|
|
#endif
|
|
|
|
#if os(macOS)
|
|
WindowGroup(player.windowTitle) {
|
|
VideoPlayerView()
|
|
.onAppear(perform: configure)
|
|
.background(
|
|
HostingWindowFinder { window in
|
|
Windows.playerWindow = window
|
|
|
|
NotificationCenter.default.addObserver( // swiftlint:disable:this discarded_notification_center_observer
|
|
forName: NSWindow.willExitFullScreenNotification,
|
|
object: window,
|
|
queue: OperationQueue.main
|
|
) { _ in
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
self.player.playingFullScreen = false
|
|
}
|
|
}
|
|
}
|
|
)
|
|
.onAppear { player.presentingPlayer = true }
|
|
.onDisappear { player.presentingPlayer = false }
|
|
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
|
.environment(\.navigationStyle, .sidebar)
|
|
.handlesExternalEvents(preferring: Set(["player", "*"]), allowing: Set(["player", "*"]))
|
|
.onOpenURL { url in
|
|
URLBookmarkModel.shared.saveBookmark(url)
|
|
OpenURLHandler(navigationStyle: navigationStyle).handle(url)
|
|
}
|
|
}
|
|
.handlesExternalEvents(matching: Set(["player", "*"]))
|
|
|
|
Settings {
|
|
SettingsView()
|
|
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
func configure() {
|
|
guard !Self.isForPreviews, !configured else {
|
|
return
|
|
}
|
|
configured = true
|
|
|
|
DispatchQueue.main.async {
|
|
#if DEBUG
|
|
SiestaLog.Category.enabled = .common
|
|
#endif
|
|
SDImageCodersManager.shared.addCoder(SDImageAWebPCoder.shared)
|
|
SDWebImageManager.defaultImageCache = PINCache(name: "stream.yattee.app")
|
|
|
|
if !Defaults[.lastAccountIsPublic] {
|
|
AccountsModel.shared.configureAccount()
|
|
}
|
|
|
|
if let countryOfPublicInstances = Defaults[.countryOfPublicInstances] {
|
|
InstancesManifest.shared.setPublicAccount(countryOfPublicInstances, asCurrent: AccountsModel.shared.current.isNil)
|
|
}
|
|
|
|
if !AccountsModel.shared.current.isNil {
|
|
player.restoreQueue()
|
|
}
|
|
|
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
if !Defaults[.saveRecents] {
|
|
recents.clear()
|
|
}
|
|
}
|
|
|
|
let startupSection = Defaults[.startupSection]
|
|
var section: TabSelection? = startupSection.tabSelection
|
|
|
|
#if os(macOS)
|
|
if section == .playlists {
|
|
section = .search
|
|
}
|
|
#endif
|
|
|
|
NavigationModel.shared.tabSelection = section ?? .search
|
|
|
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
playlists.load()
|
|
}
|
|
|
|
#if !os(macOS)
|
|
player.updateRemoteCommandCenter()
|
|
#endif
|
|
|
|
if player.presentingPlayer {
|
|
player.presentingPlayer = false
|
|
}
|
|
|
|
#if os(iOS)
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
if Defaults[.lockPortraitWhenBrowsing] {
|
|
Orientation.lockOrientation(.all, andRotateTo: .portrait)
|
|
}
|
|
}
|
|
#endif
|
|
|
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
URLBookmarkModel.shared.refreshAll()
|
|
}
|
|
|
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
self.migrateHomeHistoryItems()
|
|
}
|
|
|
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
self.migrateQualityProfiles()
|
|
}
|
|
}
|
|
}
|
|
|
|
func migrateHomeHistoryItems() {
|
|
guard Defaults[.homeHistoryItems] > 0 else { return }
|
|
|
|
if favorites.addableItems().contains(where: { $0.section == .history }) {
|
|
let historyItem = FavoriteItem(section: .history)
|
|
favorites.add(historyItem)
|
|
favorites.setListingStyle(.list, historyItem)
|
|
favorites.setLimit(Defaults[.homeHistoryItems], historyItem)
|
|
|
|
print("migrated home history items: \(favorites.limit(historyItem))")
|
|
}
|
|
|
|
Defaults[.homeHistoryItems] = -1
|
|
}
|
|
|
|
@Default(.qualityProfiles) private var qualityProfilesData
|
|
|
|
func migrateQualityProfiles() {
|
|
for profile in qualityProfilesData where profile.order.isEmpty {
|
|
var updatedProfile = profile
|
|
updatedProfile.order = Array(QualityProfile.Format.allCases.indices)
|
|
QualityProfilesModel.shared.update(profile, updatedProfile)
|
|
}
|
|
}
|
|
|
|
var navigationStyle: NavigationStyle {
|
|
#if os(iOS)
|
|
return horizontalSizeClass == .compact ? .tab : .sidebar
|
|
#elseif os(tvOS)
|
|
return .tab
|
|
#else
|
|
return .sidebar
|
|
#endif
|
|
}
|
|
}
|