Rebuild
This commit is contained in:
+18
-7
@@ -4,6 +4,7 @@ import {
|
||||
addMessage,
|
||||
addNode,
|
||||
addPosition,
|
||||
addRoute,
|
||||
addUser,
|
||||
resetState,
|
||||
setDeviceStatus,
|
||||
@@ -23,8 +24,6 @@ import {
|
||||
Types,
|
||||
} from '@meshtastic/meshtasticjs';
|
||||
|
||||
import { showNotification } from './utils/notifications';
|
||||
|
||||
type connectionType = IBLEConnection | IHTTPConnection | ISerialConnection;
|
||||
|
||||
export let connection: connectionType = new IHTTPConnection();
|
||||
@@ -36,9 +35,6 @@ export const connectionUrl = state.hostOverrideEnabled
|
||||
? window.location.hostname
|
||||
: (import.meta.env.VITE_PUBLIC_DEVICE_IP as string) ?? 'meshtastic.local';
|
||||
|
||||
export const ble = new IBLEConnection();
|
||||
export const serial = new ISerialConnection();
|
||||
|
||||
export const setConnection = async (conn: connType): Promise<void> => {
|
||||
await connection.disconnect();
|
||||
cleanupListeners();
|
||||
@@ -75,6 +71,7 @@ export const setConnection = async (conn: connType): Promise<void> => {
|
||||
};
|
||||
|
||||
export const cleanupListeners = (): void => {
|
||||
connection.onMeshPacket.cancelAll();
|
||||
connection.onDeviceStatus.cancelAll();
|
||||
connection.onMyNodeInfo.cancelAll();
|
||||
connection.onUserPacket.cancelAll();
|
||||
@@ -88,6 +85,20 @@ export const cleanupListeners = (): void => {
|
||||
const registerListeners = (): void => {
|
||||
SettingsManager.debugMode = Protobuf.LogRecord_Level.TRACE;
|
||||
|
||||
connection.onMeshPacket.subscribe((packet) => {
|
||||
console.log(packet);
|
||||
store.dispatch(
|
||||
addRoute({
|
||||
from: packet.from,
|
||||
to:
|
||||
packet.to === 0xffffffff
|
||||
? store.getState().meshtastic.radio.hardware.myNodeNum
|
||||
: packet.to,
|
||||
hops: packet.hopLimit,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
connection.onDeviceStatus.subscribe((status) => {
|
||||
store.dispatch(setDeviceStatus(status));
|
||||
|
||||
@@ -142,6 +153,8 @@ const registerListeners = (): void => {
|
||||
);
|
||||
|
||||
connection.onRoutingPacket.subscribe((routingPacket) => {
|
||||
console.log(routingPacket);
|
||||
|
||||
store.dispatch(
|
||||
updateLastInteraction({
|
||||
id: routingPacket.packet.from,
|
||||
@@ -152,13 +165,11 @@ const registerListeners = (): void => {
|
||||
|
||||
connection.onTextPacket.subscribe((message) => {
|
||||
const myNodeNum = store.getState().meshtastic.radio.hardware.myNodeNum;
|
||||
showNotification('New message', message.data);
|
||||
|
||||
store.dispatch(
|
||||
addMessage({
|
||||
message: message,
|
||||
ack: message.packet.from !== myNodeNum,
|
||||
isSender: message.packet.from === myNodeNum,
|
||||
received: message.packet.rxTime
|
||||
? new Date(message.packet.rxTime * 1000)
|
||||
: new Date(),
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ import { createRouter, defineRoute } from 'type-route';
|
||||
|
||||
export const { RouteProvider, useRoute, routes } = createRouter({
|
||||
messages: defineRoute('/'),
|
||||
map: defineRoute('/map'),
|
||||
nodes: defineRoute('/nodes'),
|
||||
settings: defineRoute('/settings'),
|
||||
extensions: defineRoute('/extensions'),
|
||||
});
|
||||
|
||||
@@ -10,17 +10,6 @@ export enum connType {
|
||||
SERIAL,
|
||||
}
|
||||
|
||||
interface Notification {
|
||||
id: string;
|
||||
icon: React.ReactNode;
|
||||
title: string;
|
||||
action?: {
|
||||
message: string;
|
||||
action: () => void;
|
||||
};
|
||||
read: boolean;
|
||||
}
|
||||
|
||||
interface AppState {
|
||||
mobileNavOpen: boolean;
|
||||
navCollapsed: boolean;
|
||||
@@ -33,7 +22,6 @@ interface AppState {
|
||||
HTTP: Types.HTTPConnectionParameters;
|
||||
SERIAL: Types.SerialConnectionParameters;
|
||||
};
|
||||
notifications: Notification[];
|
||||
}
|
||||
|
||||
const initialState: AppState = {
|
||||
@@ -53,18 +41,14 @@ const initialState: AppState = {
|
||||
},
|
||||
SERIAL: {},
|
||||
},
|
||||
notifications: [],
|
||||
};
|
||||
|
||||
export const appSlice = createSlice({
|
||||
name: 'app',
|
||||
initialState,
|
||||
reducers: {
|
||||
openMobileNav(state) {
|
||||
state.mobileNavOpen = true;
|
||||
},
|
||||
closeMobileNav(state) {
|
||||
state.mobileNavOpen = false;
|
||||
toggleMobileNav(state) {
|
||||
state.mobileNavOpen = !state.mobileNavOpen;
|
||||
},
|
||||
openConnectionModal(state) {
|
||||
state.connectionModalOpen = true;
|
||||
@@ -93,31 +77,17 @@ export const appSlice = createSlice({
|
||||
state.connectionParams[connType[action.payload.type]] =
|
||||
action.payload.params;
|
||||
},
|
||||
addNotification(state, action: PayloadAction<Notification>) {
|
||||
state.notifications.push(action.payload);
|
||||
},
|
||||
removeNotification(state, action: PayloadAction<string>) {
|
||||
state.notifications.splice(
|
||||
state.notifications.findIndex(
|
||||
(notification) => notification.id === action.payload,
|
||||
),
|
||||
1,
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
openMobileNav,
|
||||
closeMobileNav,
|
||||
toggleMobileNav,
|
||||
openConnectionModal,
|
||||
closeConnectionModal,
|
||||
setDarkModeEnabled,
|
||||
setCurrentPage,
|
||||
setConnType,
|
||||
setConnectionParams,
|
||||
addNotification,
|
||||
removeNotification,
|
||||
} = appSlice.actions;
|
||||
|
||||
export default appSlice.reducer;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import mapboxgl from 'mapbox-gl';
|
||||
|
||||
import type { MapStyle } from '@app/components/Map/styles';
|
||||
import { MapStyles } from '@app/components/Map/styles';
|
||||
import type { MapStyle } from '@app/pages/Map/styles';
|
||||
import { MapStyles } from '@app/pages/Map/styles';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ import { createSlice } from '@reduxjs/toolkit';
|
||||
export interface MessageWithAck {
|
||||
message: Types.TextPacket;
|
||||
ack: boolean;
|
||||
isSender: boolean;
|
||||
received: Date;
|
||||
}
|
||||
|
||||
export interface ChannelData {
|
||||
channel: Protobuf.Channel;
|
||||
lastChatInterraction: Date;
|
||||
messages: MessageWithAck[];
|
||||
}
|
||||
|
||||
@@ -22,6 +22,14 @@ interface CurrentPosition {
|
||||
satsInView: number;
|
||||
}
|
||||
|
||||
interface Route {
|
||||
from: number;
|
||||
to: number;
|
||||
hops: number;
|
||||
|
||||
//speed stats?
|
||||
}
|
||||
|
||||
export interface Node {
|
||||
number: number;
|
||||
lastHeard: Date;
|
||||
@@ -29,6 +37,7 @@ export interface Node {
|
||||
positions: Protobuf.Position[];
|
||||
currentPosition?: CurrentPosition;
|
||||
user?: Protobuf.User;
|
||||
routes: Route[];
|
||||
}
|
||||
|
||||
export interface Radio {
|
||||
@@ -90,7 +99,9 @@ export const meshtasticSlice = createSlice({
|
||||
node.lastHeard = new Date(action.payload.packet.rxTime * 1000);
|
||||
}
|
||||
} else {
|
||||
// todo: add node
|
||||
console.log('Node not in DB');
|
||||
console.log(action.payload);
|
||||
}
|
||||
},
|
||||
addPosition: (state, action: PayloadAction<Types.PositionPacket>) => {
|
||||
@@ -142,6 +153,7 @@ export const meshtasticSlice = createSlice({
|
||||
lastHeard: new Date(action.payload.lastHeard * 1000),
|
||||
snr: [action.payload.snr],
|
||||
positions: [],
|
||||
routes: [],
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -155,6 +167,7 @@ export const meshtasticSlice = createSlice({
|
||||
return channel.channel.index === action.payload.index
|
||||
? {
|
||||
channel: action.payload,
|
||||
lastChatInterraction: new Date(),
|
||||
messages: channel.messages,
|
||||
}
|
||||
: channel;
|
||||
@@ -162,10 +175,41 @@ export const meshtasticSlice = createSlice({
|
||||
} else {
|
||||
state.radio.channels.push({
|
||||
channel: action.payload,
|
||||
lastChatInterraction: new Date(),
|
||||
messages: [],
|
||||
});
|
||||
}
|
||||
},
|
||||
addRoute: (state, action: PayloadAction<Route>) => {
|
||||
const node = state.nodes.find(
|
||||
(node) => node.number === action.payload.from,
|
||||
);
|
||||
const exists = node?.routes.findIndex(
|
||||
(route) =>
|
||||
route.from === action.payload.from && route.to === action.payload.to,
|
||||
);
|
||||
console.log(exists);
|
||||
|
||||
if (exists === -1) {
|
||||
node?.routes.push(action.payload);
|
||||
}
|
||||
// node?.routes.map((route) => {
|
||||
// if (
|
||||
|
||||
// ) {
|
||||
// node?.routes.push(action.payload);
|
||||
// }
|
||||
// });
|
||||
|
||||
// if (node) {
|
||||
// node.routes = node.routes.map((route) => {
|
||||
// return route.from === action.payload.from &&
|
||||
// route.to === action.payload.to
|
||||
// ? action.payload
|
||||
// : route;
|
||||
// });
|
||||
// }
|
||||
},
|
||||
setPreferences: (
|
||||
state,
|
||||
action: PayloadAction<Protobuf.RadioConfig_UserPreferences>,
|
||||
@@ -178,6 +222,7 @@ export const meshtasticSlice = createSlice({
|
||||
channel.channel.index === action.payload.message.packet.channel,
|
||||
);
|
||||
state.radio.channels[channelIndex].messages.push(action.payload);
|
||||
state.radio.channels[channelIndex].lastChatInterraction = new Date();
|
||||
},
|
||||
ackMessage: (
|
||||
state,
|
||||
@@ -237,6 +282,7 @@ export const {
|
||||
addNode,
|
||||
addChannel,
|
||||
setPreferences,
|
||||
addRoute,
|
||||
addMessage,
|
||||
ackMessage,
|
||||
updateLastInteraction,
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import i18n from 'i18next';
|
||||
import detector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import { en } from '../translations/en';
|
||||
import { jp } from '../translations/jp';
|
||||
import { pt } from '../translations/pt';
|
||||
|
||||
void i18n
|
||||
.use(detector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
fallbackLng: 'en',
|
||||
resources: {
|
||||
en: { translation: en },
|
||||
jp: { translation: jp },
|
||||
pt: { translation: pt },
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
@@ -0,0 +1,9 @@
|
||||
import { request } from 'graphql-request';
|
||||
|
||||
export default async function gqlFetcher<JSON>(
|
||||
url: string,
|
||||
query?: string,
|
||||
): Promise<JSON> {
|
||||
// const res = await fetch(input, init);
|
||||
return await request<JSON>(url, query);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
export const requestNotificationPermission = async (): Promise<void> => {
|
||||
if (window.Notification && Notification.permission !== 'denied') {
|
||||
await Notification.requestPermission();
|
||||
}
|
||||
};
|
||||
|
||||
export const showNotification = (title: string, body: string): void => {
|
||||
new Notification(title, {
|
||||
body,
|
||||
icon: 'android-512.png',
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user