Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?
.env
.env
.direnv
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
description = "A Nix flake for gnosis_vpn-self-onboarding (React + TypeScript + Vite)";

inputs = {
# Using the unstable channel for up-to-date packages
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};

outputs = { self, nixpkgs }:
let
# Supported systems for the dev shell
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];

# Helper function to generate attributes for each supported system
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
in
{
devShells = forAllSystems (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
default = pkgs.mkShell {
# Core packages needed for the development environment
packages = with pkgs; [
nodejs_22 # Standard modern Node.js version (adjust to nodejs_20 if needed)
yarn # Required for yarn.lock compatibility

# Helpful utility tools for development
nodePackages.typescript-language-server
nodePackages.prettier
];

# A startup script that runs when you enter the development shell
shellHook = ''
echo "🚀 Welcome to the gnosis_vpn-self-onboarding dev shell!"
echo "Node version: $(node -v)"
echo "Yarn version: $(yarn -v)"

# Optional: automatically run yarn install if node_modules doesn't exist
if [ ! -d "node_modules" ]; then
echo "📦 Installing dependencies..."
yarn install
fi
'';
};
}
);
};
}

62 changes: 7 additions & 55 deletions src/views/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default function Login({ className }: LoginProps) {
}
}



return (
<Container className={`Login${className ? ` ${className}` : ""}`} maxWidth={false}>
Expand Down Expand Up @@ -163,64 +163,20 @@ export default function Login({ className }: LoginProps) {
lineHeight: 1.4,
}}
>
Please read our privacy policy to understand how we're keeping
this experience private.
We're committed to making onboarding as private as possible
</Typography>

<Typography
variant="body2"
sx={{
fontWeight: 600,
mb: { xs: 0.75, sm: 1, md: 1 },
fontSize: "0.85rem",
}}
>
In brief:
</Typography>

<Box
component="ul"
sx={{
pl: { xs: 1.5, sm: 2, md: 2 },
m: 0,
mb: { xs: 1, sm: 1.25, md: 1.5 },
}}
>
<Typography
component="li"
variant="body2"
sx={{
mb: { xs: 0.6, sm: 0.8, md: 0.8 },
fontSize: "0.8rem",
lineHeight: 1.4,
}}
>
<strong>"Share minimal data"</strong> will let you store login,
easily switch devices, and resume your session. You can contact
support and submit feedback through this tool.
</Typography>
<Typography
component="li"
variant="body2"
sx={{
fontSize: "0.8rem",
lineHeight: 1.4,
}}
>
If you choose to stay anonymous, data will only be stored
locally, including your feedback.
</Typography>
</Box>

<Typography
variant="body2"
sx={{
fontSize: "0.8rem",
lineHeight: 1.4,
}}
>
We respect your choice, but if you'd be willing to share minimal
data with us it would greatly help the development process.
This tool will help you onboard to Gnosis VPN.
To do so, we'll need to store minimal data which will let you resume your session, switch devices, contact support and submit feedback.
This data will only be used to facilitate the onboarding and testing process.
Although the onboarding uses your IP address to test connectivity, it is not sent to us or stored.
</Typography>
</Paper>

Expand All @@ -231,11 +187,7 @@ export default function Login({ className }: LoginProps) {
sx={{ mb: { xs: 2, sm: 2.5, md: 3 } }}
>
<Button
label="Stay anonymous"
disabled
/>
<Button
label="Share minimal data"
label="I understand. Log me in!"
loading={loading}
onClick={() => loginUser(username, password)}
/>
Expand Down
61 changes: 55 additions & 6 deletions src/views/onboarding/99_Feedback.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import { useState } from "react";
import { Box, TextField, Typography, Stack } from "@mui/material";
import {
Box,
TextField,
Typography,
Stack,
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
DialogActions,
Button as MuiButton
} from "@mui/material";
import Button from "../../components/onboarding/Button";
import { useAppStore } from "../../store/appStore";
import { uploadData } from "../../functions";
Expand All @@ -19,8 +30,9 @@ export default function Feedback({ className }: FeedbackProps) {
const isSameDevice = useAppStore((state) => state.isSameDevice);
const saveFeedback = useAppStore((state) => state.saveFeedback);
const resetStore = useAppStore((state) => state.resetStore);

const [loading, setLoading] = useState(false);

const [showThankYou, setShowThankYou] = useState(false);

const questions = [
{ key: "feel", label: "How did the product feel to use?" },
Expand All @@ -33,6 +45,12 @@ export default function Feedback({ className }: FeedbackProps) {
const handleTheEnd = async () => {
setLoading(true);
await uploadData(token, { onboardingStep, stepLog, notes, feedback, onboardingAnswers, isMacOs, isSameDevice });
setLoading(false);
setShowThankYou(true);
};

const handleCloseDialog = () => {
setShowThankYou(false);
localStorage.removeItem('gvso_authToken');
resetStore();
};
Expand Down Expand Up @@ -97,13 +115,44 @@ export default function Feedback({ className }: FeedbackProps) {
/>
</Box>
))}
<Button
label="The End"
loading={loading}
onClick={handleTheEnd}
<Button
label="The End"
loading={loading}
onClick={handleTheEnd}
style={{maxHeight: '52px'}}
/>
</Stack>

{/* Thank You Popup */}
<Dialog
open={showThankYou}
onClose={(_event, reason) => {
if (reason === "backdropClick" || reason === "escapeKeyDown") {
return;
}
handleCloseDialog();
}}
aria-labelledby="thank-you-dialog-title"
aria-describedby="thank-you-dialog-description"
PaperProps={{
sx: { p: 1, borderRadius: 2 }
}}
>
<DialogTitle id="thank-you-dialog-title" sx={{ fontWeight: 700 }}>
You made it to the end!
</DialogTitle>
<DialogContent>
<DialogContentText id="thank-you-dialog-description" sx={{ color: "text.primary" }}>
Thank you for completing the onboarding and helping test this release.
Your time and feedback help us improve the VPN and make it better for everyone.
</DialogContentText>
</DialogContent>
<DialogActions>
<MuiButton onClick={handleCloseDialog} variant="contained" disableElevation>
Close
</MuiButton>
</DialogActions>
</Dialog>
</Box>
);
}
Loading