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}; }