Skip to content
Merged
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@ fastlane/test_output

iOSInjectionProject/

.DS_Store
.DS_Store
24 changes: 24 additions & 0 deletions MiniSim.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
76059BF52AD4361C0008D38B /* SetupPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76059BF42AD4361C0008D38B /* SetupPreferences.swift */; };
76059BF72AD449DC0008D38B /* OnboardingHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76059BF62AD449DC0008D38B /* OnboardingHeader.swift */; };
76059BF92AD558C30008D38B /* SetupItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76059BF82AD558C30008D38B /* SetupItemView.swift */; };
760DEACE2B0DFB6600253576 /* ShellStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 760DEACD2B0DFB6600253576 /* ShellStub.swift */; };
7610992D2A3F95850067885A /* MiniSim.sdef in Resources */ = {isa = PBXBuildFile; fileRef = 7610992C2A3F95850067885A /* MiniSim.sdef */; };
7610992F2A3F95D90067885A /* NSScriptCommand+utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7610992E2A3F95D90067885A /* NSScriptCommand+utils.swift */; };
7625140B2992B46D0060A225 /* Pasteboard+utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7625140A2992B46D0060A225 /* Pasteboard+utils.swift */; };
Expand Down Expand Up @@ -75,8 +76,11 @@
76AC9AF62A0EA82C00864A8B /* CustomCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76AC9AF52A0EA82C00864A8B /* CustomCommands.swift */; };
76AC9AF92A0EB50800864A8B /* SymbolPicker in Frameworks */ = {isa = PBXBuildFile; productRef = 76AC9AF82A0EB50800864A8B /* SymbolPicker */; };
76B70F7E2B0D361A009D87A4 /* UserDefaultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76B70F7D2B0D361A009D87A4 /* UserDefaultsTests.swift */; };
76B70F822B0D50FE009D87A4 /* ADBTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76B70F812B0D50FE009D87A4 /* ADBTests.swift */; };
76B70F842B0D5AB4009D87A4 /* Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76B70F832B0D5AB4009D87A4 /* Shell.swift */; };
76BF0AD92C8CB3E6003BE568 /* AcknowList in Frameworks */ = {isa = PBXBuildFile; productRef = 76BF0AD82C8CB3E6003BE568 /* AcknowList */; };
76BF0ADB2C8CB4CD003BE568 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 76BF0ADA2C8CB4CD003BE568 /* Package.resolved */; };
76BF0ADD2C8DF660003BE568 /* AccessibilityElementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0ADC2C8DF660003BE568 /* AccessibilityElementTests.swift */; };
76C1396A2C849A3F006CD80C /* MenuIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76C139692C849A3F006CD80C /* MenuIcons.swift */; };
76E4451229D4391000039025 /* Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E4451129D4391000039025 /* Onboarding.swift */; };
76E4451429D4403F00039025 /* NSNotificationName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E4451329D4403F00039025 /* NSNotificationName.swift */; };
Expand Down Expand Up @@ -115,6 +119,7 @@
76059BF42AD4361C0008D38B /* SetupPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupPreferences.swift; sourceTree = "<group>"; };
76059BF62AD449DC0008D38B /* OnboardingHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingHeader.swift; sourceTree = "<group>"; };
76059BF82AD558C30008D38B /* SetupItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupItemView.swift; sourceTree = "<group>"; };
760DEACD2B0DFB6600253576 /* ShellStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellStub.swift; sourceTree = "<group>"; };
7610992C2A3F95850067885A /* MiniSim.sdef */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = MiniSim.sdef; sourceTree = "<group>"; };
7610992E2A3F95D90067885A /* NSScriptCommand+utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSScriptCommand+utils.swift"; sourceTree = "<group>"; };
7625140A2992B46D0060A225 /* Pasteboard+utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Pasteboard+utils.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -169,7 +174,10 @@
76AC9AF52A0EA82C00864A8B /* CustomCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCommands.swift; sourceTree = "<group>"; };
76B70F742B0D359D009D87A4 /* MiniSimTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MiniSimTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
76B70F7D2B0D361A009D87A4 /* UserDefaultsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsTests.swift; sourceTree = "<group>"; };
76B70F812B0D50FE009D87A4 /* ADBTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADBTests.swift; sourceTree = "<group>"; };
76B70F832B0D5AB4009D87A4 /* Shell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shell.swift; sourceTree = "<group>"; };
76BF0ADA2C8CB4CD003BE568 /* Package.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Package.resolved; path = MiniSim.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved; sourceTree = SOURCE_ROOT; };
76BF0ADC2C8DF660003BE568 /* AccessibilityElementTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityElementTests.swift; sourceTree = "<group>"; };
76C139692C849A3F006CD80C /* MenuIcons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuIcons.swift; sourceTree = "<group>"; };
76E4451129D4391000039025 /* Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Onboarding.swift; sourceTree = "<group>"; };
76E4451329D4403F00039025 /* NSNotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSNotificationName.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -230,6 +238,14 @@
path = Terminal;
sourceTree = "<group>";
};
760DEACC2B0DFB5B00253576 /* Mocks */ = {
isa = PBXGroup;
children = (
760DEACD2B0DFB6600253576 /* ShellStub.swift */,
);
path = Mocks;
sourceTree = "<group>";
};
762CF1E12981DDD400099999 /* Extensions */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -297,6 +313,7 @@
7645D4BD2982A1B100019227 /* DeviceService.swift */,
7699511C2C845B1900462287 /* DeviceParser.swift */,
76F04A10298A5AE000BF9CA3 /* ADB.swift */,
76B70F832B0D5AB4009D87A4 /* Shell.swift */,
);
path = Service;
sourceTree = "<group>";
Expand Down Expand Up @@ -396,8 +413,11 @@
76B70F752B0D359D009D87A4 /* MiniSimTests */ = {
isa = PBXGroup;
children = (
760DEACC2B0DFB5B00253576 /* Mocks */,
76B70F7D2B0D361A009D87A4 /* UserDefaultsTests.swift */,
7699511E2C845CBA00462287 /* DeviceParserTests.swift */,
76B70F812B0D50FE009D87A4 /* ADBTests.swift */,
76BF0ADC2C8DF660003BE568 /* AccessibilityElementTests.swift */,
);
path = MiniSimTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -619,6 +639,7 @@
7630B2752986D52900D8B57D /* NSAlert+showError.swift in Sources */,
4AFACC742AD730BE00EC369F /* SubMenuItem.swift in Sources */,
7630B25E2984339100D8B57D /* MainMenuActions.swift in Sources */,
76B70F842B0D5AB4009D87A4 /* Shell.swift in Sources */,
76AC9AF62A0EA82C00864A8B /* CustomCommands.swift in Sources */,
76489D5C29BFCA330070EF03 /* OnboardingItem.swift in Sources */,
7645D5012982E6FA00019227 /* main.swift in Sources */,
Expand Down Expand Up @@ -656,7 +677,10 @@
buildActionMask = 2147483647;
files = (
7699511F2C845CBA00462287 /* DeviceParserTests.swift in Sources */,
76BF0ADD2C8DF660003BE568 /* AccessibilityElementTests.swift in Sources */,
76B70F7E2B0D361A009D87A4 /* UserDefaultsTests.swift in Sources */,
760DEACE2B0DFB6600253576 /* ShellStub.swift in Sources */,
76B70F822B0D50FE009D87A4 /* ADBTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
5 changes: 3 additions & 2 deletions MiniSim/AccessibilityElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
//

import AppKit
import ShellOut

class AccessibilityElement {
static var shell: ShellProtocol = Shell()

private let underlyingElement: AXUIElement

required init(_ axUIElement: AXUIElement) {
Expand Down Expand Up @@ -44,7 +45,7 @@ class AccessibilityElement {
set frontmost of every process whose unix id is \(pid) to true
end tell'
"""
_ = try? shellOut(to: script)
_ = try? shell.execute(command: script)
}
}

Expand Down
55 changes: 43 additions & 12 deletions MiniSim/Service/Adb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@
//

import Foundation
import ShellOut

protocol ADBProtocol {
static var shell: ShellProtocol { get set }

static func getAdbPath() throws -> String
static func getEmulatorPath() throws -> String
static func getAdbId(for deviceName: String, adbPath: String) throws -> String
static func checkAndroidHome(path: String) throws -> Bool
static func isAccesibilityOn(deviceId: String, adbPath: String) -> Bool
static func getAdbId(for deviceName: String) throws -> String
static func checkAndroidHome(
path: String,
fileManager: FileManager
) throws -> Bool
static func isAccesibilityOn(deviceId: String) -> Bool
static func toggleAccesibility(deviceId: String)
}

final class ADB: ADBProtocol {
static var shell: ShellProtocol = Shell()

static let talkbackOn = "com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService"
static let talkbackOff = "com.android.talkback/com.google.android.marvin.talkback.TalkBackService"

Expand Down Expand Up @@ -55,13 +62,16 @@ final class ADB: ADBProtocol {
/**
Checks if passed path exists and points to `ANDROID_HOME`.
*/
@discardableResult static func checkAndroidHome(path: String) throws -> Bool {
if !FileManager.default.fileExists(atPath: path) {
@discardableResult static func checkAndroidHome(
path: String,
fileManager: FileManager = .default
) throws -> Bool {
if !fileManager.fileExists(atPath: path) {
throw AndroidHomeError.pathNotFound
}

do {
try shellOut(to: "\(path)" + Paths.emulator.rawValue, arguments: ["-list-avds"])
try shell.execute(command: "\(path)" + Paths.emulator.rawValue, arguments: ["-list-avds"])
} catch {
throw AndroidHomeError.pathNotCorrect
}
Expand All @@ -72,14 +82,20 @@ final class ADB: ADBProtocol {
try getAndroidHome() + Paths.emulator.rawValue
}

static func getAdbId(for deviceName: String, adbPath: String) throws -> String {
let onlineDevices = try shellOut(to: "\(adbPath) devices")
static func getAdbId(for deviceName: String) throws -> String {
let adbPath = try Self.getAdbPath()
let onlineDevices = try shell.execute(command: "\(adbPath) devices")
let splitted = onlineDevices.components(separatedBy: "\n")

for line in splitted {
let device = line.match("^emulator-[0-9]+")
guard let deviceId = device.first?.first else { continue }
let output = try? shellOut(to: "\(adbPath) -s \(deviceId) emu avd name").components(separatedBy: "\n")

let output = try? shell.execute(
command: "\(adbPath) -s \(deviceId) emu avd name"
)
.components(separatedBy: "\n")

if let name = output?.first {
let trimmedName = name.trimmingCharacters(in: .whitespacesAndNewlines)
let trimmedDeviceName = deviceName.trimmingCharacters(in: .whitespacesAndNewlines)
Expand All @@ -91,9 +107,12 @@ final class ADB: ADBProtocol {
throw DeviceError.deviceNotFound
}

static func isAccesibilityOn(deviceId: String, adbPath: String) -> Bool {
static func isAccesibilityOn(deviceId: String) -> Bool {
guard let adbPath = try? Self.getAdbPath() else {
return false
}
let shellCommand = "\(adbPath) -s \(deviceId) shell settings get secure enabled_accessibility_services"
guard let result = try? shellOut(to: [shellCommand]) else {
guard let result = try? shell.execute(command: shellCommand) else {
return false
}

Expand All @@ -103,4 +122,16 @@ final class ADB: ADBProtocol {

return false
}

static func toggleAccesibility(deviceId: String) {
guard let adbPath = try? Self.getAdbPath() else {
return
}
let a11yIsEnabled = Self.isAccesibilityOn(deviceId: deviceId)
let value = a11yIsEnabled ? ADB.talkbackOff : ADB.talkbackOn
let shellCmd = "\(adbPath) -s \(deviceId) shell settings put secure enabled_accessibility_services \(value)"

// Ignore the error if toggling a11y fails.
_ = try? shell.execute(command: shellCmd)
}
}
3 changes: 1 addition & 2 deletions MiniSim/Service/DeviceParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,11 @@ class AndroidEmulatorParser: DeviceParser {
}

func parse(_ input: String) -> [Device] {
guard let adbPath = try? adb.getAdbPath() else { return [] }
let deviceNames = input.components(separatedBy: .newlines)
return deviceNames
.filter { !$0.isEmpty && !$0.contains("Storing crashdata") }
.compactMap { deviceName in
let adbId = try? adb.getAdbId(for: deviceName, adbPath: adbPath)
let adbId = try? adb.getAdbId(for: deviceName)
return Device(name: deviceName, identifier: adbId, booted: adbId != nil, platform: .android, type: .virtual)
}
}
Expand Down
2 changes: 1 addition & 1 deletion MiniSim/Service/DeviceService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ extension DeviceService {
throw DeviceError.deviceNotFound
}

let a11yIsEnabled = ADB.isAccesibilityOn(deviceId: adbId, adbPath: adbPath)
let a11yIsEnabled = ADB.isAccesibilityOn(deviceId: adbId)
let value = a11yIsEnabled ? ADB.talkbackOff : ADB.talkbackOn
let shellCmd = "\(adbPath) -s \(adbId) shell settings put secure enabled_accessibility_services \(value)"
_ = try? shellOut(to: shellCmd)
Expand Down
34 changes: 34 additions & 0 deletions MiniSim/Service/Shell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Foundation
import ShellOut

protocol ShellProtocol {
@discardableResult func execute(
command: String,
arguments: [String],
atPath: String
) throws -> String
}

extension ShellProtocol {
@discardableResult func execute(
command: String,
arguments: [String] = [],
atPath: String = "."
) throws -> String {
try execute(command: command, arguments: arguments, atPath: atPath)
}
}

final class Shell: ShellProtocol {
@discardableResult func execute(
command: String,
arguments: [String] = [],
atPath: String = "."
) throws -> String {
try shellOut(
to: command,
arguments: arguments,
at: atPath
)
}
}
12 changes: 6 additions & 6 deletions MiniSim/Views/About.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@
// Created by Oskar Kwaśniewski on 28/01/2023.
//

import AcknowList
import Sparkle
import SwiftUI
import AcknowList

struct About: View {
private let updaterController: SPUStandardUpdaterController
@Environment (\.openURL) private var openURL
@State private var isAcknowledgementsListPresented = false

init() {
updaterController = SPUStandardUpdaterController(
startingUpdater: true,
updaterDelegate: nil,
userDriverDelegate: nil
)
}

let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
private let bottomPadding: Double = 10
private let minFrameWidth: Double = 650
private let minFrameHeight: Double = 450

var body: some View {
VStack {
Image(nsImage: NSImage(named: "AppIcon") ?? NSImage())
Expand All @@ -42,11 +42,11 @@ struct About: View {
Label("Check for updates", systemImage: "gear")
}
.padding(.bottom, bottomPadding)

Button("Acknowledgements") {
isAcknowledgementsListPresented.toggle()
}

HStack {
Button("GitHub") {
openURL(URL(string: "https://github.com/okwasniewski/MiniSim")!)
Expand Down
1 change: 0 additions & 1 deletion MiniSim/Views/Onboarding/SetupView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// Created by Oskar Kwaśniewski on 15/03/2023.
//

import ShellOut
import SwiftUI

struct SetupView: View {
Expand Down
1 change: 0 additions & 1 deletion MiniSim/Views/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import KeyboardShortcuts
import LaunchAtLogin
import Settings
import ShellOut
import SwiftUI

struct Preferences: View {
Expand Down
Loading