Skip to content

Commit

Permalink
Commit dump
Browse files Browse the repository at this point in the history
* Noifications implementation
* App delegate creation
* Add Credits file (shows in about page)
* Logical improvements
* Add support for force quitting all games upon app termination
  • Loading branch information
vapidinfinity committed Feb 25, 2024
1 parent 8f1d66e commit 4d1a571
Show file tree
Hide file tree
Showing 20 changed files with 201 additions and 23 deletions.
14 changes: 11 additions & 3 deletions Mythic.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
6A4C396E2AC5DA4D002F943B /* GameSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A4C396D2AC5DA4D002F943B /* GameSettings.swift */; };
6A634B6E2AE951DC00EAC63C /* LibrariesExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A634B6D2AE951DC00EAC63C /* LibrariesExt.swift */; };
6A6923522AD6D83D00157E3E /* Global.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A6923512AD6D83D00157E3E /* Global.swift */; };
6A721B2B2B8A4BD600A4EA3C /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 6A721B2A2B8A4BD600A4EA3C /* Credits.rtf */; };
6A721B2D2B8B3D5A00A4EA3C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A721B2C2B8B3D5A00A4EA3C /* AppDelegate.swift */; };
6A7A81132B76F9E900D19E32 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A7A81122B76F9E900D19E32 /* Task.swift */; };
6A7A81162B77093600D19E32 /* ColorfulX in Frameworks */ = {isa = PBXBuildFile; productRef = 6A7A81152B77093600D19E32 /* ColorfulX */; };
6A7A81182B77097200D19E32 /* OnboardingEvo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A7A81172B77097200D19E32 /* OnboardingEvo.swift */; };
Expand Down Expand Up @@ -100,6 +102,8 @@
6A4C396D2AC5DA4D002F943B /* GameSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameSettings.swift; sourceTree = "<group>"; };
6A634B6D2AE951DC00EAC63C /* LibrariesExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibrariesExt.swift; sourceTree = "<group>"; };
6A6923512AD6D83D00157E3E /* Global.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Global.swift; sourceTree = "<group>"; };
6A721B2A2B8A4BD600A4EA3C /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
6A721B2C2B8B3D5A00A4EA3C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6A7A81122B76F9E900D19E32 /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
6A7A81172B77097200D19E32 /* OnboardingEvo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingEvo.swift; sourceTree = "<group>"; };
6A7F00B02B231EDF00D801CD /* StopDownloadAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopDownloadAlert.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -384,6 +388,7 @@
isa = PBXGroup;
children = (
6AC25CBE2AAEFF5100D395CF /* Info.plist */,
6A721B2C2B8B3D5A00A4EA3C /* AppDelegate.swift */,
6AB474982AACBBE900AB9C63 /* MythicApp.swift */,
6AF0EB1D2AAD4DD70044C09C /* Utilities */,
6AB474A92AACBCD000AB9C63 /* Views */,
Expand All @@ -395,6 +400,7 @@
6AB4749C2AACBBEA00AB9C63 /* Assets.xcassets */,
6A85A14E2B452B9400E05D83 /* Localizable.xcstrings */,
6AB474A12AACBBEA00AB9C63 /* Mythic.entitlements */,
6A721B2A2B8A4BD600A4EA3C /* Credits.rtf */,
6AB4749E2AACBBEA00AB9C63 /* Preview Content */,
);
path = Mythic;
Expand All @@ -411,14 +417,14 @@
6AB474A92AACBCD000AB9C63 /* Views */ = {
isa = PBXGroup;
children = (
6AAAFBA72B8323940072B5BB /* BottleList.swift */,
6A00F2012AC5F51A0054858A /* GameList */,
6AF0EB2B2AADE2530044C09C /* WebView.swift */,
6AF0EB202AAD4F1E0044C09C /* NotImplemented.swift */,
6AF0EB1C2AAD4C830044C09C /* Sheets */,
6A7F00B22B231EEA00D801CD /* Alerts */,
6AD506542AAFF52B008A28C1 /* Navigation */,
6A12FF8F2B73AFCE00AA948C /* BottleSettings.swift */,
6AAAFBA72B8323940072B5BB /* BottleList.swift */,
6A8109DD2B822B9E00DF5034 /* InstallationProgress.swift */,
);
path = Views;
Expand Down Expand Up @@ -564,6 +570,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6A721B2B2B8A4BD600A4EA3C /* Credits.rtf in Resources */,
6AB474A02AACBBEA00AB9C63 /* Preview Assets.xcassets in Resources */,
6AB4749D2AACBBEA00AB9C63 /* Assets.xcassets in Resources */,
6A85A14F2B452B9400E05D83 /* Localizable.xcstrings in Resources */,
Expand Down Expand Up @@ -633,6 +640,7 @@
6AD506582AAFF6CB008A28C1 /* Library.swift in Sources */,
6A00F2002AC5EC490054858A /* Install.swift in Sources */,
6A009E5F2AB5816A00A1397F /* Logger.swift in Sources */,
6A721B2D2B8B3D5A00A4EA3C /* AppDelegate.swift in Sources */,
6AB474992AACBBE900AB9C63 /* MythicApp.swift in Sources */,
6A00F20D2AC5F8F90054858A /* ProgressViewWithError.swift in Sources */,
6A12FF902B73AFCE00AA948C /* BottleSettings.swift in Sources */,
Expand Down Expand Up @@ -793,7 +801,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2403;
CURRENT_PROJECT_VERSION = 2418;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Mythic/Preview Content\"";
DEVELOPMENT_TEAM = 67ZBY275P8;
Expand Down Expand Up @@ -832,7 +840,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2403;
CURRENT_PROJECT_VERSION = 2418;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Mythic/Preview Content\"";
DEVELOPMENT_TEAM = 67ZBY275P8;
Expand Down
59 changes: 59 additions & 0 deletions Mythic/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// AppDelegate.swift
// Mythic
//
// Created by Esiayo Alegbe on 25/2/2024.
//

import SwiftUI
import Sparkle
import UserNotifications
import OSLog

class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate {
var updaterController: SPUStandardUpdaterController?
var networkMonitor: NetworkMonitor?

func applicationDidFinishLaunching(_ notification: Notification) {
#if !DEBUG // TODO: possibly turn this into an onboarding-style message.
let appURL = Bundle.main.bundleURL

// MARK: Move to Applications
if !appURL.pathComponents.contains("Applications") {
let alert = NSAlert()
alert.messageText = "Move Mythic to the Applications folder?"
alert.informativeText = """
Mythic has detected it's running outside of the applications folder.
"""
alert.addButton(withTitle: "Move")
alert.addButton(withTitle: "Cancel")

if alert.runModal() == .alertFirstButtonReturn, let globalApps = FileLocations.globalApplications {
do {
_ = try files.replaceItemAt(appURL, withItemAt: globalApps)
workspace.open(globalApps.appending(path: "Mythic.app")
)
} catch {
Logger.file.error("Unable to move Mythic to Applications: \(error)")
}
}
}
#endif

notifications.delegate = self
notifications.getNotificationSettings { settings in
guard settings.authorizationStatus != .authorized else { return }

notifications.requestAuthorization(options: [.alert, .sound, .badge]) { _, error in
guard error == nil else {
Logger.app.error("Unable to request notification authorization: \(error!.localizedDescription)")
return
}
}
}
}

func applicationWillTerminate(_ notification: Notification) {
if defaults.bool(forKey: "quitOnAppClose") { _ = Wine.killAll() }
}
}
30 changes: 27 additions & 3 deletions Mythic/Controllers/Legendary/LegendaryInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import Foundation
import SwiftyJSON
import OSLog
import UserNotifications

// MARK: - Legendary Class
/**
Expand Down Expand Up @@ -297,11 +298,11 @@ class Legendary {
platform: GamePlatform,
type: GameModificationType = .install,
optionalPacks: [String]? = nil,
baseURL: URL? = defaults.url(forKey: "defaultInstallBaseURL"),
baseURL: URL? = defaults.url(forKey: "installBaseURL"),
gameFolder: URL? = nil
) async throws {
guard signedIn() else { throw NotSignedInError() }
guard game.type == .epic else { return } // TODO: FIXME: create IsNotLegendaryError
guard game.type == .epic else { throw IsNotLegendaryError() }
// TODO: data lock handling

let variables: VariableManager = .shared
Expand Down Expand Up @@ -392,7 +393,18 @@ class Legendary {
guard line.contains("[DLManager] INFO:") else { return }

if line.contains("All done! Download manager quitting...") {
GameModification.reset(); return
GameModification.reset()

notifications.add(
.init(identifier: UUID().uuidString,
content: {
let content = UNMutableNotificationContent()
content.title = "Finished installing \"\(game.title)\"."
return content
}(),
trigger: nil)
)
return
}

if let match = match(regex: progressRegex, line: line) {
Expand Down Expand Up @@ -451,6 +463,18 @@ class Legendary {
useCache: false,
identifier: "moveGame"
)

try await notifications.add(
.init(identifier: UUID().uuidString,
content: {
let content = UNMutableNotificationContent()
content.title = "Finished moving \"\(game.title)\"."
content.title = "\"\(game.title)\" can now be found at \(URL(filePath: newPath).prettyPath())"
return content
}(),
trigger: nil)
)

}
}

Expand Down
2 changes: 1 addition & 1 deletion Mythic/Controllers/LocalGames/LocalGames.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class LocalGames {
switch game.platform {
case .macOS:
if FileManager.default.fileExists(atPath: game.path ?? .init()) {
NSWorkspace.shared.open(
workspace.open(
URL(filePath: game.path ?? .init()),
configuration: NSWorkspace.OpenConfiguration(),
completionHandler: { (_/*game*/, error) in
Expand Down
15 changes: 13 additions & 2 deletions Mythic/Controllers/Wine/WineInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -404,11 +404,22 @@ class Wine { // TODO: https://forum.winehq.org/viewtopic.php?t=15416
}

