mirror of
https://github.com/EthanShoeDev/fressh.git
synced 2026-01-11 14:22:51 +00:00
fix some issues
This commit is contained in:
@@ -348,23 +348,29 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
card: {
|
||||
backgroundColor: '#111B34',
|
||||
borderRadius: 16,
|
||||
padding: 20,
|
||||
borderRadius: 20,
|
||||
padding: 24,
|
||||
marginHorizontal: 4,
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 12,
|
||||
elevation: 6,
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 16,
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
elevation: 8,
|
||||
borderWidth: 1,
|
||||
borderColor: '#1E293B',
|
||||
},
|
||||
title: {
|
||||
fontSize: 22,
|
||||
fontSize: 24,
|
||||
fontWeight: '700',
|
||||
color: '#E5E7EB',
|
||||
marginBottom: 4,
|
||||
marginBottom: 6,
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
color: '#9AA0A6',
|
||||
marginBottom: 16,
|
||||
marginBottom: 24,
|
||||
lineHeight: 20,
|
||||
},
|
||||
inputGroup: {
|
||||
marginBottom: 12,
|
||||
@@ -391,7 +397,7 @@ const styles = StyleSheet.create({
|
||||
fontSize: 12,
|
||||
},
|
||||
actions: {
|
||||
marginTop: 8,
|
||||
marginTop: 20,
|
||||
},
|
||||
mutedText: {
|
||||
color: '#9AA0A6',
|
||||
@@ -399,14 +405,20 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
submitButton: {
|
||||
backgroundColor: '#2563EB',
|
||||
borderRadius: 10,
|
||||
paddingVertical: 14,
|
||||
borderRadius: 12,
|
||||
paddingVertical: 16,
|
||||
alignItems: 'center',
|
||||
shadowColor: '#2563EB',
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 8,
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
elevation: 4,
|
||||
},
|
||||
submitButtonText: {
|
||||
color: '#FFFFFF',
|
||||
fontWeight: '700',
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
buttonDisabled: {
|
||||
backgroundColor: '#3B82F6',
|
||||
@@ -416,15 +428,16 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 1,
|
||||
borderColor: '#2A3655',
|
||||
borderRadius: 10,
|
||||
paddingVertical: 12,
|
||||
borderRadius: 12,
|
||||
paddingVertical: 14,
|
||||
alignItems: 'center',
|
||||
marginTop: 8,
|
||||
marginTop: 12,
|
||||
},
|
||||
secondaryButtonText: {
|
||||
color: '#C6CBD3',
|
||||
fontWeight: '600',
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.3,
|
||||
},
|
||||
listSection: {
|
||||
marginTop: 20,
|
||||
|
||||
@@ -108,13 +108,16 @@ export function PickerField<T>(
|
||||
return (
|
||||
<View style={styles.inputGroup}>
|
||||
{label ? <Text style={styles.label}>{label}</Text> : null}
|
||||
<View style={[styles.input, styles.pickerContainer]}>
|
||||
<Picker<T>
|
||||
style={styles.picker}
|
||||
selectedValue={field.state.value}
|
||||
onValueChange={(itemValue) => field.handleChange(itemValue)}
|
||||
{...rest}
|
||||
>
|
||||
{props.children}
|
||||
</Picker>
|
||||
</View>
|
||||
<FieldInfo />
|
||||
</View>
|
||||
);
|
||||
@@ -171,7 +174,7 @@ export const { useAppForm, withForm, withFieldGroup } = createFormHook({
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
inputGroup: {
|
||||
marginBottom: 12,
|
||||
marginBottom: 16,
|
||||
},
|
||||
label: {
|
||||
marginBottom: 6,
|
||||
@@ -214,4 +217,11 @@ const styles = StyleSheet.create({
|
||||
color: '#FCA5A5',
|
||||
fontSize: 12,
|
||||
},
|
||||
pickerContainer: {
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 4,
|
||||
},
|
||||
picker: {
|
||||
color: '#E5E7EB',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import { queryClient } from './utils';
|
||||
const keys = {
|
||||
storagePrefix: 'privateKey_',
|
||||
manifestKey: 'privateKeysManifest',
|
||||
chunkSize: 1800, // Safely under 2048 byte limit
|
||||
} as const;
|
||||
|
||||
const keyManifestSchema = z.object({
|
||||
@@ -15,7 +16,8 @@ const keyManifestSchema = z.object({
|
||||
z.object({
|
||||
id: z.string(),
|
||||
priority: z.number(),
|
||||
createdAt: z.date(),
|
||||
createdAtMs: z.int(),
|
||||
chunkCount: z.number().default(1),
|
||||
}),
|
||||
),
|
||||
});
|
||||
@@ -31,6 +33,19 @@ async function getKeyManifest() {
|
||||
return keyManifestSchema.parse(manifest);
|
||||
}
|
||||
|
||||
// Utility functions for chunking large data
|
||||
function splitIntoChunks(data: string, chunkSize: number): string[] {
|
||||
const chunks: string[] = [];
|
||||
for (let i = 0; i < data.length; i += chunkSize) {
|
||||
chunks.push(data.substring(i, i + chunkSize));
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
function getChunkKey(keyId: string, chunkIndex: number): string {
|
||||
return `${keys.storagePrefix}${keyId}_chunk_${chunkIndex}`;
|
||||
}
|
||||
|
||||
async function savePrivateKey(params: {
|
||||
keyId: string;
|
||||
privateKey: string;
|
||||
@@ -42,17 +57,24 @@ async function savePrivateKey(params: {
|
||||
|
||||
if (existingKey) throw new Error('Key already exists');
|
||||
|
||||
// Split the private key into chunks if it's too large
|
||||
const chunks = splitIntoChunks(params.privateKey, keys.chunkSize);
|
||||
const chunkCount = chunks.length;
|
||||
|
||||
const newKey = {
|
||||
id: params.keyId,
|
||||
priority: params.priority,
|
||||
createdAt: new Date(),
|
||||
createdAtMs: Date.now(),
|
||||
chunkCount,
|
||||
};
|
||||
|
||||
manifest.keys.push(newKey);
|
||||
await SecureStore.setItemAsync(
|
||||
`${keys.storagePrefix}${params.keyId}`,
|
||||
params.privateKey,
|
||||
);
|
||||
|
||||
// Save each chunk separately
|
||||
for (let i = 0; i < chunks.length; i++) {
|
||||
await SecureStore.setItemAsync(getChunkKey(params.keyId, i), chunks[i]!);
|
||||
}
|
||||
|
||||
await SecureStore.setItemAsync(keys.manifestKey, JSON.stringify(manifest));
|
||||
await queryClient.invalidateQueries({ queryKey: [keyQueryKey] });
|
||||
}
|
||||
@@ -61,10 +83,16 @@ async function getPrivateKey(keyId: string) {
|
||||
const manifest = await getKeyManifest();
|
||||
const key = manifest.keys.find((key) => key.id === keyId);
|
||||
if (!key) throw new Error('Key not found');
|
||||
const privateKey = await SecureStore.getItemAsync(
|
||||
`${keys.storagePrefix}${keyId}`,
|
||||
);
|
||||
if (!privateKey) throw new Error('Key not found');
|
||||
|
||||
// Reassemble the private key from chunks
|
||||
const chunks: string[] = [];
|
||||
for (let i = 0; i < key.chunkCount; i++) {
|
||||
const chunk = await SecureStore.getItemAsync(getChunkKey(keyId, i));
|
||||
if (!chunk) throw new Error(`Key chunk ${i} not found`);
|
||||
chunks.push(chunk);
|
||||
}
|
||||
|
||||
const privateKey = chunks.join('');
|
||||
return {
|
||||
...key,
|
||||
privateKey,
|
||||
@@ -75,9 +103,15 @@ async function deletePrivateKey(keyId: string) {
|
||||
const manifest = await getKeyManifest();
|
||||
const key = manifest.keys.find((key) => key.id === keyId);
|
||||
if (!key) throw new Error('Key not found');
|
||||
|
||||
manifest.keys = manifest.keys.filter((key) => key.id !== keyId);
|
||||
|
||||
// Delete all chunks for this key
|
||||
for (let i = 0; i < key.chunkCount; i++) {
|
||||
await SecureStore.deleteItemAsync(getChunkKey(keyId, i));
|
||||
}
|
||||
|
||||
await SecureStore.setItemAsync(keys.manifestKey, JSON.stringify(manifest));
|
||||
await SecureStore.deleteItemAsync(`${keys.storagePrefix}${keyId}`);
|
||||
await queryClient.invalidateQueries({ queryKey: [keyQueryKey] });
|
||||
}
|
||||
|
||||
@@ -235,9 +269,9 @@ async function generateKeyPair(params: {
|
||||
}) {
|
||||
const keyPair = await SSHClient.generateKeyPair(
|
||||
params.type,
|
||||
params.passphrase,
|
||||
params.passphrase ?? '',
|
||||
params.keySize,
|
||||
params.comment,
|
||||
params.comment ?? '',
|
||||
);
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user