mirror of
https://github.com/somegeekintn/SimDirs.git
synced 2026-06-28 05:19:37 +00:00
Added ability to save screen.
This commit is contained in:
parent
b68c2779fd
commit
7b02bd3da2
8 changed files with 171 additions and 37 deletions
|
|
@ -19,6 +19,8 @@
|
|||
C90DCC162896B0370072E403 /* AppearancePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90DCC152896B0370072E403 /* AppearancePicker.swift */; };
|
||||
C927A0D92846414900533D66 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C927A0D82846414900533D66 /* Helpers.swift */; };
|
||||
C927A0DB2846502300533D66 /* PathActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C927A0DA2846502300533D66 /* PathActions.swift */; };
|
||||
C95CC0F828B2411700928FAE /* AppearanceButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C95CC0F728B2411700928FAE /* AppearanceButtonStyle.swift */; };
|
||||
C95CC0FA28B2414900928FAE /* SystemIconButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C95CC0F928B2414900928FAE /* SystemIconButtonStyle.swift */; };
|
||||
C9779742284F6DE000706DFB /* ToolbarMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9779741284F6DE000706DFB /* ToolbarMenu.swift */; };
|
||||
C982F859283B9F9000D491F4 /* SimDirsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C982F858283B9F9000D491F4 /* SimDirsApp.swift */; };
|
||||
C982F85B283B9F9000D491F4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C982F85A283B9F9000D491F4 /* ContentView.swift */; };
|
||||
|
|
@ -60,6 +62,8 @@
|
|||
C90DCC152896B0370072E403 /* AppearancePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearancePicker.swift; sourceTree = "<group>"; };
|
||||
C927A0D82846414900533D66 /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
|
||||
C927A0DA2846502300533D66 /* PathActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathActions.swift; sourceTree = "<group>"; };
|
||||
C95CC0F728B2411700928FAE /* AppearanceButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceButtonStyle.swift; sourceTree = "<group>"; };
|
||||
C95CC0F928B2414900928FAE /* SystemIconButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemIconButtonStyle.swift; sourceTree = "<group>"; };
|
||||
C9779741284F6DE000706DFB /* ToolbarMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarMenu.swift; sourceTree = "<group>"; };
|
||||
C982F855283B9F9000D491F4 /* SimDirs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SimDirs.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C982F858283B9F9000D491F4 /* SimDirsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimDirsApp.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -101,6 +105,16 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
C95CC0F628B240F500928FAE /* Styles */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C95CC0F728B2411700928FAE /* AppearanceButtonStyle.swift */,
|
||||
C9BF5233289FE99600BDDC91 /* DescriptiveToggleStyle.swift */,
|
||||
C95CC0F928B2414900928FAE /* SystemIconButtonStyle.swift */,
|
||||
);
|
||||
path = Styles;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C982F84C283B9F9000D491F4 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -159,12 +173,12 @@
|
|||
C982F881283E7F0400D491F4 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C95CC0F628B240F500928FAE /* Styles */,
|
||||
C9DD54C12860935300D46AB3 /* SourceItem Views */,
|
||||
C9DD54CC2860992200D46AB3 /* Model Views */,
|
||||
C90DCC152896B0370072E403 /* AppearancePicker.swift */,
|
||||
C90DCC132896AAAA0072E403 /* ContentHeader.swift */,
|
||||
C9BF5231289FE95D00BDDC91 /* DescriptiveToggle.swift */,
|
||||
C9BF5233289FE99600BDDC91 /* DescriptiveToggleStyle.swift */,
|
||||
C90BCE472861D70500C2EF35 /* ErrorView.swift */,
|
||||
C927A0DA2846502300533D66 /* PathActions.swift */,
|
||||
C9EE0CD128478FDB00E9B97A /* PathRow.swift */,
|
||||
|
|
@ -309,6 +323,7 @@
|
|||
C982F877283D020C00D491F4 /* SimProductFamily.swift in Sources */,
|
||||
C982F859283B9F9000D491F4 /* SimDirsApp.swift in Sources */,
|
||||
C982F871283CE7B800D491F4 /* SimRuntime.swift in Sources */,
|
||||
C95CC0FA28B2414900928FAE /* SystemIconButtonStyle.swift in Sources */,
|
||||
C9EE0CD228478FDB00E9B97A /* PathRow.swift in Sources */,
|
||||
C982F86B283BA22100D491F4 /* SimPlatform.swift in Sources */,
|
||||
C927A0D92846414900533D66 /* Helpers.swift in Sources */,
|
||||
|
|
@ -317,6 +332,7 @@
|
|||
C9D73C29285C8C4B0044A279 /* SourceItem.swift in Sources */,
|
||||
C982F879283D042E00D491F4 /* SimModel.swift in Sources */,
|
||||
C982F87B283E40C800D491F4 /* SimCtl.swift in Sources */,
|
||||
C95CC0F828B2411700928FAE /* AppearanceButtonStyle.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -115,4 +115,8 @@ struct SimCtl {
|
|||
func setDeviceIncreaseContrast(_ device: SimDevice, increaseContrast: SimDevice.IncreaseContrast) throws {
|
||||
try runAsync(args: ["ui", device.udid, "increase_contrast", increaseContrast.rawValue])
|
||||
}
|
||||
|
||||
func saveScreen(_ device: SimDevice, url: URL) throws {
|
||||
try runAsync(args: ["io", device.udid, "screenshot", url.path])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,6 +182,14 @@ class SimDevice: ObservableObject, Decodable {
|
|||
print("Failed to set device increase contrast: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func saveScreen(_ url: URL) {
|
||||
do {
|
||||
try SimCtl().saveScreen(self, url: url)
|
||||
} catch {
|
||||
print("Failed to save screen: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SimDevice {
|
||||
|
|
|
|||
|
|
@ -7,42 +7,6 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
extension ButtonStyle where Self == AppearanceButtonStyle {
|
||||
static func appearance(selected: Bool, scheme: ColorScheme) -> AppearanceButtonStyle {
|
||||
AppearanceButtonStyle(selected: selected, scheme: scheme)
|
||||
}
|
||||
}
|
||||
|
||||
struct AppearanceButtonStyle: ButtonStyle {
|
||||
let selected : Bool
|
||||
let scheme : ColorScheme
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
VStack {
|
||||
let bordered = selected != configuration.isPressed
|
||||
let color = scheme == .light ? Color.white : Color.black
|
||||
let content = color
|
||||
.frame(width: 48, height: 32)
|
||||
.cornerRadius(5.0)
|
||||
|
||||
if bordered {
|
||||
content
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.0)
|
||||
.stroke(Color.accentColor, lineWidth: 2.0)
|
||||
)
|
||||
}
|
||||
else {
|
||||
content
|
||||
.shadow(color: .black.opacity(0.5), radius: 1.0, x: 0, y: 1.0)
|
||||
}
|
||||
|
||||
configuration.label
|
||||
}
|
||||
.padding(1.0)
|
||||
}
|
||||
}
|
||||
|
||||
struct AppearancePicker: View {
|
||||
@Environment(\.isEnabled) var isEnabled
|
||||
@Binding var scheme : ColorScheme?
|
||||
|
|
|
|||
|
|
@ -48,6 +48,14 @@ struct DeviceContent: View {
|
|||
@ObservedObject var device : SimDevice
|
||||
@State var isBooted : Bool
|
||||
|
||||
var fileDateFormatter : DateFormatter {
|
||||
let formatter = DateFormatter()
|
||||
|
||||
formatter.dateFormat = "yyyy.MM.dd'_'HH.mm.ss"
|
||||
|
||||
return formatter
|
||||
}
|
||||
|
||||
init(_ device: SimDevice) {
|
||||
self.device = device
|
||||
self.isBooted = device.isBooted
|
||||
|
|
@ -91,6 +99,14 @@ struct DeviceContent: View {
|
|||
.opacity(isBooted ? 1.0 : 0.5)
|
||||
}
|
||||
}
|
||||
|
||||
ContentHeader("Actions")
|
||||
Button(action: saveScreen) {
|
||||
Text("Save Screen")
|
||||
.fontWeight(.semibold)
|
||||
.font(.system(size: 11))
|
||||
}
|
||||
.buttonStyle(.systemIcon("camera.on.rectangle"))
|
||||
}
|
||||
.environment(\.isEnabled, isBooted)
|
||||
.onAppear {
|
||||
|
|
@ -108,6 +124,24 @@ struct DeviceContent: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func saveScreen() {
|
||||
let savePanel = NSSavePanel()
|
||||
|
||||
savePanel.allowedContentTypes = [.png]
|
||||
savePanel.canCreateDirectories = true
|
||||
savePanel.isExtensionHidden = false
|
||||
savePanel.title = "Save Screen"
|
||||
savePanel.message = "Select destination"
|
||||
savePanel.nameFieldLabel = "Filename:"
|
||||
savePanel.nameFieldStringValue = "\(device.name) - \(fileDateFormatter.string(from: Date()))"
|
||||
|
||||
if savePanel.runModal() == .OK {
|
||||
if let url = savePanel.url {
|
||||
device.saveScreen(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DeviceContent_Previews: PreviewProvider {
|
||||
|
|
|
|||
44
SimDirs/Views/Styles/AppearanceButtonStyle.swift
Normal file
44
SimDirs/Views/Styles/AppearanceButtonStyle.swift
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// AppearanceButtonStyle.swift
|
||||
// SimDirs
|
||||
//
|
||||
// Created by Casey Fleser on 8/21/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
extension ButtonStyle where Self == AppearanceButtonStyle {
|
||||
static func appearance(selected: Bool, scheme: ColorScheme) -> AppearanceButtonStyle {
|
||||
AppearanceButtonStyle(selected: selected, scheme: scheme)
|
||||
}
|
||||
}
|
||||
|
||||
struct AppearanceButtonStyle: ButtonStyle {
|
||||
let selected : Bool
|
||||
let scheme : ColorScheme
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
VStack {
|
||||
let bordered = selected != configuration.isPressed
|
||||
let color = scheme == .light ? Color.white : Color.black
|
||||
let content = color
|
||||
.frame(width: 48, height: 32)
|
||||
.cornerRadius(5.0)
|
||||
|
||||
if bordered {
|
||||
content
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.0)
|
||||
.stroke(Color.accentColor, lineWidth: 2.0)
|
||||
)
|
||||
}
|
||||
else {
|
||||
content
|
||||
.shadow(color: .black.opacity(0.5), radius: 1.0, x: 0, y: 1.0)
|
||||
}
|
||||
|
||||
configuration.label
|
||||
}
|
||||
.padding(1.0)
|
||||
}
|
||||
}
|
||||
64
SimDirs/Views/Styles/SystemIconButtonStyle.swift
Normal file
64
SimDirs/Views/Styles/SystemIconButtonStyle.swift
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// SystemIconButtonStyle.swift
|
||||
// SimDirs
|
||||
//
|
||||
// Created by Casey Fleser on 8/21/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
extension ButtonStyle where Self == SystemIconButtonStyle {
|
||||
static func systemIcon(_ imageName: String) -> SystemIconButtonStyle {
|
||||
SystemIconButtonStyle(imageName)
|
||||
}
|
||||
}
|
||||
|
||||
struct SystemIconButtonStyle: ButtonStyle {
|
||||
@State var isFocused = false
|
||||
let imageName : String
|
||||
|
||||
init(_ imageName: String) {
|
||||
self.imageName = imageName
|
||||
}
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
VStack {
|
||||
ZStack {
|
||||
backgroundColor(pressed: configuration.isPressed)
|
||||
.frame(width: 36, height: 36)
|
||||
.cornerRadius(5.0)
|
||||
|
||||
Image(systemName: imageName)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: ContentMode.fit)
|
||||
.frame(width: 24, height: 24)
|
||||
}
|
||||
|
||||
configuration.label
|
||||
}
|
||||
.foregroundColor(foregroundColor(pressed: configuration.isPressed))
|
||||
.padding(1.0)
|
||||
.onHover { isFocused = $0 }
|
||||
}
|
||||
|
||||
func foregroundColor(pressed: Bool) -> Color {
|
||||
return .primary.opacity(pressed ? 1.0 : 0.6)
|
||||
}
|
||||
|
||||
func backgroundColor(pressed: Bool) -> Color {
|
||||
return .primary.opacity(0.05 + (isFocused ? 0.1 : 0.0) + (pressed ? 0.1 : 0.0))
|
||||
}
|
||||
}
|
||||
|
||||
struct SystemIconButtonStyle_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Button("Button") { print("do stuff") }
|
||||
.preferredColorScheme(.light)
|
||||
.buttonStyle(.systemIcon("camera.on.rectangle"))
|
||||
.padding(20)
|
||||
Button("Button") { print("do stuff") }
|
||||
.preferredColorScheme(.dark)
|
||||
.buttonStyle(.systemIcon("camera.on.rectangle"))
|
||||
.padding(20)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue