diff --git a/app/src/components/Common.js b/app/src/components/Common.js index 5d738eb3..d7e64d25 100644 --- a/app/src/components/Common.js +++ b/app/src/components/Common.js @@ -15,6 +15,7 @@ import { import {Link, NavLink, useNavigate, useSearchParams} from "react-router-dom"; import Message from "semantic-ui-react/dist/commonjs/collections/Message"; import { + useCPUTemperature, useDirectories, useHotspot, useSearchDirectories, @@ -920,6 +921,25 @@ export function HotspotStatusIcon() { } +export function CPUTemperatureIcon({size = 'large'}) { + // Returns an Icon only if temperature is too high. + const {temperature, high_temperature, critical_temperature} = useCPUTemperature(); + + if (temperature < high_temperature) { + // Temperature is not a problem. + return null; + } + + let icon; + if (temperature >= critical_temperature) { + icon = ; + } else if (temperature >= high_temperature) { + 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 97f357d6..6a33fd62 100644 --- a/app/src/components/Common.test.js +++ b/app/src/components/Common.test.js @@ -1,6 +1,6 @@ import React from "react"; -import {getByTestId, render, screen} from '@testing-library/react'; -import {DisableDownloadsToggle} from "./Common"; +import {getByTestId, queryByTestId, render, screen} from '@testing-library/react'; +import {CPUTemperatureIcon, DisableDownloadsToggle} from "./Common"; import {StatusContext} from "../contexts/contexts"; import {startDownloads} from "../components/Common"; @@ -54,3 +54,35 @@ test('DownloadsToggle is on if downloading is On', async () => { const label = getByTestId(container, 'toggle-label'); expect(label).toHaveTextContent('Downloading Enabled'); }); + +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'); + expect(icon).toHaveClass('thermometer'); + expect(icon).toHaveClass('half'); +}); + +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'); + expect(icon).toHaveClass('thermometer'); + expect(icon).not.toHaveClass('half'); +}); + +test('CPUTemperatureIcon hidden', async () => { + const statusValue = {status: {cpu_info: {temperature: 35, high_temperature: 75, critical_temperature: 90}}}; + const {container} = render( + + ); + + const icon = queryByTestId(container, 'cpuTemperatureIcon'); + expect(icon).toBeNull(); +}); \ No newline at end of file diff --git a/app/src/components/Nav.js b/app/src/components/Nav.js index e453fa5f..e5e58342 100644 --- a/app/src/components/Nav.js +++ b/app/src/components/Nav.js @@ -3,7 +3,7 @@ import {NavLink} from "react-router-dom"; import {Dropdown, Menu} from "semantic-ui-react"; import {Media, StatusContext, ThemeContext} from "../contexts/contexts"; import Icon from "semantic-ui-react/dist/commonjs/elements/Icon"; -import {DarkModeToggle, HotspotStatusIcon, NAME} from "./Common"; +import {DarkModeToggle, HotspotStatusIcon, NAME, CPUTemperatureIcon} from "./Common"; import {ShareButton} from "./Share"; import {useWROLMode} from "../hooks/customHooks"; @@ -52,7 +52,7 @@ function MenuLink({link}) { } } -function NavIcon(props) { +function NavIconWrapper(props) { return
{props.children}
} @@ -67,9 +67,10 @@ export function NavBar() { {topNavText} ; const icons = - - - + + + + ; return <> diff --git a/app/src/components/admin/Status.js b/app/src/components/admin/Status.js index 873c95f3..7957f0ea 100644 --- a/app/src/components/admin/Status.js +++ b/app/src/components/admin/Status.js @@ -61,20 +61,16 @@ function DiskBandwidth({name, bytes_read_ps, bytes_write_ps}) { } -function CPUTemperatureStatistic({value, high_temperature, critical_temperature, ...props}) { - if (!value) { +function CPUTemperatureStatistic({temperature, high_temperature, critical_temperature, ...props}) { + if (!temperature) { return } - if (critical_temperature && critical_temperature === high_temperature) { - // Critical and high are equal, manually change it so high changes color before critical. - high_temperature = critical_temperature - 25; - } - if ((critical_temperature && value >= critical_temperature) || (!critical_temperature && value >= 75)) { + if ((critical_temperature && temperature >= critical_temperature) || (!critical_temperature && temperature >= 75)) { props['color'] = 'red'; - } else if ((high_temperature && value >= high_temperature) || (!high_temperature && value >= 55)) { + } else if ((high_temperature && temperature >= high_temperature) || (!high_temperature && temperature >= 55)) { props['color'] = 'orange'; } - return + return } export function BandwidthProgress({label = '', bytes, maxBytes, ...props}) { @@ -186,7 +182,7 @@ export function Status() { @@ -217,7 +213,7 @@ export function Status() { { return status && status['flags'] && status['flags'].indexOf(flag) >= 0; } +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; + + return {temperature, high_temperature, critical_temperature} +} + export const useVideoStatistics = () => { const [statistics, setStatistics] = useState({});