diff --git a/public/translations/de.json b/public/translations/de.json
index aa65ce17..b06de27b 100644
--- a/public/translations/de.json
+++ b/public/translations/de.json
@@ -471,6 +471,7 @@
"incident_detected": "Ein Sicherheitsvorfall wurde entdeckt! Bitte überprüfe deine Logs!"
},
"server": {
+ "boxineDisabled": "Boxine/Toniecloud ist derzeit deaktiviert. Aktiviere die Einstellung 'Cloud enabled', um die Verbindung zu Boxine/Toniecloud wiederherzustellen.",
"boxineStatusOffline": "Nicht mit Boxine/Toniecloud verbunden",
"boxineStatusOnline": "Mit Boxine/Toniecloud verbunden",
"teddycloudStatusOffline": "TeddyCloud Server offline",
diff --git a/public/translations/en.json b/public/translations/en.json
index 4234e366..22f1cb7e 100644
--- a/public/translations/en.json
+++ b/public/translations/en.json
@@ -471,6 +471,7 @@
"incident_detected": "Security Incident Detected! Please check your logs!"
},
"server": {
+ "boxineDisabled": "Boxine/Toniecloud is currently disabled. Enable setting 'Cloud enabled' to reconnect to Boxine/Toniecloud.",
"boxineStatusOffline": "Not connected to Boxine/Toniecloud",
"boxineStatusOnline": "Connected to Boxine/Toniecloud",
"teddycloudStatusOffline": "Teddycloud server offline",
diff --git a/public/translations/es.json b/public/translations/es.json
index 95cab9c8..729e74f1 100644
--- a/public/translations/es.json
+++ b/public/translations/es.json
@@ -471,6 +471,7 @@
"incident_detected": "¡Incidente de seguridad detectado! ¡Por favor, revisa tus registros!"
},
"server": {
+ "boxineDisabled": "Boxine/Toniecloud está actualmente desactivado. Activa la opción 'Cloud enabled' para volver a conectarte a Boxine/Toniecloud.",
"boxineStatusOffline": "No conectado a Boxine/Toniecloud",
"boxineStatusOnline": "Conectado a Boxine/Toniecloud",
"teddycloudStatusOffline": "Servidor de Teddycloud desconectado",
diff --git a/public/translations/fr.json b/public/translations/fr.json
index 825723ce..5c20bf4b 100644
--- a/public/translations/fr.json
+++ b/public/translations/fr.json
@@ -471,6 +471,7 @@
"incident_detected": "Incident de sécurité détecté ! Veuillez vérifier vos journaux !"
},
"server": {
+ "boxineDisabled": "Boxine/Toniecloud est actuellement désactivé. Active le paramètre 'Cloud enabled' pour te reconnecter à Boxine/Toniecloud.",
"boxineStatusOffline": "Non connecté à Boxine/Toniecloud",
"boxineStatusOnline": "Connecté à Boxine/Toniecloud",
"teddycloudStatusOffline": "Serveur TeddyCloud hors ligne",
diff --git a/src/App.tsx b/src/App.tsx
index 706bdd70..e4870bfc 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -39,6 +39,7 @@ import { SystemSoundsPage } from "./pages/tonies/SystemSoundsPage";
import { TonieAudioPlaylistsPage } from "./pages/tonies/TonieAudioPlaylistsPage";
import { ToniesPage } from "./pages/tonies/ToniesPage";
import { detectColorScheme } from "./utils/browserUtils";
+import { TeddyCloudProvider } from "./utils/TeddyCloudContext";
function App() {
const { defaultAlgorithm, darkAlgorithm } = theme;
@@ -101,68 +102,76 @@ function App() {
},
}}
>
-
-
-
-
-
-
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- }
- />
- } />
- }
- />
- }
- />
- } />
- }
- />
- }
- />
- } />
- } />
- } />
- } />
- } />
- } />
- }
- />
- } />
- } />
- } />
- } />
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+ } />
+ }
+ />
+ }
+ />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ }
+ />
+ }
+ />
+ } />
+ } />
+ } />
+
+
+
+
+
+
+
+
);
}
diff --git a/src/components/form/CertificatesDragAndDrop.tsx b/src/components/form/CertificatesDragAndDrop.tsx
index ecda8921..e0996ff1 100644
--- a/src/components/form/CertificatesDragAndDrop.tsx
+++ b/src/components/form/CertificatesDragAndDrop.tsx
@@ -4,11 +4,13 @@ import { InboxOutlined } from "@ant-design/icons";
import { ApiUploadCertPostRequest, TeddyCloudApi } from "../../api";
import { defaultAPIConfig } from "../../config/defaultApiConfig";
+import { useTeddyCloud } from "../../utils/TeddyCloudContext";
const api = new TeddyCloudApi(defaultAPIConfig());
export const CertificateDragNDrop: React.FC<{ overlay?: string }> = ({ overlay }) => {
const { t } = useTranslation();
+ const { setFetchCloudStatus } = useTeddyCloud();
const handleUpload = async (file: UploadFile) => {
const formData = new FormData();
@@ -35,6 +37,7 @@ export const CertificateDragNDrop: React.FC<{ overlay?: string }> = ({ overlay }
filename: file.name,
})
);
+ setFetchCloudStatus((prev) => !prev);
} catch (err) {
message.error(
t("settings.certificates.uploadFailed", {
diff --git a/src/components/form/SwitchField.tsx b/src/components/form/SwitchField.tsx
index 95596e77..b2466845 100644
--- a/src/components/form/SwitchField.tsx
+++ b/src/components/form/SwitchField.tsx
@@ -6,6 +6,7 @@ import { useField } from "formik";
import { TeddyCloudApi } from "../../api";
import { defaultAPIConfig } from "../../config/defaultApiConfig";
+import { useTeddyCloud } from "../../utils/TeddyCloudContext";
type SwitchFieldProps = {
name: string;
@@ -21,6 +22,7 @@ type SwitchFieldProps = {
const SwitchField = (props: SwitchFieldProps & SwitchProps) => {
const { t } = useTranslation();
+ const { setFetchCloudStatus } = useTeddyCloud();
const { name, label, valueConverter, description, overlayed: initialOverlayed, overlayId, ...switchProps } = props;
const [field, meta, { setValue }] = useField(name!);
const [overlayed, setOverlayed] = useState(initialOverlayed);
@@ -97,6 +99,11 @@ const SwitchField = (props: SwitchFieldProps & SwitchProps) => {
triggerWriteConfig();
message.success(t("settings.saved"));
})
+ .then(() => {
+ if (name === "cloud.enabled") {
+ setFetchCloudStatus((prev) => !prev);
+ }
+ })
.catch((e) => {
message.error("Error while saving config to file.");
});
diff --git a/src/components/header/ServerStatus.tsx b/src/components/header/ServerStatus.tsx
index 52ee19c4..939f1995 100644
--- a/src/components/header/ServerStatus.tsx
+++ b/src/components/header/ServerStatus.tsx
@@ -1,21 +1,35 @@
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Space, Tag, Tooltip } from "antd";
-import { CheckCircleOutlined, CloseCircleOutlined } from "@ant-design/icons";
+import { CheckCircleOutlined, CloseCircleOutlined, LockOutlined } from "@ant-design/icons";
import { defaultAPIConfig } from "../../config/defaultApiConfig";
-import { BoxineApi, BoxineForcedApi } from "../../api";
+import { BoxineApi, BoxineForcedApi, TeddyCloudApi } from "../../api";
import { HiddenDesktop, HiddenMobile } from "../StyledComponents";
+import { useTeddyCloud } from "../../utils/TeddyCloudContext";
const api = new BoxineApi(defaultAPIConfig());
const api2 = new BoxineForcedApi(defaultAPIConfig());
+const apiTC = new TeddyCloudApi(defaultAPIConfig());
export const ServerStatus = () => {
const { t } = useTranslation();
+ const { fetchCloudStatus } = useTeddyCloud();
const [boxineStatus, setBoxineStatus] = useState(false);
+ const [boxineEnabledStatus, setBoxineEnabledStatus] = useState(true);
const [teddyStatus, setTeddyStatus] = useState(false);
+ const fetchBoxineEnabledStatus = async () => {
+ try {
+ const cloudEnabled = await apiTC.apiGetTeddyCloudSettingRaw("cloud.enabled");
+ setBoxineEnabledStatus((await cloudEnabled.text()) === "true");
+ } catch (err) {
+ console.log("Something went wrong getting cloud.enabled.");
+ setBoxineEnabledStatus(false);
+ }
+ };
+
const fetchTime = async () => {
try {
const timeRequest = (await api.v1TimeGet()) as String;
@@ -25,27 +39,58 @@ export const ServerStatus = () => {
} catch (e) {
setTeddyStatus(false);
}
- try {
- const timeRequest2 = (await api2.reverseV1TimeGet()) as String;
- if (timeRequest2.length === 10) {
- setBoxineStatus(true);
+ if (boxineEnabledStatus) {
+ try {
+ const timeRequest2 = (await api2.reverseV1TimeGet()) as String;
+
+ if (timeRequest2.length === 10) {
+ setBoxineStatus(true);
+ }
+ } catch (e) {
+ setBoxineStatus(false);
}
- } catch (e) {
- setBoxineStatus(false);
}
};
useEffect(() => {
+ fetchBoxineEnabledStatus();
fetchTime();
}, []);
+ useEffect(() => {
+ fetchBoxineEnabledStatus();
+ fetchTime();
+ }, [fetchCloudStatus]);
+
+ useEffect(() => {
+ fetchTime();
+ }, [boxineEnabledStatus]);
+
return (
-
+
: }
- color={boxineStatus ? "#87d068" : "#f50"}
+ icon={
+ boxineEnabledStatus ? (
+ boxineStatus ? (
+
+ ) : (
+
+ )
+ ) : (
+
+ )
+ }
+ color={boxineEnabledStatus ? (boxineStatus ? "#87d068" : "#f50") : "#faad14"}
bordered={false}
style={{ cursor: "help", color: "#001529" }}
>
diff --git a/src/pages/tonieboxes/boxsetup/esp32/ESP32BoxFlashingPage.tsx b/src/pages/tonieboxes/boxsetup/esp32/ESP32BoxFlashingPage.tsx
index 405d2eff..018ba21a 100644
--- a/src/pages/tonieboxes/boxsetup/esp32/ESP32BoxFlashingPage.tsx
+++ b/src/pages/tonieboxes/boxsetup/esp32/ESP32BoxFlashingPage.tsx
@@ -33,6 +33,7 @@ import ConfirmationDialog from "../../../../components/utils/ConfirmationDialog"
import AvailableBoxesModal, { connectESP32Explanation } from "../../../../components/tonieboxes/boxSetup/CommonContent";
import DotAnimation from "../../../../components/utils/DotAnimation";
import { isWebSerialSupported } from "../../../../utils/checkWebSerialSupport";
+import { useTeddyCloud } from "../../../../utils/TeddyCloudContext";
const api = new TeddyCloudApi(defaultAPIConfig());
@@ -72,6 +73,7 @@ const { Step } = Steps;
export const ESP32BoxFlashingPage = () => {
const { t } = useTranslation();
+ const { setFetchCloudStatus } = useTeddyCloud();
const navigate = useNavigate();
const currentLanguage = i18n.language;
@@ -863,6 +865,7 @@ export const ESP32BoxFlashingPage = () => {
file: state.filename,
})
);
+ setFetchCloudStatus((prev) => !prev);
} else if (!response.ok && response.status === 409) {
hideLoading();
const errorMessage = await response.text();
diff --git a/src/utils/TeddyCloudContext.tsx b/src/utils/TeddyCloudContext.tsx
new file mode 100644
index 00000000..61be9f71
--- /dev/null
+++ b/src/utils/TeddyCloudContext.tsx
@@ -0,0 +1,29 @@
+import { createContext, useContext, useState, ReactNode, Dispatch, SetStateAction } from "react";
+
+interface TeddyCloudContextType {
+ fetchCloudStatus: boolean;
+ setFetchCloudStatus: Dispatch>;
+}
+
+const TeddyCloudContext = createContext({
+ fetchCloudStatus: false,
+ setFetchCloudStatus: () => {},
+});
+
+interface TeddyCloudProviderProps {
+ children: ReactNode;
+}
+
+export function TeddyCloudProvider({ children }: TeddyCloudProviderProps) {
+ const [fetchCloudStatus, setFetchCloudStatus] = useState(false);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useTeddyCloud() {
+ return useContext(TeddyCloudContext);
+}