// MARK: - Kill All Method
static func killAll() -> Bool {
static func killAll(bottleURL: URL? = nil) -> Bool {
let task = Process()
task.executableURL = Libraries.directory.appending(path: "Wine/bin/wineserver")
task.arguments = ["-k"]
do { try task.run() } catch { return false }

if let bottleURL = bottleURL {
task.environment = ["WINEPREFIX": bottleURL.path(percentEncoded: false)]
do { try task.run() } catch { return false }
} else {
if let bottles = Wine.allBottles {
for bottle in bottles.values {
task.environment = ["WINEPREFIX": bottle.url.path(percentEncoded: false)]
do { try task.run() } catch { return false }
}
}
}

return true
}
Expand Down
13 changes: 13 additions & 0 deletions Mythic/Credits.rtf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{\rtf1\ansi\ansicpg1252\cocoartf2759
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;}
{\*\expandedcolortbl;;\cssrgb\c0\c1\c1;\cssrgb\c100000\c100000\c99985\c0;}
\paperw12240\paperh15840\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\deftab720
\pard\pardeftab720\sa320\partightenfactor0

\f0\fs32 \cf2 \cb3 \expnd0\expndtw0\kerning0
Copyright \'a9 2024 blackxfiied, Jecta\
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.}
2 changes: 1 addition & 1 deletion Mythic/Deprecated/Views/Sheets/Onboarding/Onboarding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ struct OnboardingView: View {
// MARK: Sign In Button
if Legendary.signedIn() == false && authSuccessful != true {
Button("Sign In") {
NSWorkspace.shared.open(URL(string: "http://legendary.gl/epiclogin")!)
workspace.open(URL(string: "http://legendary.gl/epiclogin")!)
isAuthViewPresented = true
}
.buttonStyle(.borderedProminent)
Expand Down
6 changes: 6 additions & 0 deletions Mythic/Extensions/Global.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import Foundation
import SwiftUI
import OSLog
import UserNotifications

// MARK: - Global Constants
/// A simpler alias of `FileManager.default`.
Expand All @@ -25,6 +26,11 @@ let files: FileManager = .default
/// A simpler alias of `UserDefaults.standard`.
let defaults: UserDefaults = .standard

/// A simpler alias of `workspace`.
let workspace: NSWorkspace = .shared

let notifications: UNUserNotificationCenter = .current()

let gameImageURLCache: URLCache = .init(memoryCapacity: 192_000_000, diskCapacity: 500_000_000) // in bytes

let mainLock: NSRecursiveLock = .init()
Expand Down
9 changes: 9 additions & 0 deletions Mythic/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -10088,6 +10088,9 @@
},
"Folder is not writable." : {

},
"Force quit all games when Mythic closes" : {

},
"Force Quit Applications" : {

Expand Down Expand Up @@ -15869,6 +15872,9 @@
},
"Mythic Engine is Mythic's implementation of Apple's game porting toolkit (GPTK),\nwhich combines wine and D3DMetal, to create a windows gaming experience on macOS.\nSimilar to Proton, Mythic Engine attempts to be an emulator-like experience that\nenables native Windows games to be playable on macOS, while coming closer to native\nperformance than ever before. (performance will vary between games)" : {

},
"Mythic Engine is not installed!" : {

},
"Mythic is checking the connection to Epic." : {

Expand Down Expand Up @@ -21475,6 +21481,9 @@
},
"Unable to boot default bottle." : {

},
"Unable to fetch bottles." : {

},
"Unable to move %@." : {

Expand Down
6 changes: 4 additions & 2 deletions Mythic/MythicApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import UserNotifications // TODO: TODO
// MARK: - Where it all begins!
@main
struct MythicApp: App {
// MARK: - App Delegate
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

// MARK: - State Properties
@AppStorage("isFirstLaunch") var isFirstLaunch: Bool = true // TODO: FIXME: RENAME BEFORE LAUNCH!
@State var onboardingChapter: OnboardingEvo.Chapter = .allCases.first!
Expand All @@ -35,7 +38,7 @@ struct MythicApp: App {
}

// MARK: - Updater Controller
private let updaterController: SPUStandardUpdaterController
let updaterController: SPUStandardUpdaterController

// MARK: - Initialization
init() {
Expand All @@ -45,7 +48,6 @@ struct MythicApp: App {
userDriverDelegate: nil
)
}

// MARK: - App Body
var body: some Scene {
Window("Mythic", id: "main") {
Expand Down
4 changes: 2 additions & 2 deletions Mythic/Utilities/FileLocations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ class FileLocations {
do {
return try files.url(
for: .applicationSupportDirectory,
in: .userDomainMask,
in: .userDomainMask, // to remain individual
appropriateFor: nil,
create: false
)
} catch {
Logger.file.error("Unable to get Application Support directory: \(error.localizedDescription)")
Logger.file.error(" Unable to get Application Support directory: \(error.localizedDescription)")
}

return nil
Expand Down
Loading

0 comments on commit 4d1a571

Please sign in to comment.