Browse Source

Switch to Vite and prune dependencies

pull/2/head
Sacha Weatherstone 5 years ago
parent
commit
c684f6ad5f
  1. 2
      .github/workflows/main.yml
  2. 3
      .gitignore
  3. 28
      index.html
  4. 18
      package.json
  5. 2513
      pnpm-lock.yaml
  6. 53
      snowpack.config.mjs
  7. 2
      src/App.tsx
  8. 15
      src/components/Channel.tsx
  9. 6
      src/components/chat/MessageBar.tsx
  10. 155
      src/components/generic/Chart.tsx
  11. 2
      src/components/generic/form/Checkbox.tsx
  12. 4
      src/components/generic/form/Input.tsx
  13. 4
      src/components/generic/form/Select.tsx
  14. 2
      src/components/menu/buttons/DeviceStatusDropdown.tsx
  15. 2
      src/components/menu/buttons/MobileNavToggle.tsx
  16. 2
      src/components/menu/buttons/ThemeToggle.tsx
  17. 5
      src/components/templates/PageLayout.tsx
  18. 2
      src/pages/About.tsx
  19. 2
      src/pages/Messages.tsx
  20. 2
      src/pages/Nodes/Index.tsx
  21. 125
      src/pages/Nodes/Node.tsx
  22. 2
      src/pages/NotFound.tsx
  23. 14
      src/pages/Plugins/Files.tsx
  24. 2
      src/pages/Plugins/Index.tsx
  25. 10
      src/pages/Plugins/RangeTest.tsx
  26. 12
      src/pages/settings/Channels.tsx
  27. 12
      src/pages/settings/Connection.tsx
  28. 12
      src/pages/settings/Device.tsx
  29. 2
      src/pages/settings/Index.tsx
  30. 4
      src/pages/settings/Interface.tsx
  31. 10
      src/pages/settings/Radio.tsx
  32. 4
      tailwind.config.js
  33. 21
      vite.config.ts

2
.github/workflows/main.yml

@ -39,4 +39,4 @@ jobs:
automatic_release_tag: 'latest'
prerelease: false
files: |
./build/build.tar
./dist/build.tar

3
.gitignore

@ -1,4 +1,3 @@
.snowpack
build
dist
node_modules
.env

28
index.html

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-tab.svg" color="#67ea94" />
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
<meta name="theme-color" content="#67ea94" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0"
/>
<meta
name="description"
content="Web site created using create-snowpack-app"
/>
<title>Meshtastic Web</title>
</head>
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>

18
package.json

@ -4,9 +4,10 @@
"description": "Meshtastic web client",
"license": "GPL-3.0-only",
"scripts": {
"start": "NODE_ENV=development snowpack dev",
"build": "snowpack build",
"package": "gzipper c -i html,js,css,png,ico,svg,webmanifest build build/output && tar -cvf build/build.tar -C ./build/output/ $(ls ./build/output/)",
"dev": "NODE_ENV=development vite",
"build": "tsc && vite build",
"preview": "vite preview",
"package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,woff,woff2 dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ $(ls ./dist/output/)",
"format": "prettier --write 'src/**/*.{ts,tsx}'",
"lint": "eslint 'src/**/*.{ts,tsx}'"
},
@ -14,11 +15,9 @@
"@headlessui/react": "^1.4.2",
"@meshtastic/meshtasticjs": "^0.6.25",
"@reduxjs/toolkit": "^1.6.2",
"apexcharts": "^3.29.0",
"boring-avatars": "^1.5.8",
"i18next": "^21.4.2",
"i18next-browser-languagedetector": "^6.1.2",
"moment": "^2.29.1",
"react": "^17.0.2",
"react-apexcharts": "^1.3.9",
"react-dom": "^17.0.2",
@ -34,10 +33,6 @@
"use-breakpoint": "^2.0.2"
},
"devDependencies": {
"@snowpack/plugin-dotenv": "^2.2.0",
"@snowpack/plugin-postcss": "^1.4.3",
"@snowpack/plugin-react-refresh": "^2.5.0",
"@snowpack/plugin-typescript": "^1.2.1",
"@types/react": "^17.0.34",
"@types/react-dom": "^17.0.11",
"@types/react-file-icon": "^1.0.1",
@ -49,6 +44,7 @@
"@typescript-eslint/eslint-plugin": "^5.3.1",
"@typescript-eslint/parser": "^5.3.1",
"@verypossible/eslint-config": "^1.6.1",
"@vitejs/plugin-react": "^1.0.8",
"autoprefixer": "^10.4.0",
"babel-plugin-module-resolver": "^4.1.0",
"eslint": "8.2.0",
@ -61,9 +57,9 @@
"gzipper": "^6.0.0",
"postcss": "^8.3.11",
"prettier": "^2.4.1",
"snowpack": "^3.8.8",
"tailwindcss": "^3.0.0-alpha.2",
"tar": "^6.1.11",
"typescript": "^4.4.4"
"typescript": "^4.4.4",
"vite": "^2.6.14"
}
}

