mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 13:26:16 +00:00
remove terminal string
rewrote authWithPubkey() to not write files and take data direcytly remove read loop (comment adding it) readfromchannel returns string using swifterm to do terminal emulation
This commit is contained in:
@@ -8,13 +8,9 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
A9083E402DF2226F0042906E /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = A9083E3F2DF2225A0042906E /* libz.tbd */; };
|
||||
A91AE38A2DF722A700FF3537 /* Runestone in Frameworks */ = {isa = PBXBuildFile; productRef = A91AE3892DF722A600FF3537 /* Runestone */; };
|
||||
A91AE3B22DF73E0900FF3537 /* TerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91AE3B12DF73E0900FF3537 /* TerminalView.swift */; };
|
||||
A91AE3B52DF73F1D00FF3537 /* TreeSitterBash in Frameworks */ = {isa = PBXBuildFile; productRef = A91AE3B42DF73F1D00FF3537 /* TreeSitterBash */; };
|
||||
A91AE3B72DF73F1D00FF3537 /* TreeSitterBashQueries in Frameworks */ = {isa = PBXBuildFile; productRef = A91AE3B62DF73F1D00FF3537 /* TreeSitterBashQueries */; };
|
||||
A91AE3B92DF73F1D00FF3537 /* TreeSitterBashRunestone in Frameworks */ = {isa = PBXBuildFile; productRef = A91AE3B82DF73F1D00FF3537 /* TreeSitterBashRunestone */; };
|
||||
A91AE3BB2DF73F1D00FF3537 /* TreeSitterLanguagesCommon in Frameworks */ = {isa = PBXBuildFile; productRef = A91AE3BA2DF73F1D00FF3537 /* TreeSitterLanguagesCommon */; };
|
||||
A91AE3BD2DF7402100FF3537 /* TextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91AE3BC2DF7402100FF3537 /* TextViewController.swift */; };
|
||||
A92317282E07111E00ECE1E6 /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = A92317272E07111E00ECE1E6 /* SwiftTerm */; };
|
||||
A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92317292E07113100ECE1E6 /* TerminalController.swift */; };
|
||||
A923172D2E07138000ECE1E6 /* TerminalDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172C2E07138000ECE1E6 /* TerminalDelegate.swift */; };
|
||||
A92538C82DEE0742007E0A18 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538C52DEE0742007E0A18 /* ContentView.swift */; };
|
||||
A92538C92DEE0742007E0A18 /* ShhShellApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538C62DEE0742007E0A18 /* ShhShellApp.swift */; };
|
||||
A92538CA2DEE0742007E0A18 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A92538C42DEE0742007E0A18 /* Assets.xcassets */; };
|
||||
@@ -72,8 +68,8 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
A9083E3F2DF2225A0042906E /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
A91AE3B12DF73E0900FF3537 /* TerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalView.swift; sourceTree = "<group>"; };
|
||||
A91AE3BC2DF7402100FF3537 /* TextViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewController.swift; sourceTree = "<group>"; };
|
||||
A92317292E07113100ECE1E6 /* TerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalController.swift; sourceTree = "<group>"; };
|
||||
A923172C2E07138000ECE1E6 /* TerminalDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalDelegate.swift; sourceTree = "<group>"; };
|
||||
A925389A2DEE06DC007E0A18 /* ShhShell.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShhShell.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A92538A72DEE06DE007E0A18 /* ShhShellTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShhShellTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A92538B12DEE06DE007E0A18 /* ShhShellUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShhShellUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -107,13 +103,9 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A91AE3B72DF73F1D00FF3537 /* TreeSitterBashQueries in Frameworks */,
|
||||
A95FAA542DF4B62900DE2F5A /* LibSSH.xcframework in Frameworks */,
|
||||
A91AE3B52DF73F1D00FF3537 /* TreeSitterBash in Frameworks */,
|
||||
A91AE3B92DF73F1D00FF3537 /* TreeSitterBashRunestone in Frameworks */,
|
||||
A91AE38A2DF722A700FF3537 /* Runestone in Frameworks */,
|
||||
A92317282E07111E00ECE1E6 /* SwiftTerm in Frameworks */,
|
||||
A93143BE2DF4D0B300FCD5DB /* libpthread.tbd in Frameworks */,
|
||||
A91AE3BB2DF73F1D00FF3537 /* TreeSitterLanguagesCommon in Frameworks */,
|
||||
A9083E402DF2226F0042906E /* libz.tbd in Frameworks */,
|
||||
A95FAA562DF4B62A00DE2F5A /* openssl.xcframework in Frameworks */,
|
||||
);
|
||||
@@ -136,6 +128,15 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
A923172B2E0712F200ECE1E6 /* Terminal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A92317292E07113100ECE1E6 /* TerminalController.swift */,
|
||||
A923172C2E07138000ECE1E6 /* TerminalDelegate.swift */,
|
||||
);
|
||||
path = Terminal;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A92538912DEE06DC007E0A18 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -197,8 +198,8 @@
|
||||
A92538C52DEE0742007E0A18 /* ContentView.swift */,
|
||||
A98554622E0587DF009051BD /* HostsView.swift */,
|
||||
A985545C2E055D4D009051BD /* ConnectionView.swift */,
|
||||
A98554522E055347009051BD /* Terminal */,
|
||||
A93143C52DF61FE300FCD5DB /* ViewModifiers.swift */,
|
||||
A923172B2E0712F200ECE1E6 /* Terminal */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@@ -229,15 +230,6 @@
|
||||
path = ci_scripts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A98554522E055347009051BD /* Terminal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A91AE3B12DF73E0900FF3537 /* TerminalView.swift */,
|
||||
A91AE3BC2DF7402100FF3537 /* TextViewController.swift */,
|
||||
);
|
||||
path = Terminal;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A98554532E05534F009051BD /* Keys */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -293,11 +285,7 @@
|
||||
);
|
||||
name = ShhShell;
|
||||
packageProductDependencies = (
|
||||
A91AE3892DF722A600FF3537 /* Runestone */,
|
||||
A91AE3B42DF73F1D00FF3537 /* TreeSitterBash */,
|
||||
A91AE3B62DF73F1D00FF3537 /* TreeSitterBashQueries */,
|
||||
A91AE3B82DF73F1D00FF3537 /* TreeSitterBashRunestone */,
|
||||
A91AE3BA2DF73F1D00FF3537 /* TreeSitterLanguagesCommon */,
|
||||
A92317272E07111E00ECE1E6 /* SwiftTerm */,
|
||||
);
|
||||
productName = ShhShell;
|
||||
productReference = A925389A2DEE06DC007E0A18 /* ShhShell.app */;
|
||||
@@ -376,8 +364,7 @@
|
||||
mainGroup = A92538912DEE06DC007E0A18;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
packageReferences = (
|
||||
A91AE3882DF722A600FF3537 /* XCRemoteSwiftPackageReference "runestone" */,
|
||||
A91AE3B32DF73F1D00FF3537 /* XCRemoteSwiftPackageReference "treesitterlanguages" */,
|
||||
A92317262E07111E00ECE1E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = A925389B2DEE06DC007E0A18 /* Products */;
|
||||
@@ -430,11 +417,11 @@
|
||||
A92538C92DEE0742007E0A18 /* ShhShellApp.swift in Sources */,
|
||||
A98554612E058433009051BD /* HostsManager.swift in Sources */,
|
||||
A985545D2E055D4D009051BD /* ConnectionView.swift in Sources */,
|
||||
A91AE3B22DF73E0900FF3537 /* TerminalView.swift in Sources */,
|
||||
A98554592E0553AA009051BD /* KeyManager.swift in Sources */,
|
||||
A91AE3BD2DF7402100FF3537 /* TextViewController.swift in Sources */,
|
||||
A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */,
|
||||
A98554552E05535F009051BD /* KeyManagerView.swift in Sources */,
|
||||
A923172D2E07138000ECE1E6 /* TerminalDelegate.swift in Sources */,
|
||||
A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -770,49 +757,21 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
A91AE3882DF722A600FF3537 /* XCRemoteSwiftPackageReference "runestone" */ = {
|
||||
A92317262E07111E00ECE1E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/simonbs/runestone";
|
||||
repositoryURL = "https://github.com/migueldeicaza/SwiftTerm";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.5.1;
|
||||
};
|
||||
};
|
||||
A91AE3B32DF73F1D00FF3537 /* XCRemoteSwiftPackageReference "treesitterlanguages" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/simonbs/treesitterlanguages";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.1.10;
|
||||
minimumVersion = 1.2.5;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
A91AE3892DF722A600FF3537 /* Runestone */ = {
|
||||
A92317272E07111E00ECE1E6 /* SwiftTerm */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A91AE3882DF722A600FF3537 /* XCRemoteSwiftPackageReference "runestone" */;
|
||||
productName = Runestone;
|
||||
};
|
||||
A91AE3B42DF73F1D00FF3537 /* TreeSitterBash */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A91AE3B32DF73F1D00FF3537 /* XCRemoteSwiftPackageReference "treesitterlanguages" */;
|
||||
productName = TreeSitterBash;
|
||||
};
|
||||
A91AE3B62DF73F1D00FF3537 /* TreeSitterBashQueries */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A91AE3B32DF73F1D00FF3537 /* XCRemoteSwiftPackageReference "treesitterlanguages" */;
|
||||
productName = TreeSitterBashQueries;
|
||||
};
|
||||
A91AE3B82DF73F1D00FF3537 /* TreeSitterBashRunestone */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A91AE3B32DF73F1D00FF3537 /* XCRemoteSwiftPackageReference "treesitterlanguages" */;
|
||||
productName = TreeSitterBashRunestone;
|
||||
};
|
||||
A91AE3BA2DF73F1D00FF3537 /* TreeSitterLanguagesCommon */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A91AE3B32DF73F1D00FF3537 /* XCRemoteSwiftPackageReference "treesitterlanguages" */;
|
||||
productName = TreeSitterLanguagesCommon;
|
||||
package = A92317262E07111E00ECE1E6 /* XCRemoteSwiftPackageReference "SwiftTerm" */;
|
||||
productName = SwiftTerm;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
|
||||
@@ -1,31 +1,13 @@
|
||||
{
|
||||
"originHash" : "7b91b8af81dcd3e1958c781705a4b5920fdcdef24313a6e025be307b7bc092d5",
|
||||
"originHash" : "4d9d9af82f23f3c708bdd502fed3939413b4f2a95a79ae568364cc92bca1527e",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "runestone",
|
||||
"identity" : "swiftterm",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/simonbs/Runestone",
|
||||
"location" : "https://github.com/migueldeicaza/SwiftTerm",
|
||||
"state" : {
|
||||
"revision" : "1fad339aab99cf2136ce6bf8c32da3265b2e85e5",
|
||||
"version" : "0.5.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "tree-sitter",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/tree-sitter/tree-sitter",
|
||||
"state" : {
|
||||
"revision" : "98be227227af10cc7a269cb3ffb23686c0610b17",
|
||||
"version" : "0.20.9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "treesitterlanguages",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/simonbs/treesitterlanguages",
|
||||
"state" : {
|
||||
"revision" : "15cf3a9ec3ab95e0d058b7df9f35619123c9e02d",
|
||||
"version" : "0.1.10"
|
||||
"revision" : "e2b431dbf73f775fb4807a33e4572ffd3dc6933a",
|
||||
"version" : "1.2.5"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -20,7 +20,6 @@ class SSHHandler: ObservableObject {
|
||||
@Published var testSuceeded: Bool? = nil
|
||||
|
||||
@Published var host: Host
|
||||
@Published var terminal: String = ""
|
||||
|
||||
private let userDefaults = NSUbiquitousKeyValueStore.default
|
||||
private let logger = Logger(subsystem: "xy", category: "sshHandler")
|
||||
@@ -88,7 +87,6 @@ class SSHHandler: ObservableObject {
|
||||
withAnimation { connected = false }
|
||||
withAnimation { testSuceeded = nil }
|
||||
session = nil
|
||||
terminal = ""
|
||||
// host.key = nil
|
||||
}
|
||||
|
||||
@@ -173,28 +171,29 @@ class SSHHandler: ObservableObject {
|
||||
withAnimation { authorized = false }
|
||||
return
|
||||
}
|
||||
|
||||
var status: Int32
|
||||
let fileManager = FileManager.default
|
||||
let tempDir = fileManager.temporaryDirectory
|
||||
let tempPubkey = tempDir.appendingPathComponent("key.pub")
|
||||
let tempKey = tempDir.appendingPathComponent("key")
|
||||
|
||||
fileManager.createFile(atPath: tempPubkey.path(), contents: nil)
|
||||
fileManager.createFile(atPath: tempKey.path(), contents: nil)
|
||||
print(pubInp)
|
||||
var pubInpCChar: [Int8] = []
|
||||
for byte in pubInp {
|
||||
pubInpCChar.append(Int8(byte))
|
||||
}
|
||||
|
||||
try? pubInp.write(to: tempPubkey)
|
||||
try? privInp.write(to: tempKey)
|
||||
var privInpCChar: [Int8] = []
|
||||
for byte in privInp {
|
||||
privInpCChar.append(Int8(byte))
|
||||
}
|
||||
|
||||
var pubkey: ssh_key?
|
||||
ssh_pki_import_pubkey_file(tempPubkey.path(), &pubkey)
|
||||
|
||||
ssh_pki_import_pubkey_base64(&pubInpCChar, SSH_KEYTYPE_SK_ED25519, &pubkey)
|
||||
status = ssh_userauth_try_publickey(session, nil, pubkey)
|
||||
print(status)
|
||||
|
||||
var privkey: ssh_key?
|
||||
if ssh_pki_import_privkey_file(tempKey.path(), pass, nil, nil, &privkey) != 0 {
|
||||
if ssh_pki_import_privkey_base64(&privInpCChar, pass, nil, nil, &privkey) != 0 {
|
||||
print("help?!?")
|
||||
print("likeley password is incorrect")
|
||||
print("likeley passphrase is incorrect")
|
||||
}
|
||||
|
||||
status = ssh_userauth_publickey(session, nil, privkey)
|
||||
@@ -207,11 +206,6 @@ class SSHHandler: ObservableObject {
|
||||
withAnimation { authorized = true }
|
||||
return
|
||||
//if u got this far, youre authed!
|
||||
//cleanpu here:
|
||||
// ssh_key_free(pubkey)
|
||||
// ssh_key_free(privkey)
|
||||
// try? fileManager.removeItem(at: tempPubkey)
|
||||
// try? fileManager.removeItem(at: tempKey)
|
||||
}
|
||||
|
||||
func authWithPw() -> Bool {
|
||||
@@ -305,26 +299,25 @@ class SSHHandler: ObservableObject {
|
||||
self.readTimer = nil
|
||||
return
|
||||
}
|
||||
self.readFromChannel()
|
||||
}
|
||||
RunLoop.main.add(self.readTimer!, forMode: .common)
|
||||
// RunLoop.main.add(self.readTimer!, forMode: .common)
|
||||
}
|
||||
|
||||
func readFromChannel() {
|
||||
guard ssh_channel_is_open(channel) != 0 else { return }
|
||||
guard ssh_channel_is_eof(channel) == 0 else { return }
|
||||
func readFromChannel() -> String {
|
||||
guard ssh_channel_is_open(channel) != 0 else { return "" }
|
||||
guard ssh_channel_is_eof(channel) == 0 else { return "" }
|
||||
|
||||
var buffer: [CChar] = Array(repeating: 0, count: 256)
|
||||
let nbytes = ssh_channel_read_nonblocking(channel, &buffer, UInt32(buffer.count), 0)
|
||||
|
||||
guard nbytes > 0 else { return }
|
||||
guard nbytes > 0 else { return "" }
|
||||
write(1, buffer, Int(nbytes))
|
||||
|
||||
let data = Data(bytes: buffer, count: buffer.count)
|
||||
if let string = String(data: data, encoding: .utf8) {
|
||||
self.terminal.append(string)
|
||||
terminal = self.terminal.replacingOccurrences(of: "[K", with: "\n")
|
||||
return string
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
private func logSshGetError() {
|
||||
|
||||
@@ -75,7 +75,7 @@ struct ConnectionView: View {
|
||||
.fileImporter(isPresented: $pubPickerPresented, allowedContentTypes: [.item, .content, .data]) { (Result) in
|
||||
do {
|
||||
let fileURL = try Result.get()
|
||||
pubkey = try! Data(contentsOf: fileURL)
|
||||
pubkey = try? Data(contentsOf: fileURL)
|
||||
print(fileURL)
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
@@ -97,7 +97,8 @@ struct ConnectionView: View {
|
||||
.fileImporter(isPresented: $privPickerPresented, allowedContentTypes: [.item, .content, .data]) { (Result) in
|
||||
do {
|
||||
let fileURL = try Result.get()
|
||||
privkey = try! Data(contentsOf: fileURL)
|
||||
privkey = try? Data(contentsOf: fileURL)
|
||||
print(privkey)
|
||||
print(fileURL)
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
@@ -119,7 +120,10 @@ struct ConnectionView: View {
|
||||
}
|
||||
|
||||
NavigationLink() {
|
||||
TerminalView(handler: handler)
|
||||
Button("Reload") {
|
||||
handler.readFromChannel()
|
||||
}
|
||||
TerminalController(handler: handler)
|
||||
} label: {
|
||||
Label("Open Terminal", systemImage: "apple.terminal")
|
||||
}
|
||||
|
||||
28
ShhShell/Views/Terminal/TerminalController.swift
Normal file
28
ShhShell/Views/Terminal/TerminalController.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// TerminalController.swift
|
||||
// ShhShell
|
||||
//
|
||||
// Created by neon443 on 21/06/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import SwiftTerm
|
||||
|
||||
struct TerminalController: UIViewRepresentable {
|
||||
@ObservedObject var handler: SSHHandler
|
||||
|
||||
func makeUIView(context: Context) -> TerminalView {
|
||||
let tv = TerminalView()
|
||||
let terminalDelegate = ShhTerminalViewDelegate()
|
||||
tv.terminalDelegate = terminalDelegate
|
||||
|
||||
tv.getTerminal().feed(text: handler.readFromChannel())
|
||||
return tv
|
||||
}
|
||||
|
||||
func updateUIView(_ tv: TerminalView, context: Context) {
|
||||
tv.getTerminal().feed(text: handler.readFromChannel())
|
||||
}
|
||||
}
|
||||
52
ShhShell/Views/Terminal/TerminalDelegate.swift
Normal file
52
ShhShell/Views/Terminal/TerminalDelegate.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// TerminalDelegate.swift
|
||||
// ShhShell
|
||||
//
|
||||
// Created by neon443 on 21/06/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftTerm
|
||||
|
||||
class ShhTerminalViewDelegate: TerminalViewDelegate {
|
||||
func sizeChanged(source: TerminalView, newCols: Int, newRows: Int) {
|
||||
print(newRows, newCols)
|
||||
}
|
||||
|
||||
func setTerminalTitle(source: TerminalView, title: String) {
|
||||
print(title)
|
||||
}
|
||||
|
||||
func hostCurrentDirectoryUpdate(source: TerminalView, directory: String?) {
|
||||
print(directory)
|
||||
}
|
||||
|
||||
func send(source: TerminalView, data: ArraySlice<UInt8>) {
|
||||
print(data)
|
||||
}
|
||||
|
||||
func scrolled(source: TerminalView, position: Double) {
|
||||
print(position)
|
||||
}
|
||||
|
||||
func requestOpenLink(source: TerminalView, link: String, params: [String : String]) {
|
||||
print(link)
|
||||
print(params)
|
||||
}
|
||||
|
||||
func bell(source: TerminalView) {
|
||||
print("ding")
|
||||
}
|
||||
|
||||
func clipboardCopy(source: TerminalView, content: Data) {
|
||||
print(content)
|
||||
}
|
||||
|
||||
func iTermContent(source: TerminalView, content: ArraySlice<UInt8>) {
|
||||
print("idk what this does")
|
||||
}
|
||||
|
||||
func rangeChanged(source: TerminalView, startY: Int, endY: Int) {
|
||||
print(startY, endY)
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
//
|
||||
// TerminalView.swift
|
||||
// ShhShell
|
||||
//
|
||||
// Created by neon443 on 09/06/2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Runestone
|
||||
|
||||
struct TerminalView: View {
|
||||
@ObservedObject var handler: SSHHandler
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
var body: some View {
|
||||
Button("write") {
|
||||
handler.writeToChannel("top\n")
|
||||
}
|
||||
TextViewController(handler: handler)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("reload") {
|
||||
handler.readFromChannel()
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button() {
|
||||
handler.disconnect()
|
||||
withAnimation { handler.testSuceeded = false }
|
||||
withAnimation { handler.connected = false }
|
||||
dismiss()
|
||||
} label: {
|
||||
Label("Exit", systemImage: "xmark.square.fill")
|
||||
}
|
||||
.disabled(!handler.connected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
TerminalView(handler: SSHHandler(host: Host.debug))
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
//
|
||||
// TextViewController.swift
|
||||
// ShhShell
|
||||
//
|
||||
// Created by neon443 on 09/06/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import Runestone
|
||||
import TreeSitterBashRunestone
|
||||
|
||||
struct TextViewController: UIViewRepresentable {
|
||||
@ObservedObject var handler: SSHHandler
|
||||
|
||||
func makeUIView(context: Context) -> TextView {
|
||||
let languageMode = TreeSitterLanguageMode(language: .bash)
|
||||
let textView = TextView()
|
||||
setTextViewState(on: textView)
|
||||
|
||||
var editorDelegate = textView.editorDelegate
|
||||
editorDelegate = TerminalViewDelegate(handler: handler)
|
||||
textView.editorDelegate = editorDelegate
|
||||
|
||||
textView.translatesAutoresizingMaskIntoConstraints = false
|
||||
textView.backgroundColor = .systemBackground
|
||||
return textView
|
||||
}
|
||||
|
||||
func updateUIView(_ textView: TextView, context: Context) {
|
||||
textView.text = handler.terminal
|
||||
}
|
||||
|
||||
private func setTextViewState(on textView: TextView) {
|
||||
let text = handler.terminal
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
let state = TextViewState(text: text, language: .bash)
|
||||
DispatchQueue.main.async {
|
||||
textView.setState(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TerminalViewDelegate: TextViewDelegate {
|
||||
@ObservedObject var handler: SSHHandler
|
||||
|
||||
init(handler: SSHHandler) {
|
||||
self.handler = handler
|
||||
}
|
||||
|
||||
func textViewDidChangeGutterWidth(_ textView: TextView) {
|
||||
print(textView.gutterWidth)
|
||||
}
|
||||
|
||||
func textViewDidChange(_ textView: TextView) {
|
||||
handler.writeToChannel(textView.text)
|
||||
}
|
||||
|
||||
func textView(_ textView: TextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
print(range)
|
||||
print(text)
|
||||
return true
|
||||
}
|
||||
|
||||
func textViewShouldBeginEditing(_ textView: TextView) -> Bool {
|
||||
print("can edit")
|
||||
return true
|
||||
}
|
||||
|
||||
func textView(_ textView: TextView, shouldInsert characterPair: any CharacterPair, in range: NSRange) -> Bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user