feat: update ui, test release mode

This commit is contained in:
Khairul Hidayat 2024-11-09 03:38:27 +07:00
parent 334d90e691
commit 31c43836f4
8 changed files with 82 additions and 13 deletions

2
frontend/.gitignore vendored
View File

@ -20,3 +20,5 @@ expo-env.d.ts
# @end expo-cli # @end expo-cli
.env* .env*
!.env.example !.env.example
*.apk
*.aab

View File

@ -2,12 +2,12 @@ import { ExpoConfig, ConfigContext } from "expo/config";
export default ({ config }: ConfigContext): ExpoConfig => ({ export default ({ config }: ConfigContext): ExpoConfig => ({
...config, ...config,
name: "frontend", name: "Vaulterm",
slug: "frontend", slug: "vaulterm",
version: "1.0.0", version: "1.0.0",
orientation: "portrait", orientation: "portrait",
icon: "./assets/images/icon.png", icon: "./assets/images/icon.png",
scheme: "myapp", scheme: "vaulterm",
userInterfaceStyle: "automatic", userInterfaceStyle: "automatic",
newArchEnabled: true, newArchEnabled: true,
splash: { splash: {
@ -19,6 +19,7 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
supportsTablet: true, supportsTablet: true,
}, },
android: { android: {
package: "sh.rul.vaulterm",
adaptiveIcon: { adaptiveIcon: {
foregroundImage: "./assets/images/adaptive-icon.png", foregroundImage: "./assets/images/adaptive-icon.png",
backgroundColor: "#ffffff", backgroundColor: "#ffffff",
@ -33,4 +34,10 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
experiments: { experiments: {
typedRoutes: true, typedRoutes: true,
}, },
owner: "khairul169",
extra: {
eas: {
projectId: "3e0112c1-f0ed-423c-b5cf-95633f23f6dc",
},
},
}); });

View File

@ -18,7 +18,7 @@ export default function Layout() {
<Drawer.Screen name="hosts" options={{ title: "Hosts" }} /> <Drawer.Screen name="hosts" options={{ title: "Hosts" }} />
<Drawer.Screen <Drawer.Screen
name="terminal" name="terminal"
options={{ title: "Terminal", headerShown: true }} options={{ title: "Terminal", headerShown: media.sm }}
/> />
</Drawer> </Drawer>
</GestureHandlerRootView> </GestureHandlerRootView>

View File

@ -4,6 +4,7 @@ import Ionicons from "@expo/vector-icons/Ionicons";
import { ScrollView, Text, TextStyle, View } from "tamagui"; import { ScrollView, Text, TextStyle, View } from "tamagui";
import Pressable from "../ui/pressable"; import Pressable from "../ui/pressable";
import Icons from "../ui/icons"; import Icons from "../ui/icons";
import useThemeStore from "@/stores/theme";
const Keys = { const Keys = {
ArrowLeft: "\x1b[D", ArrowLeft: "\x1b[D",
@ -29,6 +30,7 @@ type TerminalProps = ComponentPropsWithoutRef<typeof View> & XTermJsProps;
const Terminal = ({ client = "xtermjs", style, ...props }: TerminalProps) => { const Terminal = ({ client = "xtermjs", style, ...props }: TerminalProps) => {
const xtermRef = React.useRef<XTermRef>(null); const xtermRef = React.useRef<XTermRef>(null);
const theme = useThemeStore((i) => i.theme);
const send = (data: string) => { const send = (data: string) => {
switch (client) { switch (client) {
@ -45,6 +47,7 @@ const Terminal = ({ client = "xtermjs", style, ...props }: TerminalProps) => {
ref={xtermRef} ref={xtermRef}
dom={{ scrollEnabled: false }} dom={{ scrollEnabled: false }}
wsUrl={props.url} wsUrl={props.url}
colorScheme={theme}
/> />
)} )}

View File

@ -18,10 +18,11 @@ type XTermJsProps = {
dom?: DOMProps; dom?: DOMProps;
style?: CSSProperties; style?: CSSProperties;
wsUrl: string; wsUrl: string;
colorScheme?: "light" | "dark";
}; };
// vscode-snazzy https://github.com/Tyriar/vscode-snazzy // vscode-snazzy https://github.com/Tyriar/vscode-snazzy
const snazzyTheme = { const darkTheme = {
foreground: "#eff0eb", foreground: "#eff0eb",
background: "#282a36", background: "#282a36",
selection: "#97979b33", selection: "#97979b33",
@ -43,6 +44,28 @@ const snazzyTheme = {
brightWhite: "#eff0eb", brightWhite: "#eff0eb",
}; };
const lightTheme = {
foreground: "#282a36",
background: "#e5f2ff",
selection: "#97979b33",
black: "#eff0eb",
brightBlack: "#686868",
red: "#d32f2f",
brightRed: "#ff5c57",
green: "#388e3c",
brightGreen: "#5af78e",
yellow: "#fbc02d",
brightYellow: "#f3f99d",
blue: "#1976d2",
brightBlue: "#57c7ff",
magenta: "#ab47bc",
brightMagenta: "#ff6ac1",
cyan: "#00acc1",
brightCyan: "#9aedfe",
white: "#282a36",
brightWhite: "#686868",
};
export interface XTermRef extends DOMImperativeFactory { export interface XTermRef extends DOMImperativeFactory {
send: (...args: JSONValue[]) => void; send: (...args: JSONValue[]) => void;
} }
@ -50,7 +73,9 @@ export interface XTermRef extends DOMImperativeFactory {
const XTermJs = forwardRef<XTermRef, XTermJsProps>((props, ref) => { const XTermJs = forwardRef<XTermRef, XTermJsProps>((props, ref) => {
const containerRef = useRef<HTMLDivElement | null>(null); const containerRef = useRef<HTMLDivElement | null>(null);
const wsRef = useRef<WebSocket | null>(null); const wsRef = useRef<WebSocket | null>(null);
const { wsUrl, onLoad, style = {} } = props; const xtermRef = useRef<XTerm | null>(null);
const { wsUrl, onLoad, style = {}, colorScheme } = props;
const theme = colorScheme === "dark" ? darkTheme : lightTheme;
useEffect(() => { useEffect(() => {
const container = containerRef.current; const container = containerRef.current;
@ -60,10 +85,11 @@ const XTermJs = forwardRef<XTermRef, XTermJsProps>((props, ref) => {
const xterm = new XTerm({ const xterm = new XTerm({
fontFamily: '"Cascadia Code", Menlo, monospace', fontFamily: '"Cascadia Code", Menlo, monospace',
theme: snazzyTheme, theme: theme,
cursorBlink: true, cursorBlink: true,
}); });
xterm.open(container); xterm.open(container);
xtermRef.current = xterm;
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
xterm.loadAddon(fitAddon); xterm.loadAddon(fitAddon);
@ -101,8 +127,6 @@ const XTermJs = forwardRef<XTermRef, XTermJsProps>((props, ref) => {
} }
function onClose(e: CloseEvent) { function onClose(e: CloseEvent) {
console.log("WS Closed", e.reason, e.code);
// Check if the close event was abnormal // Check if the close event was abnormal
if (!e.wasClean) { if (!e.wasClean) {
const reason = e.reason || `Code: ${e.code}`; const reason = e.reason || `Code: ${e.code}`;
@ -129,6 +153,7 @@ const XTermJs = forwardRef<XTermRef, XTermJsProps>((props, ref) => {
return () => { return () => {
xterm.dispose(); xterm.dispose();
xtermRef.current = null;
wsRef.current = null; wsRef.current = null;
containerRef.current = null; containerRef.current = null;
@ -154,11 +179,17 @@ const XTermJs = forwardRef<XTermRef, XTermJsProps>((props, ref) => {
[] []
); );
useEffect(() => {
if (xtermRef.current) {
xtermRef.current.options.theme = theme;
}
}, [theme]);
return ( return (
<div <div
ref={containerRef} ref={containerRef}
style={{ style={{
background: snazzyTheme.background, background: theme.background,
padding: 12, padding: 12,
flex: !IS_DOM ? 1 : undefined, flex: !IS_DOM ? 1 : undefined,
width: "100%", width: "100%",

View File

@ -19,13 +19,13 @@ const PagerView = ({
const [onPageSelect, clearPageSelectDebounce] = useDebounceCallback( const [onPageSelect, clearPageSelectDebounce] = useDebounceCallback(
(page) => onChangePage?.(page), (page) => onChangePage?.(page),
100 300
); );
const [setPage] = useDebounceCallback((page) => { const [setPage] = useDebounceCallback((page) => {
ref.current?.setPage(page); ref.current?.setPage(page);
clearPageSelectDebounce(); clearPageSelectDebounce();
}, 300); }, 100);
useEffect(() => { useEffect(() => {
if (page != null) { if (page != null) {

24
frontend/eas.json Normal file
View File

@ -0,0 +1,24 @@
{
"cli": {
"version": ">= 10.2.2"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal",
"android": {
"buildType": "apk"
},
"env": {
"EXPO_PUBLIC_API_URL": "https://vaulterm-dev.rul.sh"
}
},
"production": {}
},
"submit": {
"production": {}
}
}

View File

@ -10,7 +10,9 @@
"ios": "expo start --ios", "ios": "expo start --ios",
"web": "expo start --web", "web": "expo start --web",
"test": "jest --watchAll", "test": "jest --watchAll",
"lint": "expo lint" "lint": "expo lint",
"build:preview": "eas build -p android --profile preview --local",
"build:android": "eas build -p android --local"
}, },
"jest": { "jest": {
"preset": "jest-expo" "preset": "jest-expo"