Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Mythic/Utilities/Game/EpicGamesGame.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import Foundation
import AppKit

class EpicGamesGame: Game {
class EpicGamesGame: Game, @unchecked Sendable {
override var storefront: Storefront? { .epicGames }

override var computedVerticalImageURL: URL? { Legendary.getImageURL(gameID: self.id, type: .tall) }
Expand Down
4 changes: 2 additions & 2 deletions Mythic/Utilities/GameManager/EpicGamesGameManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ extension EpicGamesGameManager: StorefrontGameManager {
guard case .epicGames = game.storefront,
let castGame = game as? EpicGamesGame else { throw CocoaError(.coderInvalidValue) }

return try await Task(operation: { try await launch(game: castGame) }).value
return try await launch(game: castGame)
}

@MainActor static func move(game: Game,
to location: URL) async throws -> GameOperation {
guard case .epicGames = game.storefront,
let castGame = game as? EpicGamesGame else { throw CocoaError(.coderInvalidValue) }

return try await Task(operation: { try await move(game: castGame, to: location) }).value
return try await move(game: castGame, to: location)
}

@MainActor static func uninstall(game: Game,
Expand Down
12 changes: 9 additions & 3 deletions Mythic/Utilities/GameManager/Legendary/LegendaryInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ final class Legendary {
}

static func handleCLIErrorOutput(fromStandardErrorOutput output: String) throws {
if output.contains("ValueError: No saved credentials") {
throw NotSignedInError()
}

for line in output.split(whereSeparator: \.isNewline) {
if let match = try? Regex(#"(ERROR|CRITICAL): (.*)"#).firstMatch(in: line),
let errorReason = match.last?.substring {
Expand Down Expand Up @@ -103,7 +107,7 @@ final class Legendary {
progress: Progress) {
// these regexes are not dynamic, so there's no reason why they should fail to initialise
// swiftlint:disable force_try
let progressRegex: Regex = try! .init(#"Progress: (?<percentage>\d+\.\d+)% \((?<downloadedObjects>\d+)\/(?<totalObjects>\d+)\), Running for (?<runtime>\d+:\d+:\d+), ETA: (?<eta>\d+:\d+:\d+)"#)
let progressRegex: Regex = try! .init(#"Progress: (?<percentage>\d+(?:\.\d+)?)% \((?<downloadedObjects>\d+)\/(?<totalObjects>\d+)\), Running for (?<runtime>\d+:\d+:\d+), ETA: (?<eta>(?:\d+:\d+:\d+|--:--:--|Unknown))"#)
// let downloadRegex: Regex = try! .init(#"Downloaded: (?<downloaded>\d+\.\d+) \w+, Written: (?<written>\d+\.\d+) \w+"#)
// let cacheRegex: Regex = try! .init(#"Cache usage: (?<usage>\d+\.\d+) \w+, active tasks: (?<activeTasks>\d+)"#)
let downloadSpeedRegex: Regex = try! .init(#"\+ Download\s+- (?<raw>[\d.]+) \w+/\w+ \(raw\) / (?<decompressed>[\d.]+) \w+/\w+ \(decompressed\)"#)
Expand Down Expand Up @@ -410,8 +414,10 @@ final class Legendary {
throw CocoaError(.fileNoSuchFile)
}

let destinationURL = newLocation.appending(path: currentLocation.lastPathComponent)

let operation: GameOperation = .init(game: game, type: .move) { _ in
try FileManager.default.moveItem(at: currentLocation, to: newLocation)
try FileManager.default.moveItem(at: currentLocation, to: destinationURL)

let process: Process = .init()
process.arguments = ["move", game.id, newLocation.path, "--skip-move"]
Expand All @@ -424,7 +430,7 @@ final class Legendary {

try handleCLIErrorOutput(fromStandardErrorPipe: processStandardErrorPipe)

game.installationState = .installed(location: newLocation, platform: platform)
game.installationState = .installed(location: destinationURL, platform: platform)
}

await Game.operationManager.queueOperation(operation)
Expand Down
10 changes: 7 additions & 3 deletions Mythic/Utilities/GameManager/LocalGameManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class LocalGameManager {

let process: Process = .init()
process.arguments = [location.path] + game.launchArguments
process.currentDirectoryURL = location.deletingLastPathComponent()
process.environment = environment
Wine.transformProcess(process, containerURL: containerURL)

Expand All @@ -111,10 +112,13 @@ class LocalGameManager {
throw CocoaError(.fileNoSuchFile)
}

let operation: GameOperation = .init(game: game, type: .uninstall) { _ in
try FileManager.default.moveItem(at: currentLocation, to: newLocation)
game.installationState = .installed(location: newLocation, platform: platform)
let destinationURL = newLocation.appending(path: currentLocation.lastPathComponent)

let operation: GameOperation = .init(game: game, type: .move) { _ in
try FileManager.default.moveItem(at: currentLocation, to: destinationURL)
game.installationState = .installed(location: destinationURL, platform: platform)
}
Game.operationManager.queueOperation(operation)
return operation
}

Expand Down
2 changes: 1 addition & 1 deletion Mythic/Views/Navigation/SupportView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct SupportView: View {
}
verticalDivider(height: 30)
Button("FAQ"){
openLink(urlString: "https://getmythic.app/faq/")
openLink(urlString: "https://docs.getmythic.app/docs/faq/")
}
verticalDivider(height: 30)
Button("Compatibility List"){
Expand Down
3 changes: 2 additions & 1 deletion Mythic/Views/Unified/Components/WebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ struct WebView: NSViewRepresentable {

let webView = WKWebView(frame: .zero, configuration: config)
webView.navigationDelegate = context.coordinator
webView.load(URLRequest(url: url))
return webView
}

func updateNSView(_ nsView: WKWebView, context: Context) {
if nsView.url != self.url {
if nsView.url == nil || url.scheme == "javascript" {
let request = URLRequest(url: self.url)
nsView.load(request)
}
Expand Down
14 changes: 13 additions & 1 deletion Mythic/Views/Unified/Windows/EpicWebAuthView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,24 @@ private struct EpicInterceptorWebView: NSViewRepresentable {

let completion: (String) -> Void

class Coordinator: NSObject, WKNavigationDelegate {
class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {
let parent: EpicInterceptorWebView

init(parent: EpicInterceptorWebView) {
self.parent = parent
}

func webView(_ webView: WKWebView,
createWebViewWith configuration: WKWebViewConfiguration,
for navigationAction: WKNavigationAction,
windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
webView.load(navigationAction.request)
}

return nil
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.body.innerText") { result, error in
guard error == nil else {
Expand Down Expand Up @@ -237,6 +248,7 @@ private struct EpicInterceptorWebView: NSViewRepresentable {

let webView = WKWebView(frame: .zero, configuration: config)
webView.navigationDelegate = context.coordinator
webView.uiDelegate = context.coordinator
webView.load(URLRequest(url: URL(string: "https://legendary.gl/epiclogin")!))
return webView
}
Expand Down
Loading