mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 05:19:13 +00:00
bell ringing backend done now need to actually trigger it
added ring() to ring the bell terminal is now a fullscreencover can be dismissed and reopened or disconnected - need to make it keep the scrollback increased sleep between reads added support for title added setTitle function, defaults to username@server increased the buffer to 16384 bytes
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
VERSION = 1.0
|
||||
BUILD = 3
|
||||
BUILD = 27
|
||||
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://developer.apple.com/documentation/xcode/adding-a-build-configuration-file-to-your-project
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
A9083E402DF2226F0042906E /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = A9083E3F2DF2225A0042906E /* libz.tbd */; };
|
||||
A92317282E07111E00ECE1E6 /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = A92317272E07111E00ECE1E6 /* SwiftTerm */; };
|
||||
A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92317292E07113100ECE1E6 /* TerminalController.swift */; };
|
||||
A923172D2E07138000ECE1E6 /* SSHTerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172C2E07138000ECE1E6 /* SSHTerminalView.swift */; };
|
||||
A923172F2E08851200ECE1E6 /* ShellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172E2E08851200ECE1E6 /* ShellView.swift */; };
|
||||
@@ -32,6 +31,7 @@
|
||||
A985545F2E056EDD009051BD /* KeychainLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A985545E2E056EDD009051BD /* KeychainLayer.swift */; };
|
||||
A98554612E058433009051BD /* HostsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98554602E058433009051BD /* HostsManager.swift */; };
|
||||
A98554632E0587DF009051BD /* HostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98554622E0587DF009051BD /* HostsView.swift */; };
|
||||
A9A587202E0BF220006B31E6 /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = A9A5871F2E0BF220006B31E6 /* SwiftTerm */; };
|
||||
A9B15A9A2E0ABA0400F66E02 /* DialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B15A992E0ABA0400F66E02 /* DialogView.swift */; };
|
||||
A9C4140C2E096DB7005E3047 /* SSHError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C4140B2E096DB7005E3047 /* SSHError.swift */; };
|
||||
A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */; };
|
||||
@@ -110,7 +110,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A95FAA542DF4B62900DE2F5A /* LibSSH.xcframework in Frameworks */,
|
||||
A92317282E07111E00ECE1E6 /* SwiftTerm in Frameworks */,
|
||||
A9A587202E0BF220006B31E6 /* SwiftTerm in Frameworks */,
|
||||
A93143BE2DF4D0B300FCD5DB /* libpthread.tbd in Frameworks */,
|
||||
A9083E402DF2226F0042906E /* libz.tbd in Frameworks */,
|
||||
A95FAA562DF4B62A00DE2F5A /* openssl.xcframework in Frameworks */,
|
||||
@@ -294,7 +294,7 @@
|
||||
);
|
||||
name = ShhShell;
|
||||
packageProductDependencies = (
|
||||
A92317272E07111E00ECE1E6 /* SwiftTerm */,
|
||||
A9A5871F2E0BF220006B31E6 /* SwiftTerm */,
|
||||
);
|
||||
productName = ShhShell;
|
||||
productReference = A925389A2DEE06DC007E0A18 /* ShhShell.app */;
|
||||
@@ -373,7 +373,7 @@
|
||||
mainGroup = A92538912DEE06DC007E0A18;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
packageReferences = (
|
||||
A92317262E07111E00ECE1E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */,
|
||||
A9A5871E2E0BF220006B31E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = A925389B2DEE06DC007E0A18 /* Products */;
|
||||
@@ -624,7 +624,7 @@
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_STRICT_CONCURRENCY = complete;
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 6.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -660,7 +660,7 @@
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_STRICT_CONCURRENCY = complete;
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 6.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
@@ -779,20 +779,20 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
A92317262E07111E00ECE1E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */ = {
|
||||
A9A5871E2E0BF220006B31E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/migueldeicaza/SwiftTerm";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 1.2.5;
|
||||
branch = main;
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
A92317272E07111E00ECE1E6 /* SwiftTerm */ = {
|
||||
A9A5871F2E0BF220006B31E6 /* SwiftTerm */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A92317262E07111E00ECE1E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */;
|
||||
package = A9A5871E2E0BF220006B31E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */;
|
||||
productName = SwiftTerm;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/migueldeicaza/SwiftTerm",
|
||||
"state" : {
|
||||
"revision" : "e2b431dbf73f775fb4807a33e4572ffd3dc6933a",
|
||||
"version" : "1.2.5"
|
||||
"branch" : "main",
|
||||
"revision" : "f8e6e08b5a8c8eb0b18b9c250f36121e55c68f49"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -17,11 +17,12 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
|
||||
// @Published var hostsManager = HostsManager()
|
||||
|
||||
@Published var title: String = ""
|
||||
@Published var connected: Bool = false
|
||||
@Published var authorized: Bool = false
|
||||
@Published var testSuceeded: Bool? = nil
|
||||
|
||||
@Published var bell: UUID?
|
||||
@Published var bell: UUID? = nil
|
||||
|
||||
@Published var host: Host
|
||||
|
||||
@@ -76,6 +77,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
}
|
||||
}
|
||||
openShell()
|
||||
setTitle("\(host.username)@\(host.address)")
|
||||
ssh_channel_request_env(channel, "TERM", "xterm-256color")
|
||||
ssh_channel_request_env(channel, "LANG", "en_US.UTF-8")
|
||||
ssh_channel_request_env(channel, "LC_ALL", "en_US.UTF-8")
|
||||
@@ -132,6 +134,17 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
|
||||
}
|
||||
|
||||
func ring() {
|
||||
withAnimation { bell = UUID() }
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
|
||||
withAnimation { self.bell = nil }
|
||||
}
|
||||
}
|
||||
|
||||
func setTitle(_ newTitle: String) {
|
||||
self.title = newTitle
|
||||
}
|
||||
|
||||
func testExec() {
|
||||
if ssh_is_connected(session) == 0 {
|
||||
withAnimation { testSuceeded = false }
|
||||
@@ -208,6 +221,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
//MARK: auth
|
||||
func authWithPubkey(pub pubInp: Data, priv privInp: Data, pass: String) throws(KeyError) {
|
||||
guard session != nil else {
|
||||
withAnimation { authorized = false }
|
||||
@@ -309,6 +323,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
print(recievedMethod)
|
||||
}
|
||||
|
||||
//MARK: shell
|
||||
func openShell() {
|
||||
var status: CInt
|
||||
|
||||
@@ -346,7 +361,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
return nil
|
||||
}
|
||||
|
||||
var buffer: [CChar] = Array(repeating: 0, count: 4096)
|
||||
var buffer: [CChar] = Array(repeating: 0, count: 16_384)
|
||||
let nbytes = ssh_channel_read_nonblocking(channel, &buffer, UInt32(buffer.count), 0)
|
||||
|
||||
guard nbytes > 0 else { return nil }
|
||||
@@ -354,7 +369,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
let data = Data(bytes: buffer, count: Int(nbytes))
|
||||
if let string = String(data: data, encoding: .utf8) {
|
||||
#if DEBUG
|
||||
print(String(data: Data(bytes: buffer, count: Int(nbytes)), encoding: .utf8)!)
|
||||
// print(String(data: Data(bytes: buffer, count: Int(nbytes)), encoding: .utf8)!)
|
||||
#endif
|
||||
return string
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ struct ConnectionView: View {
|
||||
@State var pubkeyStr: String = ""
|
||||
@State var privkeyStr: String = ""
|
||||
|
||||
@State var showTerminal: Bool = false
|
||||
@State var privPickerPresented: Bool = false
|
||||
@State var pubPickerPresented: Bool = false
|
||||
|
||||
@@ -128,12 +129,12 @@ struct ConnectionView: View {
|
||||
}
|
||||
}
|
||||
|
||||
NavigationLink() {
|
||||
ShellView(handler: handler)
|
||||
Button() {
|
||||
showTerminal.toggle()
|
||||
} label: {
|
||||
Label("Open Terminal", systemImage: "apple.terminal")
|
||||
Label("Show Terminal", systemImage: "apple.terminal")
|
||||
}
|
||||
.disabled(!(handler.connected && handler.authorized))
|
||||
.disabled(!handler.connected || !handler.authorized)
|
||||
|
||||
Button() {
|
||||
if handler.authorized && handler.connected {
|
||||
@@ -169,6 +170,7 @@ struct ConnectionView: View {
|
||||
ToolbarItem() {
|
||||
Button() {
|
||||
handler.go()
|
||||
showTerminal = handler.connected && handler.authorized
|
||||
} label: {
|
||||
Label(
|
||||
handler.connected ? "Disconnect" : "Connect",
|
||||
@@ -178,6 +180,9 @@ struct ConnectionView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.fullScreenCover(isPresented: $showTerminal) {
|
||||
ShellView(handler: handler)
|
||||
}
|
||||
.onDisappear {
|
||||
guard hostsManager.getHostMatching(handler.host) == handler.host else {
|
||||
hostsManager.updateHost(handler.host)
|
||||
|
||||
@@ -26,15 +26,15 @@ struct HostsView: View {
|
||||
}
|
||||
|
||||
//proves that u can connect to multiple at the same time
|
||||
// NavigationLink() {
|
||||
// ForEach(hostsManager.savedHosts) { host in
|
||||
// let miniHandler = SSHHandler(host: host)
|
||||
// TerminalController(handler: miniHandler)
|
||||
// .onAppear { miniHandler.go() }
|
||||
// }
|
||||
// } label: {
|
||||
// Label("multiview", systemImage: "square.split.2x2")
|
||||
// }
|
||||
NavigationLink() {
|
||||
ForEach(hostsManager.savedHosts) { host in
|
||||
let miniHandler = SSHHandler(host: host)
|
||||
TerminalController(handler: miniHandler)
|
||||
.onAppear { miniHandler.go() }
|
||||
}
|
||||
} label: {
|
||||
Label("multiview", systemImage: "square.split.2x2")
|
||||
}
|
||||
|
||||
ForEach(hostsManager.savedHosts) { host in
|
||||
NavigationLink() {
|
||||
|
||||
@@ -35,7 +35,7 @@ final class SSHTerminalView: TerminalView, Sendable, @preconcurrency TerminalVie
|
||||
await self.feed(text: read)
|
||||
}
|
||||
} else {
|
||||
try? await Task.sleep(nanoseconds: 1_000_000) //1ms
|
||||
try? await Task.sleep(nanoseconds: 10_000_000) //10ms
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ final class SSHTerminalView: TerminalView, Sendable, @preconcurrency TerminalVie
|
||||
await self.feed(text: read)
|
||||
}
|
||||
} else {
|
||||
Task{ try? await Task.sleep(nanoseconds: 1_000_000) }
|
||||
Task{ try? await Task.sleep(nanoseconds: 10_000_000) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,9 @@ final class SSHTerminalView: TerminalView, Sendable, @preconcurrency TerminalVie
|
||||
}
|
||||
|
||||
nonisolated public func setTerminalTitle(source: TerminalView, title: String) {
|
||||
print("set title to \(title)")
|
||||
Task {
|
||||
await MainActor.run { handler?.setTitle(title) }
|
||||
}
|
||||
}
|
||||
|
||||
public func sizeChanged(source: TerminalView, newCols: Int, newRows: Int) {
|
||||
|
||||
@@ -16,6 +16,11 @@ struct ShellView: View {
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ZStack {
|
||||
if handler.bell != nil {
|
||||
Text("🔔")
|
||||
.font(.title)
|
||||
.transition(.scale)
|
||||
}
|
||||
if !handler.connected {
|
||||
DialogView(handler: handler, showDialog: !handler.connected)
|
||||
}
|
||||
@@ -27,18 +32,27 @@ struct ShellView: View {
|
||||
.toolbar {
|
||||
ToolbarItem {
|
||||
Button() {
|
||||
handler.go()
|
||||
if !handler.connected {
|
||||
dismiss()
|
||||
Task {
|
||||
await handler.disconnect()
|
||||
if !handler.connected { dismiss() }
|
||||
}
|
||||
} label: {
|
||||
Label(
|
||||
handler.connected ? "Disconnect" : "Connect",
|
||||
systemImage: handler.connected ? "xmark.app.fill" : "power"
|
||||
)
|
||||
Label("Disconnect", systemImage: "xmark.app.fill")
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button() {
|
||||
dismiss()
|
||||
} label: {
|
||||
Label("Close", systemImage: "arrow.down.right.and.arrow.up.left")
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: handler.connected) { _ in
|
||||
if !handler.connected { dismiss() }
|
||||
}
|
||||
.navigationTitle(handler.title)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user