181 lines
5.2 KiB
TypeScript
181 lines
5.2 KiB
TypeScript
import React, {
|
|
FC, memo, useEffect, useCallback, useRef,
|
|
} from '../../../lib/teact/teact';
|
|
import { getActions, withGlobal } from '../../../global';
|
|
|
|
import { SettingsScreens, ThemeKey, UPLOADING_WALLPAPER_SLUG } from '../../../types';
|
|
import { ApiWallpaper } from '../../../api/types';
|
|
|
|
import { DARK_THEME_PATTERN_COLOR, DEFAULT_PATTERN_COLOR } from '../../../config';
|
|
import { throttle } from '../../../util/schedulers';
|
|
import { openSystemFilesDialog } from '../../../util/systemFilesDialog';
|
|
import { getAverageColor, getPatternColor, rgb2hex } from '../../../util/colors';
|
|
import { selectTheme } from '../../../global/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;
|
|
};
|
|
|
|
const SUPPORTED_TYPES = 'image/jpeg';
|
|
|
|
const runThrottled = throttle((cb) => cb(), 60000, true);
|
|
|
|
const SettingsGeneralBackground: FC<OwnProps & StateProps> = ({
|
|
isActive,
|
|
onScreenSelect,
|
|
onReset,
|
|
background,
|
|
isBlurred,
|
|
loadedWallpapers,
|
|
theme,
|
|
}) => {
|
|
const {
|
|
loadWallpapers,
|
|
uploadWallpaper,
|
|
setThemeSettings,
|
|
} = getActions();
|
|
|
|
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,
|
|
onBack: onReset,
|
|
});
|
|
|
|
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,
|
|
};
|
|
},
|
|
)(SettingsGeneralBackground));
|