Compare commits

...

4 Commits

Author SHA1 Message Date
Kevin Yue
4191e9a19f feat: support drag and remove title bar on KDE 2023-06-25 13:46:35 +08:00
Kevin Yue
5bc3da99ac doc: improve doc 2023-06-25 09:32:10 +08:00
Kevin Yue
e8db014336 refactor: refine the error message 2023-06-25 09:30:13 +08:00
Kevin Yue
e5fd2ba280 doc: update the dev doc 2023-06-25 01:26:25 +08:00
12 changed files with 68 additions and 18 deletions

View File

@ -6,6 +6,7 @@
"clientgpversion", "clientgpversion",
"clientos", "clientos",
"gpcommon", "gpcommon",
"gpgui",
"gpservice", "gpservice",
"Immer", "Immer",
"jnlp", "jnlp",

View File

@ -1,9 +1,29 @@
## Development ## Development
### Build the service
```sh
# Build the client first
cargo build -p gpclient
# Build the service
cargo build -p gpservice
```
### Start the service
```sh
sudo ./target/debug/gpservice
```
### Start the GUI ### Start the GUI
``` ```sh
cd gpgui cd gpgui
pnpm install pnpm install
pnpm tauri dev pnpm tauri dev
``` ```
### Open the DevTools
Right-click on the GUI window and select "Inspect Element".

View File

@ -3,10 +3,15 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0" />
<title>Vite + React + TS</title> <title>Vite + React + TS</title>
</head> </head>
<body> <body data-tauri-drag-region>
<script>
var htmlFontSize = getComputedStyle(document.documentElement).fontSize;
var ratio = parseInt(htmlFontSize) / 16;
document.documentElement.style.fontSize = (16 / ratio) + 'px';
</script>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>

View File

@ -44,6 +44,18 @@ fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
}); });
app.manage(client); app.manage(client);
match std::env::var("XDG_CURRENT_DESKTOP") {
Ok(desktop) => {
if desktop == "KDE" {
if let Some(main_window) = app.get_window("main") {
let _ = main_window.set_decorations(false);
}
}
}
Err(_) => (),
}
Ok(()) Ok(())
} }

View File

@ -68,11 +68,13 @@
}, },
"windows": [ "windows": [
{ {
"title": "GlobalProtect",
"label": "main",
"fullscreen": false, "fullscreen": false,
"width": 260,
"height": 360, "height": 360,
"resizable": false, "resizable": false,
"title": "GlobalProtect", "fileDropEnabled": false
"width": 260
} }
] ]
} }

View File

@ -41,7 +41,7 @@ export default function App() {
const ready = useAtomValue(statusReadyAtom); const ready = useAtomValue(statusReadyAtom);
return ( return (
<Box padding={2} paddingBottom={0}> <Box data-tauri-drag-region padding={2} paddingBottom={0}>
{ready ? <MainContent /> : <Loading />} {ready ? <MainContent /> : <Loading />}
<Notification /> <Notification />
</Box> </Box>

View File

@ -93,11 +93,17 @@ function InnerStatusIcon() {
return <DisconnectedIcon />; return <DisconnectedIcon />;
} }
const DragRegion = styled(Box)(({ theme }) => ({
position: "absolute",
inset: 0,
}));
export default function StatusIcon() { export default function StatusIcon() {
return ( return (
<IconContainer> <IconContainer>
<BackgroundIcon /> <BackgroundIcon />
<InnerStatusIcon /> <InnerStatusIcon />
<DragRegion data-tauri-drag-region />
</IconContainer> </IconContainer>
); );
} }

View File

@ -7,6 +7,7 @@ export default function StatusText() {
return ( return (
<Typography <Typography
data-tauri-drag-region
textAlign="center" textAlign="center"
mt={1.5} mt={1.5}
variant="subtitle1" variant="subtitle1"

View File

@ -4,7 +4,7 @@ import StatusText from "./StatusText";
export default function ConnectionStatus() { export default function ConnectionStatus() {
return ( return (
<Box> <Box data-tauri-drag-region>
<StatusIcon /> <StatusIcon />
<StatusText /> <StatusText />
</Box> </Box>

View File

@ -1,4 +1,4 @@
import { Alert, AlertTitle, Slide, SlideProps, Snackbar } from "@mui/material"; import { Alert, AlertTitle, Box, Slide, SlideProps, Snackbar } from "@mui/material";
import { useAtom, useAtomValue } from "jotai"; import { useAtom, useAtomValue } from "jotai";
import { import {
closeNotificationAtom, closeNotificationAtom,
@ -35,6 +35,7 @@ export default function Notification() {
}} }}
> >
<Alert <Alert
data-tauri-drag-region
severity={severity} severity={severity}
icon={false} icon={false}
sx={{ sx={{
@ -42,8 +43,8 @@ export default function Notification() {
borderRadius: 0, borderRadius: 0,
}} }}
> >
{title && <AlertTitle>{title}</AlertTitle>} {title && <AlertTitle data-tauri-drag-region>{title}</AlertTitle>}
{message} {message && <Box data-tauri-drag-region>{message}</Box>}
</Alert> </Alert>
</Snackbar> </Snackbar>
); );

View File

@ -45,7 +45,7 @@ class GatewayService {
}); });
if (!response.ok) { if (!response.ok) {
throw new Error("Login failed"); throw new Error(`Gateway login failed: ${response.status}`);
} }
return this.parseLoginResponse(response.data); return this.parseLoginResponse(response.data);

View File

@ -36,8 +36,9 @@ export type PortalCredential = {
class PortalService { class PortalService {
async prelogin(portal: string): Promise<Prelogin> { async prelogin(portal: string): Promise<Prelogin> {
const preloginUrl = `https://${portal}/global-protect/prelogin.esp`; const preloginUrl = `https://${portal}/global-protect/prelogin.esp`;
let response;
try { try {
const response = await fetch<string>(preloginUrl, { response = await fetch<string>(preloginUrl, {
method: "POST", method: "POST",
headers: { headers: {
"User-Agent": "PAN GlobalProtect", "User-Agent": "PAN GlobalProtect",
@ -57,14 +58,15 @@ class PortalService {
// "host-id": "TODO, mac address?", // "host-id": "TODO, mac address?",
}), }),
}); });
if (!response.ok) {
throw new Error(`Failed to prelogin: ${response.status}`);
}
return this.parsePrelogin(response.data);
} catch (err) { } catch (err) {
throw new Error(`Failed to prelogin: Network error`); console.error("Failed to prelogin: Network error", err);
throw new Error("Failed to prelogin: Network error");
} }
if (!response.ok) {
throw new Error(`Failed to prelogin: ${response.status}`);
}
return this.parsePrelogin(response.data);
} }
private parsePrelogin(response: string): Prelogin { private parsePrelogin(response: string): Prelogin {