Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mythic v0.4.1 | "Silver Chariot", Part 2 #163

Merged
merged 8 commits into from
Nov 2, 2024
4 changes: 2 additions & 2 deletions Mythic.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 3027;
CURRENT_PROJECT_VERSION = 3037;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = "\"Mythic/Preview Content\"";
Expand Down Expand Up @@ -811,7 +811,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 3027;
CURRENT_PROJECT_VERSION = 3037;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = "\"Mythic/Preview Content\"";
Expand Down
47 changes: 34 additions & 13 deletions Mythic/Utilities/Legendary/LegendaryInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,20 @@ final class Legendary {
return
}

if output.stderr.contains("Verification finished successfully.") {
Task { @MainActor in
let alert = NSAlert()
alert.messageText = "Successfully verified \"\(args.game.title)\"."
alert.informativeText = "\"\(args.game.title)\" is now ready to be played."
alert.alertStyle = .informational
alert.addButton(withTitle: "OK")

if let window = NSApp.windows.first {
alert.beginSheetModal(for: window)
}
}
}

if let match = try? progressRegex.firstMatch(in: output.stderr) {
Task { @MainActor in
operation.status.progress = GameOperation.InstallStatus.Progress(
Expand Down Expand Up @@ -597,23 +611,30 @@ final class Legendary {
*/
static func getImage(of game: Mythic.Game, type: ImageType) -> String {
let metadata = try? getGameMetadata(game: game)
var imageURL: String = .init()
let keyImages = metadata?["metadata"]["keyImages"].array ?? .init()

if let keyImages = metadata?["metadata"]["keyImages"].array {
for image in keyImages {
if type == .normal {
if image["type"] == "DieselGameBox" {
imageURL = image["url"].stringValue
}
} else if type == .tall {
if image["type"] == "DieselGameBoxTall" {
imageURL = image["url"].stringValue
}
}
let prioritisedTypes: [String] = {
switch type {
case .normal: return ["DieselGameBoxWide", "DieselGameBox"]
case .tall: return ["DieselGameBoxTall"]
}
}()

if let imageURL = keyImages.first(where: { prioritisedTypes.contains($0["type"].stringValue) })?["url"].stringValue {
return imageURL
}

// fallback #1
if let fallbackURL = keyImages.first(where: {
guard let width = $0["width"].int, let height = $0["height"].int else { return false }

return (type == .normal && width >= height) || (type == .tall && height > width) // check aspect ratios
})?["url"].stringValue {
return fallbackURL
}

return imageURL
// fallback #2
return keyImages.first?["url"].stringValue ?? .init()
}

// MARK: - Is Alias Method
Expand Down
6 changes: 5 additions & 1 deletion Mythic/Utilities/Local/LocalGames.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ final class LocalGames {
if FileManager.default.fileExists(atPath: game.path ?? .init()) {
workspace.open(
URL(filePath: game.path ?? .init()),
configuration: .init(),
configuration: {
let configuration = NSWorkspace.OpenConfiguration()
configuration.arguments = game.launchArguments
return configuration
}(),
completionHandler: { (_/*game*/, error) in
if let error = error {
log.error("Error launching local macOS game \"\(game.title)\": \(error)")
Expand Down
3 changes: 2 additions & 1 deletion Mythic/Views/Navigation/AccountsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ struct AccountsView: View {
@State private var signedIn: Bool = false

@State private var isHoveringOverDestructiveSteamButton: Bool = false


// Spacer()s here are necessary
var body: some View {
VStack {
HStack {
Expand Down
53 changes: 20 additions & 33 deletions Mythic/Views/Navigation/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,48 +63,35 @@ struct SettingsView: View {
Toggle("Force quit all games when Mythic closes", isOn: $quitOnClose)

HStack {
VStack {
HStack {
Text("Choose the default base path for games:")
Spacer()
}
HStack {
Text(installBaseURL.prettyPath())
.foregroundStyle(.placeholder)

Spacer()
}
VStack(alignment: .leading) {
Text("Choose the default base path for games:")
Text(installBaseURL.prettyPath())
.foregroundStyle(.placeholder)
}

Spacer()

if !FileLocations.isWritableFolder(url: installBaseURL) {
Image(systemName: "exclamationmark.triangle.fill")
.help("Folder is not writable.")
}

VStack {
HStack {
Spacer()
Button("Browse...") { // TODO: replace with .fileImporter
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.canCreateDirectories = true
openPanel.allowsMultipleSelection = false

if openPanel.runModal() == .OK {
installBaseURL = openPanel.urls.first!
}

VStack(alignment: .trailing) {
Button("Browse...") { // TODO: replace with .fileImporter
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.canCreateDirectories = true
openPanel.allowsMultipleSelection = false

if openPanel.runModal() == .OK {
installBaseURL = openPanel.urls.first!
}
.buttonStyle(.borderedProminent)
}

HStack {
Spacer()
Button("Reset to Default") {
installBaseURL = Bundle.appGames!
}
.buttonStyle(.borderedProminent)

Button("Reset to Default") {
installBaseURL = Bundle.appGames!
}
}
}
Expand Down
1 change: 1 addition & 0 deletions Mythic/Views/OnboardingViewR2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ struct OnboardingR2: View { // TODO: ViewModel

VStack {
Spacer()

Text("(alpha)")
.font(.footnote)
.foregroundStyle(.placeholder)
Expand Down
7 changes: 4 additions & 3 deletions Mythic/Views/Unified/ContainerListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ struct ContainerListView: View {
.buttonStyle(.accessoryBar)

Spacer()
Button(action: {

Button {
selectedContainerURL = container.url
isContainerConfigurationViewPresented = true
}, label: {
} label: {
Image(systemName: "gear")
})
}
.buttonStyle(.borderless)
.help("Modify default settings for \"\(container.name)\"")

Expand Down
1 change: 0 additions & 1 deletion Mythic/Views/Unified/Models/GameCardVM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ import Shimmer
}
.sheet(isPresented: $isUninstallSheetPresented) {
UninstallViewEvo(game: $game, isPresented: $isUninstallSheetPresented)
.padding()
}
}

Expand Down
12 changes: 6 additions & 6 deletions Mythic/Views/Unified/Modules/GameCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ struct FadeInModifier: ViewModifier {
extension GameCard {
struct ImageCard: View {
@Binding var game: Game
var withBlur: Bool = true

/// Binding that updates when image is empty (default to true)
@Binding var isImageEmpty: Bool


var withBlur: Bool = true

var body: some View {
RoundedRectangle(cornerRadius: 20)
.fill(.background)
blankImageView
.aspectRatio(3/4, contentMode: .fit)
.overlay {
gameImage
Expand All @@ -108,12 +108,12 @@ extension GameCard {
withAnimation { isImageEmpty = false }
}
case .failure:
blankImageView
EmptyView()
.onAppear {
withAnimation { isImageEmpty = true }
}
@unknown default:
blankImageView
EmptyView()
.onAppear {
withAnimation { isImageEmpty = true }
}
Expand Down
4 changes: 3 additions & 1 deletion Mythic/Views/Unified/Modules/GameInstallProgressView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ struct GameInstallProgressView: View {
HStack {
OperationProgressView(withPercentage: withPercentage)

infoButton()
if operation.current?.type != .repair {
infoButton()
}

stopButton()
}
Expand Down
11 changes: 3 additions & 8 deletions Mythic/Views/Unified/Modules/GameListCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ struct GameListCard: View {
CachedAsyncImage(url: URL(string: Legendary.getImage(of: game, type: .normal))) { phase in
switch phase {
case .empty:
RoundedRectangle(cornerRadius: 20)
.fill(.background)
EmptyView()
.onAppear {
withAnimation { isImageEmpty = true }
}
Expand All @@ -43,16 +42,12 @@ struct GameListCard: View {
withAnimation { isImageEmpty = false }
}
case .failure:
RoundedRectangle(cornerRadius: 20)
.fill(.background)
.overlay { Image(systemName: "exclamationmark.triangle.fill") }
EmptyView()
.onAppear {
withAnimation { isImageEmpty = true }
}
@unknown default:
RoundedRectangle(cornerRadius: 20)
.fill(.background)
.overlay { Image(systemName: "questionmark.circle.fill") }
EmptyView()
.onAppear {
withAnimation { isImageEmpty = true }
}
Expand Down
18 changes: 6 additions & 12 deletions Mythic/Views/Unified/Sheets/ContainerCreationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,13 @@ struct ContainerCreationView: View {
TextField("Choose a name for your container:", text: $containerName)

HStack {
VStack {
HStack {
Text("Where do you want the container's base path to be located?")
Spacer()
}
HStack {
Text(containerURL.prettyPath())
.foregroundStyle(.placeholder)

Spacer()
}
VStack(alignment: .leading) {
Text("Where do you want the container's base path to be located?")

Text(containerURL.prettyPath())
.foregroundStyle(.placeholder)
}

Spacer()

if !FileLocations.isWritableFolder(url: containerURL) {
Expand Down
19 changes: 18 additions & 1 deletion Mythic/Views/Unified/Sheets/GameSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,25 @@ private extension GameSettingsView {
}

Spacer()
TextField("", text: $typingArgument)

TextField("", text: Binding(
get: { typingArgument },
set: { newValue in
withAnimation{
typingArgument = newValue
}
}
))
.onSubmit(submitLaunchArgument)

if !typingArgument.isEmpty {
Button {
submitLaunchArgument()
} label: {
Image(systemName: "return")
}
.buttonStyle(.plain)
}
}
}

Expand Down
25 changes: 10 additions & 15 deletions Mythic/Views/Unified/Sheets/UninstallGameView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,20 @@ struct UninstallViewEvo: View {
VStack {
Text("Uninstall \"\(game.title)\"")
.font(.title)

.padding([.horizontal, .top])

Form {
HStack {
Toggle(isOn: $deleteFiles) {
Text("Remove game files")
}
Spacer()
Toggle(isOn: $deleteFiles) {
Text("Remove game files")
}

HStack {
Toggle(isOn: $runUninstaller) {
Text("Run specialised uninstaller (If applicable)")
}
.disabled(game.source == .local)
Spacer()

Toggle(isOn: $runUninstaller) {
Text("Run specialised uninstaller (If applicable)")
}
.disabled(game.source == .local)
}
.formStyle(.grouped)

HStack {
Button("Cancel", role: .cancel) {
isPresented = false
Expand Down Expand Up @@ -133,8 +128,8 @@ struct UninstallViewEvo: View {
)
}
}
.padding([.horizontal, .bottom])
}
.interactiveDismissDisabled()
}
}

Expand Down
Loading