mirror of
https://github.com/khairul169/vaulterm.git
synced 2025-04-28 16:49:39 +07:00
153 lines
4.1 KiB
TypeScript
153 lines
4.1 KiB
TypeScript
import React, { ComponentPropsWithoutRef } from "react";
|
|
import XTermJs, { XTermRef } from "./xtermjs";
|
|
import Ionicons from "@expo/vector-icons/Ionicons";
|
|
import {
|
|
Pressable,
|
|
ScrollView,
|
|
StyleProp,
|
|
StyleSheet,
|
|
Text,
|
|
TextStyle,
|
|
View,
|
|
} from "react-native";
|
|
|
|
const Keys = {
|
|
ArrowLeft: "\x1b[D",
|
|
ArrowRight: "\x1b[C",
|
|
ArrowUp: "\x1b[A",
|
|
ArrowDown: "\x1b[B",
|
|
Enter: "\x0D",
|
|
Escape: "\x1b",
|
|
Home: "\x1b[H",
|
|
End: "\x1b[F",
|
|
PageUp: "\x1b[5~",
|
|
PageDown: "\x1b[6~",
|
|
Alt: "\x1b",
|
|
Tab: "\x09",
|
|
};
|
|
|
|
type XTermJsProps = {
|
|
client?: "xtermjs";
|
|
url: string;
|
|
};
|
|
|
|
type TerminalProps = ComponentPropsWithoutRef<typeof View> & XTermJsProps;
|
|
|
|
const Terminal = ({ client = "xtermjs", style, ...props }: TerminalProps) => {
|
|
const xtermRef = React.useRef<XTermRef>(null);
|
|
|
|
const send = (data: string) => {
|
|
switch (client) {
|
|
case "xtermjs":
|
|
xtermRef.current?.send(data);
|
|
break;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<View style={[styles.container, style]} {...props}>
|
|
{client === "xtermjs" && (
|
|
<XTermJs
|
|
ref={xtermRef}
|
|
dom={{ scrollEnabled: false }}
|
|
wsUrl={props.url}
|
|
/>
|
|
)}
|
|
|
|
<ScrollView
|
|
horizontal
|
|
style={{ flexGrow: 0 }}
|
|
contentContainerStyle={styles.buttons}
|
|
>
|
|
<TerminalButton
|
|
title={<Ionicons name="swap-horizontal" color="white" size={16} />}
|
|
onPress={() => send(Keys.Tab)}
|
|
/>
|
|
<TerminalButton title="ESC" onPress={() => send(Keys.Escape)} />
|
|
<TerminalButton
|
|
title={<Ionicons name="home" color="white" size={16} />}
|
|
onPress={() => send(Keys.Home)}
|
|
/>
|
|
<TerminalButton
|
|
title={<Ionicons name="arrow-back" color="white" size={18} />}
|
|
onPress={() => send(Keys.ArrowLeft)}
|
|
/>
|
|
<TerminalButton
|
|
title={<Ionicons name="arrow-up" color="white" size={18} />}
|
|
onPress={() => send(Keys.ArrowUp)}
|
|
/>
|
|
<TerminalButton
|
|
title={<Ionicons name="arrow-down" color="white" size={18} />}
|
|
onPress={() => send(Keys.ArrowDown)}
|
|
/>
|
|
<TerminalButton
|
|
title={<Ionicons name="arrow-forward" color="white" size={18} />}
|
|
onPress={() => send(Keys.ArrowRight)}
|
|
/>
|
|
<TerminalButton title="Enter" onPress={() => send(Keys.Enter)} />
|
|
<TerminalButton title="End" onPress={() => send(Keys.End)} />
|
|
<TerminalButton title="PgUp" onPress={() => send(Keys.PageUp)} />
|
|
<TerminalButton title="PgDn" onPress={() => send(Keys.PageDown)} />
|
|
{/* <TerminalButton title="Alt" onPress={() => send(Keys.Alt)} /> */}
|
|
<TerminalButton title="^C" onPress={() => send("\x03")} />
|
|
<TerminalButton title="^D" onPress={() => send("\x04")} />
|
|
<TerminalButton title="^Q" onPress={() => send("\x11")} />
|
|
<TerminalButton title="^V" onPress={() => send("\x11")} />
|
|
<TerminalButton title="^S" onPress={() => send("\x13")} />
|
|
<TerminalButton title="^W" onPress={() => send("\x18")} />
|
|
<TerminalButton title="^X" onPress={() => send("\x18")} />
|
|
<TerminalButton title="^Z" onPress={() => send("\x1a")} />
|
|
</ScrollView>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const TerminalButton = ({
|
|
title,
|
|
textStyle,
|
|
...props
|
|
}: ComponentPropsWithoutRef<typeof Pressable> & {
|
|
title: string | React.ReactNode;
|
|
textStyle?: StyleProp<TextStyle>;
|
|
}) => (
|
|
<Pressable
|
|
style={({ pressed }) => [styles.btn, pressed && styles.btnPressed]}
|
|
{...props}
|
|
>
|
|
{typeof title === "string" ? (
|
|
<Text style={[styles.btnText, textStyle]}>{title}</Text>
|
|
) : (
|
|
title
|
|
)}
|
|
</Pressable>
|
|
);
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: "#232323",
|
|
},
|
|
buttons: {
|
|
display: "flex",
|
|
flexDirection: "row",
|
|
alignItems: "stretch",
|
|
backgroundColor: "#232323",
|
|
},
|
|
btn: {
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
paddingHorizontal: 14,
|
|
paddingVertical: 10,
|
|
},
|
|
btnPressed: {
|
|
backgroundColor: "#3a3a3a",
|
|
},
|
|
btnText: {
|
|
color: "white",
|
|
fontSize: 16,
|
|
},
|
|
});
|
|
|
|
export default Terminal;
|