diff --git a/components/chart/HorizontalBarChart.tsx b/components/chart/HorizontalBarChart.tsx index ec74af24..757c1c5c 100644 --- a/components/chart/HorizontalBarChart.tsx +++ b/components/chart/HorizontalBarChart.tsx @@ -10,6 +10,12 @@ import { Legend, } from 'chart.js' import { convertToHumanReadable } from '../../lib/queueManager' +import { + GRAY_200, + GRAY_700, +} from '../../lib/colors' +import { useSelector } from 'react-redux' +import { RootState } from '../../store' ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) interface BarChartHorizontalProps { @@ -25,6 +31,8 @@ const BarChartHorizontal: FC = ({ titleText, numericTooltip, }) => { + const { theme } = useSelector((state: RootState) => state.darkTheme) + const options = { indexAxis: 'y' as const, elements: { @@ -62,6 +70,11 @@ const BarChartHorizontal: FC = ({ font: { size: 16, }, + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_200 + : GRAY_700, }, tooltip: { callbacks: { diff --git a/components/chart/HorizontalNoLabel.tsx b/components/chart/HorizontalNoLabel.tsx index 68e28695..1f3c1464 100644 --- a/components/chart/HorizontalNoLabel.tsx +++ b/components/chart/HorizontalNoLabel.tsx @@ -11,6 +11,12 @@ import { } from 'chart.js' import { getRandomColor } from '../../lib/queueManager' import ChartDataLabels from 'chartjs-plugin-datalabels' +import { + GRAY_200, + GRAY_700, +} from '../../lib/colors' +import { useSelector } from 'react-redux' +import { RootState } from '../../store' ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) @@ -20,13 +26,12 @@ interface BarChartHorizontalNoLabelsProps { queuedata: any } -// type Align = 'start' | 'center' | 'end' | 'left' | 'right' | 'top' | 'bottom' | number | ((context: any) => Align); - const BarChartHorizontalNoLabels: FC = ({ datasets, titleText, queuedata, }) => { + const { theme } = useSelector((state: RootState) => state.darkTheme) const validQueueData = queuedata || [] const queueDataMap: { [label: string]: any } = {} @@ -48,7 +53,6 @@ const BarChartHorizontalNoLabels: FC = ({ }, scales: { y: { - // display: false, display: true, beginAtZero: true, @@ -63,6 +67,11 @@ const BarChartHorizontalNoLabels: FC = ({ font: { size: 14, }, + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_200 + : GRAY_700, }, }, x: { @@ -91,6 +100,11 @@ const BarChartHorizontalNoLabels: FC = ({ font: { size: 16, }, + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_200 + : GRAY_700, }, datalabels: { color: 'white', diff --git a/components/chart/HorizontalNotStacked.tsx b/components/chart/HorizontalNotStacked.tsx index c8c68e7b..7007334c 100644 --- a/components/chart/HorizontalNotStacked.tsx +++ b/components/chart/HorizontalNotStacked.tsx @@ -9,6 +9,14 @@ import { Tooltip, Legend, } from 'chart.js' +import { + GRAY_200, + GRAY_300, + GRAY_600, + GRAY_700, +} from '../../lib/colors' +import { useSelector } from 'react-redux' +import { RootState } from '../../store' ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) interface BarChartHorizontalNotStackedProps { @@ -24,6 +32,7 @@ const BarChartHorizontalNotStacked: FC = ({ tickColor, titleText }) => { + const { theme } = useSelector((state: RootState) => state.darkTheme) const options = { indexAxis: 'y' as const, responsive: true, @@ -45,7 +54,11 @@ const BarChartHorizontalNotStacked: FC = ({ }, ticks: { stepSize: 1, - color: tickColor, + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_200 + : GRAY_700, font:{ size:14, }, @@ -74,6 +87,11 @@ const BarChartHorizontalNotStacked: FC = ({ font: { size: 16, }, + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_300 + : GRAY_600, }, }, } diff --git a/components/chart/HorizontalWithTitle.tsx b/components/chart/HorizontalWithTitle.tsx index a9e98c8e..3f6f34ff 100644 --- a/components/chart/HorizontalWithTitle.tsx +++ b/components/chart/HorizontalWithTitle.tsx @@ -9,21 +9,28 @@ import { Tooltip, Legend, } from 'chart.js' +import { useSelector } from 'react-redux' +import { RootState } from '../../store' +import { + GRAY_200, + GRAY_300, + GRAY_600, + GRAY_700, +} from '../../lib/colors' ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) interface BarChartHorizontalWithTitleProps { labels: string[] datasets: any[] - tickColor?: string titleText?: string } const BarChartHorizontalWithTitle: FC = ({ labels, datasets, - tickColor, titleText, }) => { + const { theme } = useSelector((state: RootState) => state.darkTheme) const options = { indexAxis: 'y' as const, responsive: true, @@ -45,7 +52,11 @@ const BarChartHorizontalWithTitle: FC = ({ }, ticks: { stepSize: 2, - color: tickColor, + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_200 + : GRAY_700, font: { size: 14, }, @@ -62,6 +73,13 @@ const BarChartHorizontalWithTitle: FC = ({ legend: { position: 'bottom' as const, display: false, + labels: { + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_300 + : GRAY_600, + }, }, title: { display: true, @@ -69,6 +87,11 @@ const BarChartHorizontalWithTitle: FC = ({ font: { size: 16, }, + color: + theme === 'dark' || + (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) + ? GRAY_300 + : GRAY_600, padding: { top: 0, bottom: 4, diff --git a/components/common/ProfilePicture/GravatarIconDrawerContent.tsx b/components/common/ProfilePicture/GravatarIconDrawerContent.tsx index 4e21717c..d0364a75 100644 --- a/components/common/ProfilePicture/GravatarIconDrawerContent.tsx +++ b/components/common/ProfilePicture/GravatarIconDrawerContent.tsx @@ -7,11 +7,10 @@ import { Button } from '../Button' import { useState, useRef } from 'react' import { closeSideDrawer } from '../../../lib/utils' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCircleXmark, faSave, faSearch } from '@fortawesome/free-solid-svg-icons' +import { faCircleXmark, faSearch } from '@fortawesome/free-solid-svg-icons' import { SideDrawerCloseIcon } from '../SideDrawerCloseIcon' import { t } from 'i18next' import { TextInput } from '../TextInput' -import gravatar from 'gravatar' import { Avatar } from '../Avatar' import { uploadProfilePicture } from '../../../lib/profilePicture' import { useSelector } from 'react-redux' @@ -169,7 +168,7 @@ export const GravatarIconDrawerContent = forwardRef<
-
diff --git a/components/common/ProfilePicture/SelectProfilePictureDrawerContent.tsx b/components/common/ProfilePicture/SelectProfilePictureDrawerContent.tsx index 3d44bdeb..8cea1e9a 100644 --- a/components/common/ProfilePicture/SelectProfilePictureDrawerContent.tsx +++ b/components/common/ProfilePicture/SelectProfilePictureDrawerContent.tsx @@ -73,14 +73,11 @@ export const SelectProfilePictureDrawerContent = forwardRef< const reader = new FileReader() reader.readAsDataURL(file) + //to prevent local storage from becoming full reader.onloadend = () => { - setSelectedFileBase64(reader.result) - setPreviewImage(reader.result) + resizeImage(reader.result as string, 30 * 1024) } - if (selectedFileBase64) { - setPreviewImage(selectedFileBase64) - } if (errorUpload) { setErrorUpload(false) } @@ -98,9 +95,10 @@ export const SelectProfilePictureDrawerContent = forwardRef< const reader = new FileReader() reader.readAsDataURL(file) + + //to prevent local storage from becoming full reader.onloadend = () => { - setSelectedFileBase64(reader.result) - setPreviewImage(reader.result) + resizeImage(reader.result as string, 30 * 1024) } if (errorUpload) { @@ -111,6 +109,67 @@ export const SelectProfilePictureDrawerContent = forwardRef< } } + // Function to resize the image + function resizeImage(dataUrl: string, maxFileSize: number) { + const img = new Image() + img.src = dataUrl + + img.onload = () => { + const canvas = document.createElement('canvas') + const ctx = canvas.getContext('2d') + + // Set the maximum width and height for the image + const MAX_WIDTH = 800 + const MAX_HEIGHT = 800 + + let width = img.width + let height = img.height + + if (width > height) { + if (width > MAX_WIDTH) { + height = (height * MAX_WIDTH) / width + width = MAX_WIDTH + } + } else { + if (height > MAX_HEIGHT) { + width = (width * MAX_HEIGHT) / height + height = MAX_HEIGHT + } + } + + canvas.width = width + canvas.height = height + + ctx?.drawImage(img, 0, 0, width, height) + + // Reduce the quality of the image + canvas.toBlob( + (blob) => { + if (blob) { + const reader = new FileReader() + reader.readAsDataURL(blob) + + reader.onloadend = () => { + const compressedBase64 = reader.result as string + const size = blob.size + + // Check if the size of the image is less than the maximum size + if (size <= maxFileSize) { + setSelectedFileBase64(compressedBase64) + setPreviewImage(compressedBase64) + } else { + // If the size of the image is greater than the maximum size, compress it again + resizeImage(compressedBase64, maxFileSize) + } + } + } + }, + 'image/jpeg', + 0.7, + ) + } + } + // Check if file is an image function isImageFile(file: File): boolean { const allowedImageTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'] @@ -169,15 +228,14 @@ export const SelectProfilePictureDrawerContent = forwardRef<