RemminaMac 0.1.0: SSH/RDP-Client für macOS (SwiftUI, Remmina-Layout, Profile, SSH-Keys, Docs, Release-Skripte)
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import Foundation
|
||||
|
||||
@MainActor
|
||||
final class ProfileStore: ObservableObject {
|
||||
@Published var profiles: [ConnectionProfile] = []
|
||||
@Published var sshKeys: [StoredSSHKey] = []
|
||||
@Published var searchText: String = ""
|
||||
@Published var selectedGroup: String = "Alle"
|
||||
|
||||
private var profilesURL: URL {
|
||||
let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
|
||||
.appendingPathComponent("RemminaMac", isDirectory: true)
|
||||
try? FileManager.default.createDirectory(at: base, withIntermediateDirectories: true)
|
||||
return base.appendingPathComponent("profiles.json")
|
||||
}
|
||||
|
||||
private var keysURL: URL {
|
||||
let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
|
||||
.appendingPathComponent("RemminaMac", isDirectory: true)
|
||||
try? FileManager.default.createDirectory(at: base, withIntermediateDirectories: true)
|
||||
return base.appendingPathComponent("sshkeys.json")
|
||||
}
|
||||
|
||||
var groups: [String] {
|
||||
let g = Set(profiles.map { $0.group.isEmpty ? "Allgemein" : $0.group })
|
||||
return ["Alle"] + g.sorted()
|
||||
}
|
||||
|
||||
var filteredProfiles: [ConnectionProfile] {
|
||||
profiles.filter { p in
|
||||
let matchGroup = selectedGroup == "Alle" || p.group == selectedGroup
|
||||
let matchSearch = searchText.isEmpty ||
|
||||
p.name.localizedCaseInsensitiveContains(searchText) ||
|
||||
p.host.localizedCaseInsensitiveContains(searchText) ||
|
||||
p.username.localizedCaseInsensitiveContains(searchText)
|
||||
return matchGroup && matchSearch
|
||||
}.sorted { $0.name.localizedCompare($1.name) == .orderedAscending }
|
||||
}
|
||||
|
||||
func load() {
|
||||
if let data = try? Data(contentsOf: profilesURL),
|
||||
let decoded = try? JSONDecoder().decode([ConnectionProfile].self, from: data) {
|
||||
profiles = decoded
|
||||
}
|
||||
if let data = try? Data(contentsOf: keysURL),
|
||||
let decoded = try? JSONDecoder().decode([StoredSSHKey].self, from: data) {
|
||||
sshKeys = decoded
|
||||
}
|
||||
if profiles.isEmpty {
|
||||
profiles = Self.sampleProfiles
|
||||
}
|
||||
}
|
||||
|
||||
func save() {
|
||||
if let data = try? JSONEncoder().encode(profiles) {
|
||||
try? data.write(to: profilesURL)
|
||||
}
|
||||
if let data = try? JSONEncoder().encode(sshKeys) {
|
||||
try? data.write(to: keysURL)
|
||||
}
|
||||
}
|
||||
|
||||
func add(_ profile: ConnectionProfile) {
|
||||
profiles.append(profile)
|
||||
save()
|
||||
}
|
||||
|
||||
func update(_ profile: ConnectionProfile) {
|
||||
if let i = profiles.firstIndex(where: { $0.id == profile.id }) {
|
||||
profiles[i] = profile
|
||||
save()
|
||||
}
|
||||
}
|
||||
|
||||
func delete(_ profile: ConnectionProfile) {
|
||||
profiles.removeAll { $0.id == profile.id }
|
||||
save()
|
||||
}
|
||||
|
||||
func duplicate(_ profile: ConnectionProfile) {
|
||||
var copy = profile
|
||||
copy.id = UUID()
|
||||
copy.name += " (Kopie)"
|
||||
copy.passwordAccount = nil
|
||||
add(copy)
|
||||
}
|
||||
|
||||
func key(for profile: ConnectionProfile) -> StoredSSHKey? {
|
||||
guard let id = profile.sshKeyID else { return nil }
|
||||
return sshKeys.first { $0.id == id }
|
||||
}
|
||||
|
||||
static var sampleProfiles: [ConnectionProfile] {
|
||||
[
|
||||
ConnectionProfile(name: "Webserver", proto: .ssh, host: "192.168.1.10", port: 22, username: "admin", group: "Server"),
|
||||
ConnectionProfile(name: "Büro-PC", proto: .rdp, host: "192.168.1.50", port: 3389, username: "user", group: "Windows"),
|
||||
ConnectionProfile(name: "Dateiserver", proto: .sftp, host: "nas.local", port: 22, username: "nas", group: "Server")
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user