2513
pnpm-lock.yaml

File diff suppressed because it is too large

53
snowpack.config.mjs

@ -1,53 +0,0 @@
//@ts-check
/** @type {import("snowpack").SnowpackUserConfig } */
export default {
mount: {
public: { url: '/' },
src: { url: '/' },
},
plugins: [
'@snowpack/plugin-react-refresh',
'@snowpack/plugin-dotenv',
'@snowpack/plugin-postcss',
[
'@snowpack/plugin-typescript',
{
/* Yarn PnP workaround: see https://www.npmjs.com/package/@snowpack/plugin-typescript */
...(process.versions.pnp ? { tsc: 'yarn pnpify tsc' } : {}),
},
],
],
alias: {
// Type 1: Package Import Alias
// "lodash": "lodash-es",
// Type 2: Local Directory Import Alias (relative to cwd)
'@app': './src',
'@pages': './src/pages',
'@components': './src/components',
'@core': './src/core',
},
routes: [
/* Enable an SPA Fallback in development: */
// {"match": "routes", "src": ".*", "dest": "/index.html"},
],
optimize: {
/* Example: Bundle your final build: */
bundle: true,
sourcemap: false,
splitting: true,
treeshake: true,
manifest: false,
minify: true,
target: 'es2020',
},
packageOptions: {
/* ... */
},
devOptions: {
/* ... */
},
buildOptions: {
/* ... */
},
};

2
src/App.tsx

