diff --git a/gcs/src/components/dashboard/tabsSectionTabs/actionTabsSection.jsx b/gcs/src/components/dashboard/tabsSectionTabs/actionTabsSection.jsx
index fa779bc0c..2411ad462 100644
--- a/gcs/src/components/dashboard/tabsSectionTabs/actionTabsSection.jsx
+++ b/gcs/src/components/dashboard/tabsSectionTabs/actionTabsSection.jsx
@@ -10,6 +10,11 @@ import { useEffect, useMemo, useState } from "react"
import { Button, NumberInput, Popover, Select, Tabs } from "@mantine/core"
import { useLocalStorage } from "@mantine/hooks"
+// Styling imports
+import resolveConfig from "tailwindcss/resolveConfig"
+import tailwindConfig from "../../../../tailwind.config"
+const tailwindColors = resolveConfig(tailwindConfig).theme.colors
+
// Mavlink
import { getFlightModeMap } from "../../../helpers/mavlinkConstants"
@@ -27,6 +32,7 @@ import {
} from "../../../redux/slices/droneInfoSlice"
import { NoConnectionMsg } from "../tabsSection"
+import { useRebootCallback } from "../../../helpers/useRebootCallback"
export default function ActionTabsSection({
connected,
@@ -113,6 +119,7 @@ const ArmTakeoffLandAction = () => {
defaultValue: 10,
})
const isArmed = useSelector(selectArmed)
+ const rebootCallback = useRebootCallback()
function armDisarm(arm, force = false) {
// TODO: Add force arm ability
@@ -165,6 +172,15 @@ const ArmTakeoffLandAction = () => {
>
Land
+
+ {/** Reboot Button */}
+
>
)
diff --git a/gcs/src/components/mainContent.jsx b/gcs/src/components/mainContent.jsx
index 62e069ee1..61059dc8e 100644
--- a/gcs/src/components/mainContent.jsx
+++ b/gcs/src/components/mainContent.jsx
@@ -8,6 +8,7 @@ import { Route, Routes } from "react-router-dom"
import SettingsModal from "./settingsModal"
import { Commands } from "./spotlight/commandHandler"
import Toolbar from "./toolbar/toolbar"
+import AutopilotRebootModal from "./params/autopilotRebootModal.jsx"
// Wrappers
import { SettingsProvider } from "../helpers/settingsProvider"
@@ -59,6 +60,7 @@ export default function AppContent() {
} />
+
diff --git a/gcs/src/components/spotlight/actions.js b/gcs/src/components/spotlight/actions.js
index cddf74f44..fc2f26478 100644
--- a/gcs/src/components/spotlight/actions.js
+++ b/gcs/src/components/spotlight/actions.js
@@ -135,3 +135,6 @@ AddSpotlightAction(
RunCommand("new_preflight_checklist")
},
)
+AddSpotlightAction("reboot_autopilot", "Reboot Autopilot", "command", () => {
+ RunCommand("reboot_autopilot")
+})
diff --git a/gcs/src/components/spotlight/commandHandler.js b/gcs/src/components/spotlight/commandHandler.js
index 952e095f3..d553620ad 100644
--- a/gcs/src/components/spotlight/commandHandler.js
+++ b/gcs/src/components/spotlight/commandHandler.js
@@ -8,12 +8,14 @@ import { useHotkeys } from "@mantine/hooks"
import { useEffect, useState } from "react"
import { useNavigate } from "react-router"
import { useSettings } from "../../helpers/settings"
+import { useRebootCallback } from "../../helpers/useRebootCallback"
let commands = []
export function Commands() {
let navigate = useNavigate()
const [isMac, setIsMac] = useState(false)
+ const rebootCallback = useRebootCallback()
useEffect(() => {
window.ipcRenderer.invoke("app:is-mac").then((result) => {
@@ -49,6 +51,7 @@ export function Commands() {
AddCommand("open_settings", () => {
open()
})
+ AddCommand("reboot_autopilot", rebootCallback)
// Register hotkeys
useHotkeys([
diff --git a/gcs/src/helpers/useRebootCallback.js b/gcs/src/helpers/useRebootCallback.js
new file mode 100644
index 000000000..b407929a2
--- /dev/null
+++ b/gcs/src/helpers/useRebootCallback.js
@@ -0,0 +1,22 @@
+import { useCallback } from "react"
+import { useDispatch } from "react-redux"
+
+import {
+ emitRebootAutopilot,
+ setAutoPilotRebootModalOpen,
+ resetParamState,
+} from "../redux/slices/paramsSlice.js"
+
+/**
+ * Hook that returns a callback to reboot the autopilot.
+ * Initiates autopilot reboot, displays status modal, and resets params.
+ * @returns Callback to reboot autopilot
+ */
+export function useRebootCallback() {
+ const dispatch = useDispatch()
+ return useCallback(() => {
+ dispatch(emitRebootAutopilot())
+ dispatch(setAutoPilotRebootModalOpen(true))
+ dispatch(resetParamState())
+ }, [dispatch])
+}
diff --git a/gcs/src/params.jsx b/gcs/src/params.jsx
index dc90c4b88..cc5e38cfd 100644
--- a/gcs/src/params.jsx
+++ b/gcs/src/params.jsx
@@ -22,9 +22,9 @@ const tailwindColors = resolveConfig(tailwindConfig).theme.colors
// Custom components, helpers, and data
import Layout from "./components/layout.jsx"
import NoDroneConnected from "./components/noDroneConnected.jsx"
-import AutopilotRebootModal from "./components/params/autopilotRebootModal.jsx"
import ParamsToolbar from "./components/params/paramsToolbar.jsx"
import { Row } from "./components/params/row.jsx"
+import { useRebootCallback } from "./helpers/useRebootCallback.js"
// Redux
import { useDispatch, useSelector } from "react-redux"
@@ -34,7 +34,6 @@ import { showErrorNotification } from "./helpers/notification.js"
import { selectConnectedToDrone } from "./redux/slices/droneConnectionSlice.js"
import {
emitExportParamsToFile,
- emitRebootAutopilot,
emitRefreshParams,
emitSetMultipleParams,
resetParamState,
@@ -46,7 +45,6 @@ import {
selectParamSearchValue,
selectShowModifiedParams,
selectShownParams,
- setAutoPilotRebootModalOpen,
setFetchingVars,
setHasFetchedOnce,
setLoadedFileName,
@@ -70,6 +68,7 @@ function cleanFloat(value, decimals = 5) {
export default function Params() {
const dispatch = useDispatch()
const connected = useSelector(selectConnectedToDrone)
+ const rebootCallback = useRebootCallback()
// Parameter states
const hasFetchedOnce = useSelector(selectHasFetchedOnce)
@@ -125,12 +124,6 @@ export default function Params() {
dispatch(setFetchingVars(true))
}
- function rebootCallback() {
- dispatch(emitRebootAutopilot())
- dispatch(setAutoPilotRebootModalOpen(true))
- dispatch(resetParamState())
- }
-
async function saveParamsToFile() {
const options = {
title: "Save parameters to a file",
@@ -208,7 +201,6 @@ export default function Params() {
return (
-
{connected ? (