diff --git a/app/src/components/Common.js b/app/src/components/Common.js
index 7c34ba4c..f128eb29 100644
--- a/app/src/components/Common.js
+++ b/app/src/components/Common.js
@@ -19,6 +19,7 @@ import {
useCPUTemperature,
useDirectories,
useHotspot,
+ useLoad,
useSearchDirectories,
useSearchOrder,
useSettings,
@@ -952,25 +953,38 @@ export function HotspotStatusIcon() {
>
}
-export function CPUTemperatureIcon({size = 'large'}) {
+export function CPUTemperatureIcon({size = 'large', fallback = null}) {
// Returns an Icon only if temperature is too high.
- const {temperature, high_temperature, critical_temperature} = useCPUTemperature();
+ const {temperature, highTemperature, criticalTemperature} = useCPUTemperature();
- if (temperature === null || temperature < high_temperature) {
+ if (temperature === null || temperature < highTemperature) {
// Temperature is not a problem.
- return null;
+ return fallback;
}
- let icon;
- if (temperature >= critical_temperature) {
- icon = ;
- } else if (temperature >= high_temperature) {
- icon = ;
- }
+ let icon = temperature >= criticalTemperature ?
+
+ : ;
+ icon = {icon};
return
}
+export function SystemLoadIcon({size = 'large', fallback = null}) {
+ const {minute_1, mediumLoad, highLoad} = useLoad();
+
+ if (!mediumLoad && !highLoad) {
+ return fallback;
+ }
+
+ // Only return the icon if the load is not low.
+ const color = highLoad ? 'red' : 'yellow';
+ let icon =
+
+ ;
+ return
+}
+
export function useTitle(title) {
const documentDefined = typeof document !== 'undefined';
const originalTitle = React.useRef(documentDefined ? document.title : null);
diff --git a/app/src/components/Common.test.js b/app/src/components/Common.test.js
index 6a33fd62..9e316de4 100644
--- a/app/src/components/Common.test.js
+++ b/app/src/components/Common.test.js
@@ -3,6 +3,14 @@ import {getByTestId, queryByTestId, render, screen} from '@testing-library/react
import {CPUTemperatureIcon, DisableDownloadsToggle} from "./Common";
import {StatusContext} from "../contexts/contexts";
import {startDownloads} from "../components/Common";
+import {BrowserRouter} from "react-router-dom";
+
+const mockedUseHref = jest.fn();
+
+jest.mock("react-router-dom", () => ({
+ ...(jest.requireActual("react-router-dom")),
+ useHref: () => mockedUseHref
+}));
test('DownloadsToggle is off when loading', async () => {
const statusValue = {status: null, fetchStatus: null};
@@ -58,7 +66,9 @@ test('DownloadsToggle is on if downloading is On', async () => {
test('CPUTemperatureIcon high', async () => {
const statusValue = {status: {cpu_info: {temperature: 80, high_temperature: 75, critical_temperature: 90}}};
const {container} = render(
-
+
+
+
);
const icon = getByTestId(container, 'cpuTemperatureIcon');
@@ -69,7 +79,9 @@ test('CPUTemperatureIcon high', async () => {
test('CPUTemperatureIcon critical', async () => {
const statusValue = {status: {cpu_info: {temperature: 100, high_temperature: 75, critical_temperature: 90}}};
const {container} = render(
-
+
+
+
);
const icon = getByTestId(container, 'cpuTemperatureIcon');
diff --git a/app/src/components/Nav.js b/app/src/components/Nav.js
index e5e58342..7e6743d1 100644
--- a/app/src/components/Nav.js
+++ b/app/src/components/Nav.js
@@ -1,9 +1,9 @@
import React from "react";
import {NavLink} from "react-router-dom";
import {Dropdown, Menu} from "semantic-ui-react";
-import {Media, StatusContext, ThemeContext} from "../contexts/contexts";
+import {Media, ThemeContext} from "../contexts/contexts";
import Icon from "semantic-ui-react/dist/commonjs/elements/Icon";
-import {DarkModeToggle, HotspotStatusIcon, NAME, CPUTemperatureIcon} from "./Common";
+import {CPUTemperatureIcon, DarkModeToggle, HotspotStatusIcon, NAME, SystemLoadIcon} from "./Common";
import {ShareButton} from "./Share";
import {useWROLMode} from "../hooks/customHooks";
@@ -66,8 +66,12 @@ export function NavBar() {
const homeLink =
{topNavText}
;
+
+ // Display the temperature icon first because it can cause the system to throttle.
+ const warningIcon = }/>
+
const icons =
-
+ {warningIcon}
diff --git a/app/src/hooks/customHooks.js b/app/src/hooks/customHooks.js
index 6623ef58..47a5d358 100644
--- a/app/src/hooks/customHooks.js
+++ b/app/src/hooks/customHooks.js
@@ -737,11 +737,43 @@ export const useStatusFlag = (flag) => {
export const useCPUTemperature = () => {
const {status} = React.useContext(StatusContext);
- const temperature = status && status['cpu_info'] ? status['cpu_info']['temperature'] : 0;
- const high_temperature = status && status['cpu_info'] ? status['cpu_info']['high_temperature'] : 75;
- const critical_temperature = status && status['cpu_info'] ? status['cpu_info']['critical_temperature'] : 85;
+ let temperature = 0;
+ let highTemperature = 75;
+ let criticalTemperature = 85;
- return {temperature, high_temperature, critical_temperature}
+ if (status && status['cpu_info']) {
+ temperature = status['cpu_info']['temperature'];
+ highTemperature = status['cpu_info']['high_temperature'];
+ criticalTemperature = status['cpu_info']['critical_temperature'];
+ }
+
+ return {temperature, highTemperature, criticalTemperature}
+}
+
+export const useLoad = () => {
+ const {status} = React.useContext(StatusContext);
+ let minute_1;
+ let minute_5;
+ let minute_15;
+ let mediumLoad = false;
+ let highLoad = false;
+ let cores;
+
+ if (status && status['load']) {
+ minute_1 = status['load']['minute_1'];
+ minute_5 = status['load']['minute_5'];
+ minute_15 = status['load']['minute_15'];
+
+ cores = status['cpu_info']['cores'];
+ const quarter = cores / 4;
+ if (cores && minute_1 >= (quarter * 3)) {
+ highLoad = true;
+ } else if (cores && minute_1 >= (quarter * 2)) {
+ mediumLoad = true;
+ }
+ }
+
+ return {minute_1, minute_5, minute_15, mediumLoad, highLoad, cores};
}