@ -50,7 +50,7 @@ const App = (): JSX.Element => {
? hostOverride
: import.meta.env.NODE_ENV === 'production'
? window.location.hostname
: (import.meta.env.SNOWPACK_PUBLIC_DEVICE_IP as string) ??
: (import.meta.env.VITE_PUBLIC_DEVICE_IP as string) ??
'http://meshtastic.local';
React.useEffect(() => {

15
src/components/Channel.tsx

@ -5,10 +5,10 @@ import { FiEdit3, FiSave } from 'react-icons/fi';
import { Protobuf } from '@meshtastic/meshtasticjs';
import { connection } from '../core/connection.js';
import { Input } from './generic/form/Input.jsx';
import { Select } from './generic/form/Select.jsx';
import { IconButton } from './generic/IconButton.jsx';
import { connection } from '../core/connection';
import { Input } from './generic/form/Input';
import { Select } from './generic/form/Select';
import { IconButton } from './generic/IconButton';
export interface ChannelProps {
channel: Protobuf.Channel;
@ -39,7 +39,6 @@ export const Channel = ({ channel }: ChannelProps): JSX.Element => {
role: Protobuf.Channel_Role;
settings: {
name: string;
modemConfig: Protobuf.ChannelSettings_ModemConfig;
bandwidth?: number;
codingRate?: number;
spreadFactor?: number;
@ -99,19 +98,19 @@ export const Channel = ({ channel }: ChannelProps): JSX.Element => {
<Input
label="Bandwidth"
type="number"
{...register('settings.bandwidth')}
{...register('settings.bandwidth', { valueAsNumber: true })}
/>
<Input
label="Spread Factor"
type="number"
min={7}
max={12}
{...register('settings.spreadFactor')}
{...register('settings.spreadFactor', { valueAsNumber: true })}
/>
<Input
label="Coding Rate"
type="number"
{...register('settings.codingRate')}
{...register('settings.codingRate', { valueAsNumber: true })}
/>
</form>
</div>

6
src/components/chat/MessageBar.tsx

@ -3,13 +3,13 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { FiSend } from 'react-icons/fi';
import { ackMessage } from '@app/core/slices/meshtasticSlice.js';
import { ackMessage } from '@app/core/slices/meshtasticSlice';
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { Input } from '@components/generic/form/Input';
import { connection } from '@core/connection';
import { Select } from '../generic/form/Select.jsx';
import { IconButton } from '../generic/IconButton.jsx';
import { Select } from '../generic/form/Select';
import { IconButton } from '../generic/IconButton';
export const MessageBar = (): JSX.Element => {
const dispatch = useAppDispatch();

155
src/components/generic/Chart.tsx

@ -1,155 +0,0 @@
import React from 'react';
import ApexChart from 'react-apexcharts';
import { Button } from './Button';
import { Card } from './Card';
type DefaultDivProps = JSX.IntrinsicElements['div'];
interface ISeries {
name: string;
data: {
x: string | Date;
y: number;
}[];
}
interface ChartProps extends DefaultDivProps {
title: string;
description: string;
hasMultipleSeries: boolean;
series: ISeries[];
}
export const Chart = ({
title,
description,
hasMultipleSeries,
series,
...props
}: ChartProps): JSX.Element => {
const [activeSeries, setActiveSeries] = React.useState<ISeries>(series[0]);
return (
<div className="dark" {...props}>
<Card
title={title}
description={description}
buttons={
hasMultipleSeries ? (
<div className="flex space-x-2">
{series.map((data, index) => (
<Button
active={data.name === activeSeries.name}
key={index}
className="font-medium"
onClick={(): void => {
setActiveSeries(series[index]);
}}
>
{data.name}
</Button>
))}
</div>
) : undefined
}
>
<div className="h-80">
<ApexChart
height="96%"
type="area"
options={{
chart: {
animations: {
speed: 400,
animateGradually: {
enabled: false,
},
},
toolbar: {
show: false,
},
zoom: {
enabled: false,
},
},
colors: ['#818CF8'],
dataLabels: {
enabled: false,
},
fill: {
colors: ['#312E81'],
},
grid: {
padding: {
top: 10,
left: 0,
right: 0,
},
xaxis: {
lines: {
show: false,
},
},
yaxis: {
lines: {
show: false,
},
},
},
stroke: {
width: 2,
},
tooltip: {
followCursor: true,
theme: 'dark',
x: {
format: 'MMM dd, yyyy',
},
y: {
formatter: (value: number): string => `${value}`,
},
},
xaxis: {
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
crosshairs: {
stroke: {
color: '#475569',
dashArray: 0,
width: 2,
},
},
labels: {
style: {
colors: '#CBD5E1',
},
},
tooltip: {
enabled: false,
},
type: 'datetime',
},
yaxis: {
axisTicks: {
show: false,
},
axisBorder: {
show: false,
},
show: false,
},
}}
series={[activeSeries]}
/>
</div>
</Card>
</div>
);
};

2
src/components/generic/form/Checkbox.tsx

@ -1,6 +1,6 @@
import React from 'react';
import { Label } from './Label.jsx';
import { Label } from './Label';
type DefaultInputProps = JSX.IntrinsicElements['input'];

4
src/components/generic/form/Input.tsx

@ -1,7 +1,7 @@
import React from 'react';
import { InputWrapper } from './InputWrapper.jsx';
import { Label } from './Label.jsx';
import { InputWrapper } from './InputWrapper';
import { Label } from './Label';
type DefaultInputProps = JSX.IntrinsicElements['input'];

4
src/components/generic/form/Select.tsx

@ -1,7 +1,7 @@
import React from 'react';
import { InputWrapper } from './InputWrapper.jsx';
import { Label } from './Label.jsx';
import { InputWrapper } from './InputWrapper';
import { Label } from './Label';
type DefaultSelectProps = JSX.IntrinsicElements['select'];

2
src/components/menu/buttons/DeviceStatusDropdown.tsx

@ -2,8 +2,8 @@ import React from 'react';
import { FiWifi, FiWifiOff } from 'react-icons/fi';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { useAppSelector } from '@app/hooks/redux';
import { IconButton } from '@components/generic/IconButton';
import { Types } from '@meshtastic/meshtasticjs';
export const DeviceStatusDropdown = (): JSX.Element => {

2
src/components/menu/buttons/MobileNavToggle.tsx

@ -2,7 +2,7 @@ import React from 'react';
import { FiMenu } from 'react-icons/fi';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { IconButton } from '@components/generic/IconButton';
import { openMobileNav } from '@core/slices/appSlice';
import { useAppDispatch } from '../../../hooks/redux';

2
src/components/menu/buttons/ThemeToggle.tsx

@ -2,8 +2,8 @@ import React from 'react';
import { FiMoon, FiSun } from 'react-icons/fi';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { IconButton } from '@components/generic/IconButton';
import { setDarkModeEnabled } from '@core/slices/appSlice';
export const ThemeToggle = (): JSX.Element => {

5
src/components/templates/PageLayout.tsx

@ -2,10 +2,11 @@ import React from 'react';
import { FiXCircle } from 'react-icons/fi';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { useBreakpoint } from '@app/hooks/breakpoint';
import { Drawer } from '@components/generic/Drawer';
import { SidebarItem, SidebarItemProps } from '@components/generic/SidebarItem';
import { IconButton } from '@components/generic/IconButton';
import type { SidebarItemProps } from '@components/generic/SidebarItem';
import { SidebarItem } from '@components/generic/SidebarItem';
import { Tab } from '@headlessui/react';
export interface PageLayoutProps {

2
src/pages/About.tsx

@ -1,6 +1,6 @@
import React from 'react';
import { Card } from '@app/components/generic/Card';
import { Card } from '@components/generic/Card';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
export const About = (): JSX.Element => {

2
src/pages/Messages.tsx

@ -2,9 +2,9 @@ import React from 'react';
import { FiHash } from 'react-icons/fi';
import { Select } from '@app/components/generic/form/Select.jsx';
import { Message } from '@components/chat/Message';
import { MessageBar } from '@components/chat/MessageBar';
import { Select } from '@components/generic/form/Select';
import { Protobuf } from '@meshtastic/meshtasticjs';
import { useAppSelector } from '../hooks/redux';

2
src/pages/Nodes/Index.tsx

@ -2,8 +2,8 @@ import React from 'react';
import Avatar from 'boring-avatars';
import { PageLayout } from '@app/components/templates/PageLayout.jsx';
import { useAppSelector } from '@app/hooks/redux';
import { PageLayout } from '@components/templates/PageLayout';
import { Protobuf } from '@meshtastic/meshtasticjs';
import { Node } from './Node';

125
src/pages/Nodes/Node.tsx

@ -2,17 +2,15 @@ import 'react-json-pretty/themes/acai.css';
import React from 'react';
import moment from 'moment';
import { FiMenu, FiTerminal } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
import TimeAgo from 'react-timeago';
import { Card } from '@app/components/generic/Card';
import { Chart } from '@app/components/generic/Chart';
import { Checkbox } from '@app/components/generic/form/Checkbox';
import { Input } from '@app/components/generic/form/Input';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { StatCard } from '@app/components/generic/StatCard';
import { Card } from '@components/generic/Card';
import { Checkbox } from '@components/generic/form/Checkbox';
import { Input } from '@components/generic/form/Input';
import { IconButton } from '@components/generic/IconButton';
import { StatCard } from '@components/generic/StatCard';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import type { Protobuf } from '@meshtastic/meshtasticjs';
@ -44,119 +42,6 @@ export const Node = ({ navOpen, setNavOpen, node }: NodeProps): JSX.Element => {
/>
<StatCard title="SNR" value={node.snr.toString()} />
</div>
<Chart
title={`${node.user?.longName ?? 'UNK'}`}
description="Airtime"
hasMultipleSeries={true}
series={[
{
name: 'Series 1',
data: [
{
x: moment().subtract(12, 'months').day(1).toDate(),
y: 4884,
},
{
x: moment().subtract(12, 'months').day(4).toDate(),
y: 5351,
},
{
x: moment().subtract(12, 'months').day(7).toDate(),
y: 5293,
},
{
x: moment().subtract(12, 'months').day(10).toDate(),
y: 4908,
},
{
x: moment().subtract(12, 'months').day(13).toDate(),
y: 5027,
},
{
x: moment().subtract(12, 'months').day(16).toDate(),
y: 4837,
},
{
x: moment().subtract(12, 'months').day(19).toDate(),
y: 4484,
},
{
x: moment().subtract(12, 'months').day(22).toDate(),
y: 4071,
},
{
x: moment().subtract(12, 'months').day(25).toDate(),
y: 4124,
},
{
x: moment().subtract(12, 'months').day(28).toDate(),
y: 4563,
},
{
x: moment().subtract(11, 'months').day(1).toDate(),
y: 3820,
},
{
x: moment().subtract(11, 'months').day(4).toDate(),
y: 3968,
},
],
},
{
name: 'Series 2',
data: [
{
x: moment().subtract(12, 'months').day(1).toDate(),
y: 4332,
},
{
x: moment().subtract(12, 'months').day(4).toDate(),
y: 6642,
},
{
x: moment().subtract(12, 'months').day(7).toDate(),
y: 5531,
},
{
x: moment().subtract(12, 'months').day(10).toDate(),
y: 2231,
},
{
x: moment().subtract(12, 'months').day(13).toDate(),
y: 5532,
},
{
x: moment().subtract(12, 'months').day(16).toDate(),
y: 3352,
},
{
x: moment().subtract(12, 'months').day(19).toDate(),
y: 6633,
},
{
x: moment().subtract(12, 'months').day(22).toDate(),
y: 1442,
},
{
x: moment().subtract(12, 'months').day(25).toDate(),
y: 4332,
},
{
x: moment().subtract(12, 'months').day(28).toDate(),
y: 6332,
},
{
x: moment().subtract(11, 'months').day(1).toDate(),
y: 5334,
},
{
x: moment().subtract(11, 'months').day(4).toDate(),
y: 5253,
},
],
},
]}
/>
<Card
title="Position"
description={new Date(node.lastHeard * 1000).toLocaleString()}

2
src/pages/NotFound.tsx

@ -1,6 +1,6 @@
import React from 'react';
import { Card } from '@app/components/generic/Card';
import { Card } from '@components/generic/Card';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
export const NotFound = (): JSX.Element => {

14
src/pages/Plugins/Files.tsx

@ -1,13 +1,13 @@
import React from 'react';
import { DefaultExtensionType, defaultStyles, FileIcon } from 'react-file-icon';
// import { DefaultExtensionType, defaultStyles, FileIcon } from 'react-file-icon';
import { FiMenu, FiTrash, FiUploadCloud } from 'react-icons/fi';
import useSWR from 'swr';
import { Card } from '@app/components/generic/Card';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import fetcher from '@app/core/utils/fetcher.js';
import fetcher from '@app/core/utils/fetcher';
import { useAppSelector } from '@app/hooks/redux';
import { Card } from '@components/generic/Card';
import { IconButton } from '@components/generic/IconButton';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
export interface RangeTestProps {
@ -42,7 +42,7 @@ export const Files = ({ navOpen, setNavOpen }: RangeTestProps): JSX.Element => {
? hostOverride
: import.meta.env.NODE_ENV === 'production'
? window.location.hostname
: (import.meta.env.SNOWPACK_PUBLIC_DEVICE_IP as string) ??
: (import.meta.env.VITE_PUBLIC_DEVICE_IP as string) ??
'http://meshtastic.local';
const { data } = useSWR<IFiles>(
@ -91,7 +91,7 @@ export const Files = ({ navOpen, setNavOpen }: RangeTestProps): JSX.Element => {
>
<div className="flex p-2 max-h-12">
<div className="flex w-12">
<FileIcon
{/* <FileIcon
extension={
(file.nameModified ?? file.name).split('.')[
(file.nameModified ?? file.name).split('.').length -
@ -104,7 +104,7 @@ export const Files = ({ navOpen, setNavOpen }: RangeTestProps): JSX.Element => {
1
] as DefaultExtensionType
]}
/>
/> */}
</div>
<a
href={`http://${connectionURL}/${file.name.replace(

2
src/pages/Plugins/Index.tsx

@ -2,7 +2,7 @@ import React from 'react';
import { FiFileText, FiRss } from 'react-icons/fi';
import { PageLayout } from '@app/components/templates/PageLayout.jsx';
import { PageLayout } from '@components/templates/PageLayout';
import { Files } from './Files';
import { RangeTest } from './RangeTest';

10
src/pages/Plugins/RangeTest.tsx

@ -4,13 +4,13 @@ import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { FiMenu, FiSave } from 'react-icons/fi';
import { Card } from '@app/components/generic/Card';
import { Checkbox } from '@app/components/generic/form/Checkbox';
import { Input } from '@app/components/generic/form/Input.jsx';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { connection } from '@app/core/connection.js';
import { connection } from '@app/core/connection';
import { useAppSelector } from '@app/hooks/redux';
import { Button } from '@components/generic/Button';
import { Card } from '@components/generic/Card';
import { Checkbox } from '@components/generic/form/Checkbox';
import { Input } from '@components/generic/form/Input';
import { IconButton } from '@components/generic/IconButton';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import type { RadioConfig_UserPreferences } from '@meshtastic/meshtasticjs/dist/generated';

12
src/pages/settings/Channels.tsx

@ -4,13 +4,13 @@ import { useTranslation } from 'react-i18next';
import { FiCode, FiMenu, FiSave } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
import { Channel } from '@app/components/Channel.jsx';
import { Card } from '@app/components/generic/Card';
import { Cover } from '@app/components/generic/Cover.jsx';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { connection } from '@app/core/connection.js';
import { useAppSelector } from '@app/hooks/redux.js';
import { connection } from '@app/core/connection';
import { useAppSelector } from '@app/hooks/redux';
import { Channel } from '@components/Channel';
import { Button } from '@components/generic/Button';
import { Card } from '@components/generic/Card';
import { Cover } from '@components/generic/Cover';
import { IconButton } from '@components/generic/IconButton';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
export interface ChannelsProps {

12
src/pages/settings/Connection.tsx

@ -4,14 +4,14 @@ import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { FiCheck, FiMenu, FiSave } from 'react-icons/fi';
import { Card } from '@app/components/generic/Card';
import { Checkbox } from '@app/components/generic/form/Checkbox';
import { Input } from '@app/components/generic/form/Input';
import { Select } from '@app/components/generic/form/Select';
import { IconButton } from '@app/components/generic/IconButton';
import { connection, setConnection } from '@app/core/connection';
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { Button } from '@components/generic/Button';
import { Card } from '@components/generic/Card';
import { Checkbox } from '@components/generic/form/Checkbox';
import { Input } from '@components/generic/form/Input';
import { Select } from '@components/generic/form/Select';
import { IconButton } from '@components/generic/IconButton';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import {
IBLEConnection,
@ -111,7 +111,7 @@ export const Connection = ({
? hostOverride
: import.meta.env.NODE_ENV === 'production'
? window.location.hostname
: (import.meta.env.SNOWPACK_PUBLIC_DEVICE_IP as string) ??
: (import.meta.env.VITE_PUBLIC_DEVICE_IP as string) ??
'http://meshtastic.local';
const ble = new IBLEConnection();

12
src/pages/settings/Device.tsx

@ -5,16 +5,16 @@ import { useTranslation } from 'react-i18next';
import { FiCode, FiMenu, FiSave } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
import { Card } from '@app/components/generic/Card';
import { Cover } from '@app/components/generic/Cover.jsx';
import { Checkbox } from '@app/components/generic/form/Checkbox';
import { Select } from '@app/components/generic/form/Select.jsx';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { connection } from '@app/core/connection';
import { addUser } from '@app/core/slices/meshtasticSlice.js';
import { addUser } from '@app/core/slices/meshtasticSlice';
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { Button } from '@components/generic/Button';
import { Card } from '@components/generic/Card';
import { Cover } from '@components/generic/Cover';
import { Checkbox } from '@components/generic/form/Checkbox';
import { Input } from '@components/generic/form/Input';
import { Select } from '@components/generic/form/Select';
import { IconButton } from '@components/generic/IconButton';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import { Protobuf } from '@meshtastic/meshtasticjs';

2
src/pages/settings/Index.tsx

@ -8,7 +8,7 @@ import {
FiSmartphone,
} from 'react-icons/fi';
import { PageLayout } from '@app/components/templates/PageLayout.jsx';
import { PageLayout } from '@components/templates/PageLayout';
import { Channels } from './Channels';
import { Connection } from './Connection';

4
src/pages/settings/Interface.tsx

@ -3,10 +3,10 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { FiMenu, FiSave } from 'react-icons/fi';
import { Card } from '@app/components/generic/Card';
import { Select } from '@app/components/generic/form/Select';
import i18n from '@app/core/translation';
import { Button } from '@components/generic/Button';
import { Card } from '@components/generic/Card';
import { Select } from '@components/generic/form/Select';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
export interface InterfaceProps {

10
src/pages/settings/Radio.tsx

@ -5,15 +5,15 @@ import { useTranslation } from 'react-i18next';
import { FiCode, FiMenu, FiSave, FiXCircle } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
import { Card } from '@app/components/generic/Card';
import { Cover } from '@app/components/generic/Cover.jsx';
import { Checkbox } from '@app/components/generic/form/Checkbox';
import { Select } from '@app/components/generic/form/Select.jsx';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { connection } from '@app/core/connection';
import { useAppSelector } from '@app/hooks/redux';
import { Button } from '@components/generic/Button';
import { Card } from '@components/generic/Card';
import { Cover } from '@components/generic/Cover';
import { Checkbox } from '@components/generic/form/Checkbox';
import { Input } from '@components/generic/form/Input';
import { Select } from '@components/generic/form/Select';
import { IconButton } from '@components/generic/IconButton';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import { Protobuf } from '@meshtastic/meshtasticjs';

4
tailwind.config.js

@ -1,9 +1,11 @@
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
content: ['./public/**/*.html', './src/**/*.tsx'],
darkMode: 'class', // or 'media' or 'class'
theme: {
fontFamily: {
sans: 'Roboto',
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
},
extend: {
colors: {

21
vite.config.ts

@ -0,0 +1,21 @@
import path from 'path';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
build: {
target: 'esnext',
assetsDir: '',
},
resolve: {
alias: {
'@app': path.resolve(__dirname, './src'),
'@pages': path.resolve(__dirname, './src/pages'),
'@components': path.resolve(__dirname, './src/components'),
'@core': path.resolve(__dirname, './src/core'),
},
},
});
Loading…
Cancel
Save