diff --git a/package.json b/package.json
index 120f795c..29aaa51f 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"@emeraldpay/hashicon-react": "^0.5.2",
"@floating-ui/react-dom": "^0.4.3",
"@meshtastic/components": "^1.0.23",
- "@meshtastic/meshtasticjs": "^0.6.43",
+ "@meshtastic/meshtasticjs": "^0.6.45",
"@reduxjs/toolkit": "^1.7.2",
"base64-js": "^1.5.1",
"framer-motion": "^6.2.6",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e2505cb6..fa8652f8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,7 +4,7 @@ specifiers:
'@emeraldpay/hashicon-react': ^0.5.2
'@floating-ui/react-dom': ^0.4.3
'@meshtastic/components': ^1.0.23
- '@meshtastic/meshtasticjs': ^0.6.43
+ '@meshtastic/meshtasticjs': ^0.6.45
'@reduxjs/toolkit': ^1.7.2
'@types/mapbox-gl': ^2.6.1
'@types/react': ^17.0.39
@@ -62,7 +62,7 @@ dependencies:
'@emeraldpay/hashicon-react': 0.5.2
'@floating-ui/react-dom': 0.4.3_b8fdba992ce7d797017dc07106486496
'@meshtastic/components': 1.0.23_@types+react@17.0.39
- '@meshtastic/meshtasticjs': 0.6.43
+ '@meshtastic/meshtasticjs': 0.6.45
'@reduxjs/toolkit': 1.7.2_react-redux@7.2.6+react@17.0.2
base64-js: 1.5.1
framer-motion: 6.2.6_react-dom@17.0.2+react@17.0.2
@@ -1587,8 +1587,8 @@ packages:
- '@types/react'
dev: false
- /@meshtastic/meshtasticjs/0.6.43:
- resolution: {integrity: sha512-INI9hj3AzjkXzJIp2yq65eV908wTCk6Ih5/5fMknKhwOgx14eC6d5qhlWxjC85kHB6gu8c/2KF3LUCFKHh+1fg==}
+ /@meshtastic/meshtasticjs/0.6.45:
+ resolution: {integrity: sha512-icAGMofpQ3hYqWhjYMLqMyhb0Xtk3GozEgOXScFTKVOaecDY0XIJmuvoBDfgD2lxNxDDPr0Dj77js+3JGxTcRg==}
dependencies:
'@protobuf-ts/runtime': 2.2.2
sub-events: 1.8.9
diff --git a/public/placeholders/Files Dark.svg b/public/placeholders/Files Dark.svg
new file mode 100644
index 00000000..ffecedc3
--- /dev/null
+++ b/public/placeholders/Files Dark.svg
@@ -0,0 +1,57 @@
+
diff --git a/public/placeholders/Files.svg b/public/placeholders/Files.svg
new file mode 100644
index 00000000..f306c952
--- /dev/null
+++ b/public/placeholders/Files.svg
@@ -0,0 +1,57 @@
+
diff --git a/public/placeholders/View Code Dark.svg b/public/placeholders/View Code Dark.svg
new file mode 100644
index 00000000..0ead22d1
--- /dev/null
+++ b/public/placeholders/View Code Dark.svg
@@ -0,0 +1,28 @@
+
diff --git a/public/placeholders/View Code.svg b/public/placeholders/View Code.svg
new file mode 100644
index 00000000..b46b0d34
--- /dev/null
+++ b/public/placeholders/View Code.svg
@@ -0,0 +1,28 @@
+
diff --git a/src/App.tsx b/src/App.tsx
index 587ba910..693dac59 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,6 +5,7 @@ import { Connection } from '@components/Connection';
import { useRoute } from '@core/router';
import { useAppSelector } from '@hooks/useAppSelector';
+import { ContextMenu } from './components/generic/ContextMenu';
import { BottomNav } from './components/menu/BottomNav';
import { Extensions } from './pages/Extensions/Index';
import { Messages } from './pages/Messages';
@@ -17,17 +18,19 @@ export const App = (): JSX.Element => {
return (
-
-
-
- {route.name === 'messages' &&
}
- {route.name === 'nodes' &&
}
- {route.name === 'map' &&
}
- {route.name === 'extensions' &&
}
- {route.name === false &&
}
+
+
+
+
+ {route.name === 'messages' && }
+ {route.name === 'nodes' && }
+ {route.name === 'map' && }
+ {route.name === 'extensions' && }
+ {route.name === false && }
+
+
-
-
+
);
};
diff --git a/src/components/generic/ContextMenu.tsx b/src/components/generic/ContextMenu.tsx
new file mode 100644
index 00000000..d3c11808
--- /dev/null
+++ b/src/components/generic/ContextMenu.tsx
@@ -0,0 +1,93 @@
+import React from 'react';
+
+import { m } from 'framer-motion';
+import { FiActivity, FiAperture, FiTag } from 'react-icons/fi';
+
+export interface ContextMenuProps {
+ children: React.ReactNode;
+}
+
+export const ContextMenu = ({ children }: ContextMenuProps): JSX.Element => {
+ const [visible, setVisible] = React.useState(false);
+ const [position, setPosition] = React.useState({ x: 0, y: 0 });
+ const [selectedValue, setSelectedValue] = React.useState
();
+ const doSomething = (selectedValue: string) => {
+ setSelectedValue(selectedValue);
+ };
+
+ const showContextMenu = (event: React.MouseEvent) => {
+ event.preventDefault();
+
+ setVisible(false);
+ const newPosition = {
+ x: event.pageX,
+ y: event.pageY,
+ };
+
+ setPosition(newPosition);
+ setVisible(true);
+ };
+
+ const hideContextMenu = (event: React.MouseEvent) => {
+ setVisible(false);
+ };
+
+ return (
+
+ {children}
+ {selectedValue &&
{selectedValue} is selected
}
+
+ {visible && (
+
+
+
+
+
+
+
+
+ Menu item 2
+
+
+
+
+
+
+
+
+
+ Menu item 3 with a very long name that should wrap
+
+
+
+
+ )}
+
+ );
+};
diff --git a/src/core/slices/meshtasticSlice.ts b/src/core/slices/meshtasticSlice.ts
index a0a356d7..36fdf9b9 100644
--- a/src/core/slices/meshtasticSlice.ts
+++ b/src/core/slices/meshtasticSlice.ts
@@ -85,6 +85,8 @@ export const meshtasticSlice = createSlice({
initialState,
reducers: {
addLogEvent: (state, action: PayloadAction) => {
+ console.log(action.payload.packet);
+
state.logs.push(action.payload);
},
setDeviceStatus: (state, action: PayloadAction) => {
diff --git a/src/pages/Extensions/FileBrowser.tsx b/src/pages/Extensions/FileBrowser.tsx
index bc7e9b9a..7c04f45b 100644
--- a/src/pages/Extensions/FileBrowser.tsx
+++ b/src/pages/Extensions/FileBrowser.tsx
@@ -1,5 +1,6 @@
import React from 'react';
+import { AnimatePresence, m } from 'framer-motion';
import useSWR from 'swr';
import fetcher from '@app/core/utils/fetcher';
@@ -27,6 +28,7 @@ export const FileBrowser = (): JSX.Element => {
const connectionParams = useAppSelector(
(state) => state.app.connectionParams,
);
+ const darkMode = useAppSelector((state) => state.app.darkMode);
const { data } = useSWR(
`${connectionParams.HTTP.tls ? 'https' : 'http'}://${
@@ -42,7 +44,22 @@ export const FileBrowser = (): JSX.Element => {
FileName
Actions
-
+
+
+ {(!data || data?.data.files.length === 0) && (
+
+
+
+ )}
+
{data?.data.files.map((file) => (
{
const logs = useAppSelector((state) => state.meshtastic.logs);
+ const darkMode = useAppSelector((state) => state.app.darkMode);
type lookupType = { [key: number]: string };
@@ -54,6 +55,21 @@ export const Logs = (): JSX.Element => {
className="
block h-full flex-col overflow-y-auto py-4 px-2 font-mono text-xs dark:text-gray-400"
>
+
+ {logs.length === 0 && (
+
+
+
+ )}
+
{logs.map((log, index) => (
{
[{Protobuf.LogRecord_Level[log.level]}]{/* */}
+ |
+
+ |
{log.message} |
))}