Private
Public Access
1
0

Adds keychain support

This commit is contained in:
2025-08-29 15:12:54 -06:00
parent 402b5a5f80
commit 5da92a90d4
3 changed files with 69 additions and 1 deletions

View File

@@ -6,6 +6,10 @@
objectVersion = 77; objectVersion = 77;
objects = { objects = {
/* Begin PBXBuildFile section */
CD41F5D32E62431D00E0027B /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = CD41F5D22E62431D00E0027B /* KeychainAccess */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
CD41F5972E5B8E7300E0027B /* kordophone2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = kordophone2.app; sourceTree = BUILT_PRODUCTS_DIR; }; CD41F5972E5B8E7300E0027B /* kordophone2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = kordophone2.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@@ -23,6 +27,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
CD41F5D32E62431D00E0027B /* KeychainAccess in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -65,6 +70,7 @@
); );
name = kordophone2; name = kordophone2;
packageProductDependencies = ( packageProductDependencies = (
CD41F5D22E62431D00E0027B /* KeychainAccess */,
); );
productName = kordophone2; productName = kordophone2;
productReference = CD41F5972E5B8E7300E0027B /* kordophone2.app */; productReference = CD41F5972E5B8E7300E0027B /* kordophone2.app */;
@@ -94,6 +100,9 @@
); );
mainGroup = CD41F58E2E5B8E7300E0027B; mainGroup = CD41F58E2E5B8E7300E0027B;
minimizedProjectReferenceProxies = 1; minimizedProjectReferenceProxies = 1;
packageReferences = (
CD41F5D12E62431D00E0027B /* XCRemoteSwiftPackageReference "KeychainAccess" */,
);
preferredProjectObjectVersion = 77; preferredProjectObjectVersion = 77;
productRefGroup = CD41F5982E5B8E7300E0027B /* Products */; productRefGroup = CD41F5982E5B8E7300E0027B /* Products */;
projectDirPath = ""; projectDirPath = "";
@@ -321,6 +330,25 @@
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
CD41F5D12E62431D00E0027B /* XCRemoteSwiftPackageReference "KeychainAccess" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git";
requirement = {
branch = master;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
CD41F5D22E62431D00E0027B /* KeychainAccess */ = {
isa = XCSwiftPackageProductDependency;
package = CD41F5D12E62431D00E0027B /* XCRemoteSwiftPackageReference "KeychainAccess" */;
productName = KeychainAccess;
};
/* End XCSwiftPackageProductDependency section */
}; };
rootObject = CD41F58F2E5B8E7300E0027B /* Project object */; rootObject = CD41F58F2E5B8E7300E0027B /* Project object */;
} }

View File

@@ -5,6 +5,7 @@
// Created by James Magahern on 8/24/25. // Created by James Magahern on 8/24/25.
// //
import KeychainAccess
import SwiftUI import SwiftUI
struct PreferencesView: View struct PreferencesView: View
@@ -56,6 +57,7 @@ struct AccountSettings: View
var password: String var password: String
private let xpc = XPCClient() private let xpc = XPCClient()
private let keychain = Keychain(service: "net.buzzert.kordophonecd")
init(serverURL: String = "", username: String = "", password: String = "") { init(serverURL: String = "", username: String = "", password: String = "") {
self.serverURL = serverURL self.serverURL = serverURL
@@ -70,6 +72,7 @@ struct AccountSettings: View
let settings = try await xpc.getSettings() let settings = try await xpc.getSettings()
self.serverURL = settings.serverUrl self.serverURL = settings.serverUrl
self.username = settings.username self.username = settings.username
self.password = keychain[settings.username] ?? ""
} catch { } catch {
print("Error getting settings: \(error)") print("Error getting settings: \(error)")
} }
@@ -93,6 +96,8 @@ struct AccountSettings: View
username: username username: username
)) ))
} }
keychain[username] = password
} catch { } catch {
print("Error saving settings: \(error)") print("Error saving settings: \(error)")
} }

View File

@@ -71,16 +71,51 @@ struct ImageItemView: View
@State private var img: NSImage? @State private var img: NSImage?
@Environment(\.xpcClient) var xpcClient @Environment(\.xpcClient) var xpcClient
@State private var containerWidth: CGFloat? = nil
var aspectRatio: CGFloat {
if let size = attachment.size, size.height > 0 {
return size.width / size.height
} else {
return 1.0
}
}
var preferredSize: CGSize {
return CGSize(
width: preferredWidth,
height: preferredWidth / aspectRatio
)
}
var preferredWidth: CGFloat {
if let containerWidth, let attachmentWidth = attachment.size?.width {
return CGFloat.minimum(containerWidth, attachmentWidth)
} else if let containerWidth {
return containerWidth
} else {
return 200.0 // fallback
}
}
var body: some View { var body: some View {
BubbleView(isFromMe: isFromMe) { BubbleView(isFromMe: isFromMe) {
if let img { if let img {
Image(nsImage: img) Image(nsImage: img)
.resizable() .resizable()
.scaledToFit() .scaledToFit()
.frame(
maxWidth: containerWidth
)
} else { } else {
ProgressView() Rectangle()
.fill(.gray)
} }
} }
.onGeometryChange(for: CGFloat.self,
of: { $0.size.width },
action: { containerWidth = $0 })
.task { .task {
do { do {
let handle = try await xpcClient.openAttachmentFileHandle( let handle = try await xpcClient.openAttachmentFileHandle(