mirror of
https://github.com/EthanShoeDev/fressh.git
synced 2026-01-11 06:12:51 +00:00
rust changes
This commit is contained in:
@@ -29,7 +29,10 @@ export default function TabsShellDetail() {
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
startTransition(() => {
|
||||
setReady(true);
|
||||
setTimeout(() => {
|
||||
// TODO: This is gross
|
||||
setReady(true);
|
||||
}, 50);
|
||||
}); // React 19: non-urgent
|
||||
|
||||
return () => {
|
||||
@@ -78,6 +81,7 @@ function ShellDetail() {
|
||||
useEffect(() => {
|
||||
if (!sess) return;
|
||||
if (sess.status === 'disconnected') {
|
||||
console.log('shell disconnected, replacing route with /shell');
|
||||
// Replace so the detail screen isn't on the stack anymore
|
||||
router.replace('/shell');
|
||||
}
|
||||
@@ -119,6 +123,7 @@ function ShellDetail() {
|
||||
}}
|
||||
style={{
|
||||
flex: 1,
|
||||
justifyContent: 'flex-start',
|
||||
backgroundColor: theme.colors.background,
|
||||
padding: 0,
|
||||
paddingBottom:
|
||||
@@ -142,7 +147,6 @@ function ShellDetail() {
|
||||
} catch (e) {
|
||||
console.warn('Failed to disconnect', e);
|
||||
}
|
||||
router.replace('/shell');
|
||||
}}
|
||||
>
|
||||
<Ionicons name="power" size={20} color={theme.colors.primary} />
|
||||
@@ -162,7 +166,7 @@ function ShellDetail() {
|
||||
// xterm options
|
||||
xtermOptions={{
|
||||
theme: {
|
||||
background: theme.colors.background,
|
||||
background: 'red',
|
||||
foreground: theme.colors.textPrimary,
|
||||
},
|
||||
}}
|
||||
|
||||
@@ -1,86 +1,125 @@
|
||||
import {
|
||||
RnRussh,
|
||||
type SshConnection,
|
||||
type SshShell,
|
||||
type SshConnectionStatus,
|
||||
} from '@fressh/react-native-uniffi-russh';
|
||||
import { create } from 'zustand';
|
||||
|
||||
export type SessionKey = string;
|
||||
export const makeSessionKey = (connectionId: string, channelId: number) =>
|
||||
`${connectionId}:${channelId}` as const;
|
||||
// export type SessionKey = string;
|
||||
// export const makeSessionKey = (connectionId: string, channelId: number) =>
|
||||
// `${connectionId}:${channelId}` as const;
|
||||
|
||||
export type SessionStatus = 'connecting' | 'connected' | 'disconnected';
|
||||
// export type SessionStatus = 'connecting' | 'connected' | 'disconnected';
|
||||
|
||||
export interface StoredSession {
|
||||
connection: SshConnection;
|
||||
shell: SshShell;
|
||||
status: SessionStatus;
|
||||
// export interface StoredSession {
|
||||
// connection: SshConnection;
|
||||
// shell: SshShell;
|
||||
// status: SessionStatus;
|
||||
// }
|
||||
|
||||
// interface SshStoreState {
|
||||
// sessions: Record<SessionKey, StoredSession>;
|
||||
// addSession: (conn: SshConnection, shell: SshShell) => SessionKey;
|
||||
// removeSession: (key: SessionKey) => void;
|
||||
// setStatus: (key: SessionKey, status: SessionStatus) => void;
|
||||
// getByKey: (key: SessionKey) => StoredSession | undefined;
|
||||
// listConnectionsWithShells: () => (SshConnection & { shells: SshShell[] })[];
|
||||
// }
|
||||
|
||||
// export const useSshStore = create<SshStoreState>((set, get) => ({
|
||||
// sessions: {},
|
||||
// addSession: (conn, shell) => {
|
||||
// const key = makeSessionKey(conn.connectionId, shell.channelId);
|
||||
// set((s) => ({
|
||||
// sessions: {
|
||||
// ...s.sessions,
|
||||
// [key]: { connection: conn, shell, status: 'connected' },
|
||||
// },
|
||||
// }));
|
||||
// return key;
|
||||
// },
|
||||
// removeSession: (key) => {
|
||||
// set((s) => {
|
||||
// const { [key]: _omit, ...rest } = s.sessions;
|
||||
// return { sessions: rest };
|
||||
// });
|
||||
// },
|
||||
// setStatus: (key, status) => {
|
||||
// set((s) =>
|
||||
// s.sessions[key]
|
||||
// ? { sessions: { ...s.sessions, [key]: { ...s.sessions[key], status } } }
|
||||
// : s,
|
||||
// );
|
||||
// },
|
||||
// getByKey: (key) => get().sessions[key],
|
||||
// listConnectionsWithShells: () => {
|
||||
// const byConn = new Map<
|
||||
// string,
|
||||
// { conn: SshConnection; shells: SshShell[] }
|
||||
// >();
|
||||
// for (const { connection, shell } of Object.values(get().sessions)) {
|
||||
// const g = byConn.get(connection.connectionId) ?? {
|
||||
// conn: connection,
|
||||
// shells: [],
|
||||
// };
|
||||
// g.shells.push(shell);
|
||||
// byConn.set(connection.connectionId, g);
|
||||
// }
|
||||
// return Array.from(byConn.values()).map(({ conn, shells }) => ({
|
||||
// ...conn,
|
||||
// shells,
|
||||
// }));
|
||||
// },
|
||||
// }));
|
||||
|
||||
// export function toSessionStatus(status: SshConnectionStatus): SessionStatus {
|
||||
// switch (status) {
|
||||
// case 'shellConnecting':
|
||||
// return 'connecting';
|
||||
// case 'shellConnected':
|
||||
// return 'connected';
|
||||
// case 'shellDisconnected':
|
||||
// return 'disconnected';
|
||||
// default:
|
||||
// return 'connected';
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
type SshRegistryStore = {
|
||||
connections: Record<string, {
|
||||
connection: SshConnection,
|
||||
shells: Record<number, SshShell>,
|
||||
status:
|
||||
}>,
|
||||
shells: Record<`${string}-${number}`, SshShell>,
|
||||
addConnection: typeof RnRussh.connect,
|
||||
}
|
||||
|
||||
interface SshStoreState {
|
||||
sessions: Record<SessionKey, StoredSession>;
|
||||
addSession: (conn: SshConnection, shell: SshShell) => SessionKey;
|
||||
removeSession: (key: SessionKey) => void;
|
||||
setStatus: (key: SessionKey, status: SessionStatus) => void;
|
||||
getByKey: (key: SessionKey) => StoredSession | undefined;
|
||||
listConnectionsWithShells: () => (SshConnection & { shells: SshShell[] })[];
|
||||
type SshRegistryService = {
|
||||
connect: typeof RnRussh.connect,
|
||||
}
|
||||
|
||||
export const useSshStore = create<SshStoreState>((set, get) => ({
|
||||
sessions: {},
|
||||
addSession: (conn, shell) => {
|
||||
const key = makeSessionKey(conn.connectionId, shell.channelId);
|
||||
set((s) => ({
|
||||
sessions: {
|
||||
...s.sessions,
|
||||
[key]: { connection: conn, shell, status: 'connected' },
|
||||
},
|
||||
}));
|
||||
return key;
|
||||
},
|
||||
removeSession: (key) => {
|
||||
set((s) => {
|
||||
const { [key]: _omit, ...rest } = s.sessions;
|
||||
return { sessions: rest };
|
||||
const useSshRegistryStore = create<SshRegistryStore>((set) => ({
|
||||
connections: {},
|
||||
shells: {},
|
||||
addConnection: async (args) => {
|
||||
const connection = await RnRussh.connect({
|
||||
...args,
|
||||
onStatusChange: (status) => {
|
||||
args.onStatusChange?.(status);
|
||||
if (status === 'tcpDisconnected') {
|
||||
// remove all shell
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
setStatus: (key, status) => {
|
||||
set((s) =>
|
||||
s.sessions[key]
|
||||
? { sessions: { ...s.sessions, [key]: { ...s.sessions[key], status } } }
|
||||
: s,
|
||||
);
|
||||
},
|
||||
getByKey: (key) => get().sessions[key],
|
||||
listConnectionsWithShells: () => {
|
||||
const byConn = new Map<
|
||||
string,
|
||||
{ conn: SshConnection; shells: SshShell[] }
|
||||
>();
|
||||
for (const { connection, shell } of Object.values(get().sessions)) {
|
||||
const g = byConn.get(connection.connectionId) ?? {
|
||||
conn: connection,
|
||||
shells: [],
|
||||
};
|
||||
g.shells.push(shell);
|
||||
byConn.set(connection.connectionId, g);
|
||||
}
|
||||
return Array.from(byConn.values()).map(({ conn, shells }) => ({
|
||||
...conn,
|
||||
shells,
|
||||
}));
|
||||
},
|
||||
}));
|
||||
|
||||
export function toSessionStatus(status: SshConnectionStatus): SessionStatus {
|
||||
switch (status) {
|
||||
case 'shellConnecting':
|
||||
return 'connecting';
|
||||
case 'shellConnected':
|
||||
return 'connected';
|
||||
case 'shellDisconnected':
|
||||
return 'disconnected';
|
||||
default:
|
||||
return 'connected';
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
const sshRegistryService = {
|
||||
connect
|
||||
}
|
||||
Reference in New Issue
Block a user