diff --git a/src/components/SlideSheets/NewDevice.tsx b/src/components/SlideSheets/NewDevice.tsx index 93eb2f3a..c96ad1d6 100644 --- a/src/components/SlideSheets/NewDevice.tsx +++ b/src/components/SlideSheets/NewDevice.tsx @@ -10,12 +10,12 @@ import { Tab, Tablist, } from "evergreen-ui"; -import type { IconType } from "react-icons"; import { FiBluetooth, FiTerminal, FiWifi } from "react-icons/fi"; import { BLE } from "../connect/BLE.js"; import { HTTP } from "../connect/HTTP.js"; import { Serial } from "../connect/Serial.js"; +import type { TabType } from "../layout/page/TabbedContent.js"; export interface NewDeviceProps { open: boolean; @@ -28,35 +28,32 @@ export interface CloseProps { export type connType = "http" | "ble" | "serial"; -export interface Tab { - name: connType; - icon: IconType; - displayName: string; +export interface ConnTab extends Omit { + connType: connType; element: ({ close }: CloseProps) => JSX.Element; - disabled?: boolean; } export const NewDevice = ({ open, onClose }: NewDeviceProps) => { const [selectedConnType, setSelectedConnType] = useState("ble"); - const tabs: Tab[] = [ + const tabs: ConnTab[] = [ { - name: "ble", + connType: "ble", icon: FiBluetooth, - displayName: "BLE", + name: "BLE", element: BLE, disabled: !navigator.bluetooth, }, { - name: "http", + connType: "http", icon: FiWifi, - displayName: "HTTP", + name: "HTTP", element: HTTP, }, { - name: "serial", + connType: "serial", icon: FiTerminal, - displayName: "Serial", + name: "Serial", element: Serial, disabled: !navigator.serial, }, @@ -85,13 +82,13 @@ export const NewDevice = ({ open, onClose }: NewDeviceProps) => { setSelectedConnType(TabData.name)} + isSelected={selectedConnType === TabData.connType} + onSelect={() => setSelectedConnType(TabData.connType)} disabled={TabData.disabled} > <> - {TabData.displayName} + {TabData.name} ))} @@ -106,7 +103,7 @@ export const NewDevice = ({ open, onClose }: NewDeviceProps) => { backgroundColor="white" elevation={1} flexGrow={1} - display={selectedConnType === TabData.name ? "block" : "none"} + display={selectedConnType === TabData.connType ? "block" : "none"} > {!TabData.disabled && } diff --git a/src/components/layout/page/SlideSheetTabbedContent.tsx b/src/components/layout/page/SlideSheetTabbedContent.tsx new file mode 100644 index 00000000..4296e22d --- /dev/null +++ b/src/components/layout/page/SlideSheetTabbedContent.tsx @@ -0,0 +1,78 @@ +import type React from "react"; +import { useState } from "react"; + +import { + Heading, + IconComponent, + majorScale, + Pane, + Paragraph, + Tab, + Tablist, +} from "evergreen-ui"; +import type { IconType } from "react-icons"; + +export interface TabType { + name: string; + icon: IconComponent | IconType; + element: () => JSX.Element; + disabled?: boolean; +} + +export interface SlideSheetTabbedContentProps { + heading: string; + description: string; + tabs: TabType[]; +} + +export const SlideSheetTabbedContent = ({ + heading, + description, + tabs, +}: SlideSheetTabbedContentProps): JSX.Element => { + const [selectedTab, setSelectedTab] = useState(0); + + return ( + <> + + + {heading} + + {description} + + + + + {tabs.map((Entry, index) => ( + setSelectedTab(index)} + isSelected={selectedTab === index} + > + + {Entry.name} + + ))} + + + + + {tabs.map((Entry, index) => ( + + {!Entry.disabled && } + + ))} + + + ); +}; diff --git a/src/components/layout/page/TabbedContent.tsx b/src/components/layout/page/TabbedContent.tsx index 081bde39..dd2a920c 100644 --- a/src/components/layout/page/TabbedContent.tsx +++ b/src/components/layout/page/TabbedContent.tsx @@ -1,28 +1,27 @@ import type React from "react"; +import { useState } from "react"; import { IconComponent, majorScale, Pane, Tab, Tablist } from "evergreen-ui"; +import type { IconType } from "react-icons"; -export interface Tab { - key: number; +export interface TabType { name: string; - icon: IconComponent; + icon: IconComponent | IconType; element: () => JSX.Element; disabled?: boolean; } export interface TabbedContentProps { - active: number; - setActive: (index: number) => void; - tabs: Tab[]; + tabs: TabType[]; actions?: (() => JSX.Element)[]; } export const TabbedContent = ({ - active, - setActive, tabs, actions, }: TabbedContentProps): JSX.Element => { + const [selectedTab, setSelectedTab] = useState(0); + return ( - {tabs.map((Entry) => ( + {tabs.map((Entry, index) => ( setActive(Entry.key)} - isSelected={active === Entry.key} + onSelect={() => setSelectedTab(index)} + isSelected={selectedTab === index} > {Entry.name} @@ -59,14 +59,14 @@ export const TabbedContent = ({ - {tabs.map((Entry) => ( + {tabs.map((Entry, index) => ( - + {!Entry.disabled && } ))} diff --git a/src/pages/Channels/index.tsx b/src/pages/Channels/index.tsx index 7869b799..13ef8d6b 100644 --- a/src/pages/Channels/index.tsx +++ b/src/pages/Channels/index.tsx @@ -5,7 +5,7 @@ import { Button, LayerIcon, LayerOutlineIcon, Tooltip } from "evergreen-ui"; import { IoQrCodeOutline } from "react-icons/io5"; import { QRDialog } from "@app/components/Dialog/QRDialog.js"; -import { Tab, TabbedContent } from "@components/layout/page/TabbedContent"; +import { TabbedContent, TabType } from "@components/layout/page/TabbedContent"; import { useDevice } from "@core/stores/deviceStore.js"; import { Protobuf } from "@meshtastic/meshtasticjs"; @@ -14,11 +14,9 @@ import { Channel } from "./Channel.js"; export const ChannelsPage = (): JSX.Element => { const { channels, config } = useDevice(); const [QRDialogOpen, setQRDialogOpen] = useState(false); - const [activeChannel, setActiveChannel] = useState(0); - const tabs: Tab[] = channels.map((channel) => { + const tabs: TabType[] = channels.map((channel) => { return { - key: channel.config.index, name: channel.config.settings?.name.length ? channel.config.settings.name : channel.config.role === Protobuf.Channel_Role.PRIMARY @@ -43,8 +41,6 @@ export const ChannelsPage = (): JSX.Element => { loraConfig={config.lora} /> ( diff --git a/src/pages/Config/AppConfig.tsx b/src/pages/Config/AppConfig.tsx new file mode 100644 index 00000000..92ea4aa6 --- /dev/null +++ b/src/pages/Config/AppConfig.tsx @@ -0,0 +1,56 @@ +import type React from "react"; +import { useState } from "react"; + +import { Pane, Tab, Tablist } from "evergreen-ui"; + +import { ExternalNotification } from "@app/components/PageComponents/ModuleConfig/ExternalNotification.js"; +import { MQTT } from "@components/PageComponents/ModuleConfig/MQTT.js"; +import { Serial } from "@components/PageComponents/ModuleConfig/Serial.js"; + +export const AppConfig = (): JSX.Element => { + const [selectedIndex, setSelectedIndex] = useState(0); + + const configSections = [ + { + label: "Interface", + element: MQTT, + }, + { + label: "Logging", + element: Serial, + }, + { + label: "Language", + element: ExternalNotification, + }, + ]; + + return ( + + + + {configSections.map((Config, index) => ( + setSelectedIndex(index)} + > + {Config.label} + + ))} + + + + {configSections.map((Config, index) => ( + + + + ))} + + + ); +}; diff --git a/src/pages/Config/index.tsx b/src/pages/Config/index.tsx index 0d97f317..c706173a 100644 --- a/src/pages/Config/index.tsx +++ b/src/pages/Config/index.tsx @@ -1,36 +1,31 @@ import type React from "react"; -import { useState } from "react"; -import { CogIcon, CubeIcon } from "evergreen-ui"; +import { ApplicationsIcon, CogIcon, CubeIcon } from "evergreen-ui"; -import { Tab, TabbedContent } from "@components/layout/page/TabbedContent"; +import { TabbedContent, TabType } from "@components/layout/page/TabbedContent"; +import { AppConfig } from "./AppConfig.js"; import { DeviceConfig } from "./DeviceConfig.js"; import { ModuleConfig } from "./ModuleConfig.js"; export const ConfigPage = (): JSX.Element => { - const [activeConfig, setActiveConfig] = useState(0); - - const tabs: Tab[] = [ + const tabs: TabType[] = [ { - key: 0, name: "Device Config", icon: CogIcon, element: DeviceConfig, }, { - key: 1, name: "Module Config", icon: CubeIcon, element: ModuleConfig, }, + { + name: "App Config", + icon: ApplicationsIcon, + element: AppConfig, + }, ]; - return ( - - ); + return ; }; diff --git a/src/pages/Extensions/FileBrowser.tsx b/src/pages/Extensions/FileBrowser.tsx index 08d941a9..d677fb70 100644 --- a/src/pages/Extensions/FileBrowser.tsx +++ b/src/pages/Extensions/FileBrowser.tsx @@ -36,10 +36,7 @@ export const FileBrowser = (): JSX.Element => { {file.name.replace("static/", "").replace(".gz", "")} diff --git a/src/pages/Extensions/Index.tsx b/src/pages/Extensions/Index.tsx index a11449cd..bb5ebb6a 100644 --- a/src/pages/Extensions/Index.tsx +++ b/src/pages/Extensions/Index.tsx @@ -1,46 +1,35 @@ import type React from "react"; -import { useState } from "react"; import { DocumentIcon, GanttChartIcon, RainIcon } from "evergreen-ui"; import { useDevice } from "@app/core/stores/deviceStore.js"; -import { Tab, TabbedContent } from "@components/layout/page/TabbedContent"; +import { TabbedContent, TabType } from "@components/layout/page/TabbedContent"; import { FileBrowser } from "@pages/Extensions/FileBrowser"; import { Environment } from "./Environment.js"; export const ExtensionsPage = (): JSX.Element => { - const [activeExtension, setActiveExtension] = useState(0); const { hardware } = useDevice(); - const tabs: Tab[] = [ + const tabs: TabType[] = [ { - key: 0, name: "File Browser", icon: DocumentIcon, element: FileBrowser, disabled: !hardware.hasWifi, }, { - key: 1, name: "Range Test", icon: GanttChartIcon, element: FileBrowser, disabled: !hardware.hasWifi, }, { - key: 2, name: "Environment", icon: RainIcon, element: Environment, }, ]; - return ( - - ); + return ; }; diff --git a/src/pages/Messages/ChannelChat.tsx b/src/pages/Messages/ChannelChat.tsx index 23a799bf..0bb27ec1 100644 --- a/src/pages/Messages/ChannelChat.tsx +++ b/src/pages/Messages/ChannelChat.tsx @@ -28,10 +28,9 @@ export const ChannelChat = ({ channel }: ChannelChatProps): JSX.Element => { currentMessage, undefined, true, - channel.config.index, //maybe channel.config.index-- + channel.config.index, (id) => { - ackMessage(channel.config.index, id), console.log("Got Ack"); - + ackMessage(channel.config.index, id); return Promise.resolve(); } ); @@ -44,7 +43,7 @@ export const ChannelChat = ({ channel }: ChannelChatProps): JSX.Element => { {channel.messages.map((message, index) => ( { - const { channels, activeChat, setActiveChat, setActivePage } = useDevice(); + const { channels, setActivePage } = useDevice(); - const tabs: Tab[] = channels.map((channel) => { + const tabs: TabType[] = channels.map((channel) => { return { - key: channel.config.index, name: channel.config.settings?.name.length ? channel.config.settings?.name : channel.config.index === 0 @@ -35,8 +37,6 @@ export const MessagesPage = (): JSX.Element => { return ( (