TelegramPWA/src/components/left/settings/SettingsGeneralBackground.tsx
2021-08-27 21:05:46 +03:00

184 lines
5.5 KiB
TypeScript

import React, {
FC, memo, useEffect, useCallback, useRef,
} from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens, ThemeKey, UPLOADING_WALLPAPER_SLUG } from '../../../types';
import { ApiWallpaper } from '../../../api/types';
import { DARK_THEME_PATTERN_COLOR, DEFAULT_PATTERN_COLOR } from '../../../config';
import { pick } from '../../../util/iteratees';
import { throttle } from '../../../util/schedulers';
import { openSystemFilesDialog } from '../../../util/systemFilesDialog';
import { getAverageColor, getPatternColor, rgb2hex } from '../../../util/colors';
import { selectTheme } from '../../../modules/selectors';
import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack';
import ListItem from '../../ui/ListItem';
import Checkbox from '../../ui/Checkbox';
import Loading from '../../ui/Loading';
import WallpaperTile from './WallpaperTile';
import './SettingsGeneralBackground.scss';
type OwnProps = {
isActive?: boolean;
onScreenSelect: (screen: SettingsScreens) => void;
onReset: () => void;
};
type StateProps = {
background?: string;
isBlurred?: boolean;
loadedWallpapers?: ApiWallpaper[];
theme: ThemeKey;
};
type DispatchProps = Pick<GlobalActions, (
'loadWallpapers' | 'uploadWallpaper' | 'setThemeSettings'
)>;
const SUPPORTED_TYPES = 'image/jpeg';
const runThrottled = throttle((cb) => cb(), 60000, true);
const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
isActive,
onScreenSelect,
onReset,
background,
isBlurred,
loadedWallpapers,
theme,
loadWallpapers,
uploadWallpaper,
setThemeSettings,
}) => {
const themeRef = useRef<string>();
themeRef.current = theme;
// Due to the parent Transition, this component never gets unmounted,
// that's why we use throttled API call on every update.
useEffect(() => {
runThrottled(() => {
loadWallpapers();
});
}, [loadWallpapers]);
const handleFileSelect = useCallback((e: Event) => {
const { files } = e.target as HTMLInputElement;
if (files && files.length > 0) {
uploadWallpaper(files[0]);
}
}, [uploadWallpaper]);
const handleUploadWallpaper = useCallback(() => {
openSystemFilesDialog(SUPPORTED_TYPES, handleFileSelect, true);
}, [handleFileSelect]);
const handleSetColor = useCallback(() => {
onScreenSelect(SettingsScreens.GeneralChatBackgroundColor);
}, [onScreenSelect]);
const handleResetToDefault = useCallback(() => {
setThemeSettings({
theme,
background: undefined,
backgroundColor: undefined,
isBlurred: true,
patternColor: theme === 'dark' ? DARK_THEME_PATTERN_COLOR : DEFAULT_PATTERN_COLOR,
});
}, [setThemeSettings, theme]);
const handleWallPaperSelect = useCallback((slug: string) => {
setThemeSettings({ theme: themeRef.current, background: slug });
const currentWallpaper = loadedWallpapers && loadedWallpapers.find((wallpaper) => wallpaper.slug === slug);
if (currentWallpaper?.document.thumbnail) {
getAverageColor(currentWallpaper.document.thumbnail.dataUri)
.then((color) => {
const patternColor = getPatternColor(color);
const rgbColor = `#${rgb2hex(color)}`;
setThemeSettings({ theme: themeRef.current, backgroundColor: rgbColor, patternColor });
});
}
}, [loadedWallpapers, setThemeSettings]);
const handleWallPaperBlurChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setThemeSettings({ theme: themeRef.current, isBlurred: e.target.checked });
}, [setThemeSettings]);
const lang = useLang();
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.GeneralChatBackground);
const isUploading = loadedWallpapers?.[0] && loadedWallpapers[0].slug === UPLOADING_WALLPAPER_SLUG;
return (
<div className="SettingsGeneralBackground settings-content custom-scroll">
<div className="settings-item pt-3">
<ListItem
icon="camera-add"
className="mb-0"
disabled={isUploading}
onClick={handleUploadWallpaper}
>
{lang('UploadImage')}
</ListItem>
<ListItem
icon="colorize"
className="mb-0"
onClick={handleSetColor}
>
{lang('SetColor')}
</ListItem>
<ListItem icon="favorite" onClick={handleResetToDefault}>
{lang('ThemeResetToDefaults')}
</ListItem>
<Checkbox
label={lang('BackgroundBlurred')}
checked={Boolean(isBlurred)}
onChange={handleWallPaperBlurChange}
/>
</div>
{loadedWallpapers ? (
<div className="settings-wallpapers">
{loadedWallpapers.map((wallpaper) => (
<WallpaperTile
wallpaper={wallpaper}
theme={theme}
isSelected={background === wallpaper.slug}
onClick={handleWallPaperSelect}
/>
))}
</div>
) : (
<Loading />
)}
</div>
);
};
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const theme = selectTheme(global);
const { background, isBlurred } = global.settings.themes[theme] || {};
const { loadedWallpapers } = global.settings;
return {
background,
isBlurred,
loadedWallpapers,
theme,
};
},
(setGlobal, actions): DispatchProps => pick(actions, [
'loadWallpapers', 'uploadWallpaper', 'setThemeSettings',
]),
)(SettingsGeneralBackground));