Skip to content

Commit

Permalink
Merge branch 'develop' into MaaTools
Browse files Browse the repository at this point in the history
  • Loading branch information
hguandl committed Oct 26, 2023
2 parents 835cf2f + 7803c73 commit cbefd14
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 18 deletions.
3 changes: 3 additions & 0 deletions PlayCover/AppInstaller/Installer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Installer {
// If (the option key is held or the install playtools popup settings is true) and its not an export,
// then show the installer dialog
let installPlayTools: Bool
let applicationType = InstallPreferences.shared.defaultAppType

if (Installer.isOptionKeyHeld || InstallPreferences.shared.showInstallPopup) && !export {
installPlayTools = installPlayToolsPopup()
Expand Down Expand Up @@ -81,6 +82,8 @@ class Installer {
try PlayTools.installInIPA(app.executable)
}

app.info.applicationCategoryType = applicationType

if !export {
// -rwxr-xr-x
try app.executable.setBinaryPosixPermissions(0o755)
Expand Down
74 changes: 74 additions & 0 deletions PlayCover/Model/AppInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,35 @@

import Foundation

enum LSApplicationCategoryType: String, CaseIterable {
case business = "public.app-category.business"
case developerTools = "public.app-category.developer-tools"
case education = "public.app-category.education"
case entertainment = "public.app-category.entertainment"
case finance = "public.app-category.finance"
case games = "public.app-category.games"
case graphicsDesign = "public.app-category.graphics-design"
case healthcareFitness = "public.app-category.healthcare-fitness"
case lifestyle = "public.app-category.lifestyle"
case medical = "public.app-category.medical"
case music = "public.app-category.music"
case news = "public.app-category.news"
case photography = "public.app-category.photography"
case productivity = "public.app-category.productivity"
case reference = "public.app-category.reference"
case socialNetworking = "public.app-category.social-networking"
case sports = "public.app-category.sports"
case travel = "public.app-category.travel"
case utilities = "public.app-category.utilities"
case video = "public.app-category.video"
case weather = "public.app-category.weather"
case none = "public.app-category.none" // Note: This is not in an official category type

var localizedName: String {
NSLocalizedString(rawValue, comment: "")
}
}

public class AppInfo {
public let url: URL
fileprivate var rawStorage: NSMutableDictionary
Expand Down Expand Up @@ -122,6 +151,26 @@ public class AppInfo {
}
}

var applicationCategoryType: LSApplicationCategoryType {
get {
LSApplicationCategoryType(
rawValue: self[string: "LSApplicationCategoryType"] ?? ""
) ?? LSApplicationCategoryType.none
}
set {
if newValue == .none {
rawStorage.removeObject(forKey: "LSApplicationCategoryType")
} else {
self[string: "LSApplicationCategoryType"] = newValue.rawValue
}
do {
try write()
} catch {
Log.shared.error(error)
}
}
}

var minimumOSVersion: String {
get {
self[string: "MinimumOSVersion"] ?? ""
Expand Down Expand Up @@ -186,6 +235,31 @@ public class AppInfo {
return "AppIcon"
}

var lsEnvironment: [String: String] {
get {
if self[dictionary: "LSEnvironment"] == nil {
self[dictionary: "LSEnvironment"] = NSMutableDictionary(dictionary: [String: String]())
}

return self[dictionary: "LSEnvironment"] as? [String: String] ?? [:]
}
set {
if self[dictionary: "LSEnvironment"] == nil {
self[dictionary: "LSEnvironment"] = NSMutableDictionary(dictionary: [String: String]())
}

if let key = newValue.first?.key, let value = newValue.first?.value {
self[dictionary: "LSEnvironment"]?[key] = value

do {
try write()
} catch {
Log.shared.error(error)
}
}
}
}

func assert(minimumVersion: Double) {
if let double = Double(minimumOSVersion) {
if double > 11.0 {
Expand Down
15 changes: 14 additions & 1 deletion PlayCover/Model/AppSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import Foundation
import UniformTypeIdentifiers

struct AppSettingsData: Codable {
var bundleIdentifier: String = ""

var keymapping = true
var sensitivity: Float = 50

Expand All @@ -25,7 +27,15 @@ struct AppSettingsData: Codable {
var playChain = true
var playChainDebugging = false
var inverseScreenValues = false
var metalHUD = false
var metalHUD = false {
didSet {
do {
try Shell.setMetalHUD(bundleIdentifier, enabled: metalHUD)
} catch {
Log.shared.error(error)
}
}
}
var windowFixMethod = 0
var injectIntrospection = false
var rootWorkDir = true
Expand All @@ -39,6 +49,7 @@ struct AppSettingsData: Codable {
// handle old 2.x settings where PlayChain did not exist yet
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
bundleIdentifier = try container.decodeIfPresent(String.self, forKey: .bundleIdentifier) ?? ""
keymapping = try container.decodeIfPresent(Bool.self, forKey: .keymapping) ?? true
sensitivity = try container.decodeIfPresent(Float.self, forKey: .sensitivity) ?? 50
disableTimeout = try container.decodeIfPresent(Bool.self, forKey: .disableTimeout) ?? false
Expand Down Expand Up @@ -103,6 +114,8 @@ class AppSettings {
if !decode() {
encode()
}

settings.bundleIdentifier = info.bundleIdentifier
}

public func sync() {
Expand Down
33 changes: 27 additions & 6 deletions PlayCover/Model/PlayApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,6 @@ class PlayApp: BaseApp {
func runAppExec() {
let config = NSWorkspace.OpenConfiguration()

if settings.settings.metalHUD {
config.environment = ["MTL_HUD_ENABLED": "1"]
} else {
config.environment = ["MTL_HUD_ENABLED": "0"]
}

if settings.settings.injectIntrospection {
config.environment["DYLD_LIBRARY_PATH"] = "/usr/lib/system/introspection"
}
Expand Down Expand Up @@ -208,6 +202,33 @@ class PlayApp: BaseApp {
}
}

func introspection(set: Bool? = nil) -> Bool {
if info.lsEnvironment["DYLD_LIBRARY_PATH"] == nil {
info.lsEnvironment["DYLD_LIBRARY_PATH"] = ""
}

if let set = set {
if set {
info.lsEnvironment["DYLD_LIBRARY_PATH"]? += "/usr/lib/system/introspection:"
} else {
info.lsEnvironment["DYLD_LIBRARY_PATH"] = info.lsEnvironment["DYLD_LIBRARY_PATH"]?
.replacingOccurrences(of: "/usr/lib/system/introspection:", with: "")
}

do {
try Shell.signApp(executable)
} catch {
Log.shared.error(error)
}
}

guard let introspection = info.lsEnvironment["DYLD_LIBRARY_PATH"] else {
return false
}

return introspection.contains("/usr/lib/system/introspection")
}

func hasAlias() -> Bool {
return FileManager.default.fileExists(atPath: aliasURL.path)
}
Expand Down
5 changes: 5 additions & 0 deletions PlayCover/Utils/Shell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ class Shell: ObservableObject {
"--deep", "--preserve-metadata=entitlements")
}

static func setMetalHUD(_ bundleID: String, enabled: Bool) throws {
try run("/usr/bin/defaults", "write", bundleID,
"MetalForceHudEnabled", "-bool", String(enabled))
}

static func lldb(_ url: URL, withTerminalWindow: Bool = false) throws {
Task(priority: .utility) {
if withTerminalWindow {
Expand Down
48 changes: 45 additions & 3 deletions PlayCover/Views/AppSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ struct AppSettingsView: View {
}
.disabled(!(hasPlayTools ?? true))
BypassesView(settings: $viewModel.settings,
hasPlayTools: $hasPlayTools)
hasPlayTools: $hasPlayTools,
hasIntrospection: viewModel.app.introspection(),
app: viewModel.app)
.tabItem {
Text("settings.tab.bypasses")
}
Expand All @@ -90,7 +92,8 @@ struct AppSettingsView: View {
closeView: $closeView,
hasPlayTools: $hasPlayTools,
hasAlias: $hasAlias,
app: viewModel.app)
app: viewModel.app,
applicationCategoryType: viewModel.app.info.applicationCategoryType)
.tabItem {
Text("settings.tab.misc")
}
Expand Down Expand Up @@ -441,6 +444,10 @@ struct BypassesView: View {
@Binding var settings: AppSettings
@Binding var hasPlayTools: Bool?

@State var hasIntrospection: Bool

var app: PlayApp

var body: some View {
ScrollView {
VStack {
Expand All @@ -461,7 +468,7 @@ struct BypassesView: View {
}
Spacer()
HStack {
Toggle("settings.toggle.introspection", isOn: $settings.settings.injectIntrospection)
Toggle("settings.toggle.introspection", isOn: $hasIntrospection)
.help("settings.toggle.introspection.help")
Spacer()
}
Expand All @@ -483,6 +490,9 @@ struct BypassesView: View {
}
.padding()
}
.onChange(of: hasIntrospection) {_ in
_ = app.introspection(set: hasIntrospection)
}
}
}

Expand All @@ -496,9 +506,34 @@ struct MiscView: View {

var app: PlayApp

@State var applicationCategoryType: LSApplicationCategoryType

var body: some View {
ScrollView {
VStack {
HStack {
Text("settings.applicationCategoryType")
Spacer()
Picker("", selection: $applicationCategoryType) {
ForEach(LSApplicationCategoryType.allCases, id: \.rawValue) { value in
Text(value.localizedName)
.tag(value)
}
}
.frame(width: 225)
.onChange(of: applicationCategoryType) { _ in
app.info.applicationCategoryType = applicationCategoryType
Task(priority: .userInitiated) {
do {
try Shell.signApp(app.executable)
} catch {
Log.shared.error(error)
}
}
}
}
Spacer()
.frame(height: 20)
HStack {
Toggle("settings.toggle.discord", isOn: $settings.settings.discordActivity.enable)
Spacer()
Expand Down Expand Up @@ -594,6 +629,8 @@ struct MiscView: View {
}
}
}
Spacer()
.frame(height: 20)
// swiftlint:disable:next todo
// TODO: Test and remove before 3.0 release
HStack {
Expand Down Expand Up @@ -642,6 +679,11 @@ struct InfoView: View {
Spacer()
Text("\(info.bundleVersion)")
}
HStack {
Text("settings.applicationCategoryType") + Text(":")
Spacer()
Text("\(info.applicationCategoryType.rawValue)")
}
HStack {
Text("settings.info.executableName")
Spacer()
Expand Down
2 changes: 1 addition & 1 deletion PlayCover/Views/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ struct MainView: View {
self.selectedView = URLObserved.type == .source ? 2 : 1
}
.toolbar {
ToolbarItem(placement: .navigation) {
ToolbarItem { // Sits on the left by default
Button(action: toggleSidebar, label: {
Image(systemName: "sidebar.leading")
})
Expand Down
32 changes: 25 additions & 7 deletions PlayCover/Views/Settings/InstallSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class InstallPreferences: NSObject, ObservableObject {

@objc @AppStorage("AlwaysInstallPlayTools") var alwaysInstallPlayTools = true

@AppStorage("DefaultAppType") var defaultAppType: LSApplicationCategoryType = .none

@AppStorage("ShowInstallPopup") var showInstallPopup = false
}

Expand All @@ -21,20 +23,36 @@ struct InstallSettings: View {
@ObservedObject var installPreferences = InstallPreferences.shared

var body: some View {
Form {
VStack(alignment: .leading) {
HStack {
Text("settings.applicationCategoryType")
Spacer()
Picker("", selection: installPreferences.$defaultAppType) {
ForEach(LSApplicationCategoryType.allCases, id: \.rawValue) { value in
Text(value.localizedName)
.tag(value)
}
}
.frame(width: 225)
}
Spacer()
.frame(height: 20)
Toggle("preferences.toggle.showInstallPopup", isOn: $installPreferences.showInstallPopup)
GroupBox {
HStack {
VStack(alignment: .leading) {
Toggle("preferences.toggle.alwaysInstallPlayTools",
isOn: $installPreferences.alwaysInstallPlayTools)
VStack {
HStack {
VStack(alignment: .leading) {
Toggle("preferences.toggle.alwaysInstallPlayTools",
isOn: $installPreferences.alwaysInstallPlayTools)
}
Spacer()
}
Spacer()
.frame(height: 20)
}
}.disabled(installPreferences.showInstallPopup)
Spacer()
}
.padding(20)
.frame(width: 350, height: 100, alignment: .center)
.frame(width: 400, height: 200)
}
}
1 change: 1 addition & 0 deletions PlayCover/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
"settings.toggle.introspection" = "Insert Introspection libraries";
"settings.toggle.introspection.help" = "Add the system introspection libraries to the app. Known to fix issues with some apps not starting correctly";

"settings.applicationCategoryType" = "Application Type";
"settings.removePlayTools" = "Remove PlayTools";
"settings.addToLaunchpad" = "Add to Launchpad";
"settings.removeFromLaunchpad" = "Remove from Launchpad";
Expand Down

0 comments on commit cbefd14

Please sign in to comment.