import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button, ColorPicker, Dropdown, DropdownType, EditableText, Group, NumberDropdown, Size, Toggle, ToggleType, Type } from 'browndash-components'; import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { BsGoogle } from 'react-icons/bs'; import { FaFillDrip, FaPalette } from 'react-icons/fa'; import { Doc } from '../../fields/Doc'; import { DashVersion } from '../../fields/DocSymbols'; import { BoolCast, Cast, StrCast } from '../../fields/Types'; import { addStyleSheet, addStyleSheetRule, Utils } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Networking } from '../Network'; import { MainViewModal } from '../views/MainViewModal'; import { GroupManager } from './GroupManager'; import './SettingsManager.scss'; import { undoBatch } from './UndoManager'; export enum ColorScheme { Dark = 'Dark', Light = 'Light', Custom = 'Custom', CoolBlue = 'CoolBlue', Cupcake = 'Cupcake', } export enum freeformScrollMode { Pan = 'pan', Zoom = 'zoom', } @observer export class SettingsManager extends React.Component<{}> { public static Instance: SettingsManager; static _settingsStyle = addStyleSheet(); @observable public isOpen = false; @observable private passwordResultText = ''; @observable private playgroundMode = false; @observable private curr_password = ''; @observable private new_password = ''; @observable private new_confirm = ''; @observable activeTab = 'Accounts'; @observable public static propertiesWidth: number = 0; @observable public static headerBarHeight: number = 0; constructor(props: {}) { super(props); SettingsManager.Instance = this; this.matchSystem(); window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { if (Doc.UserDoc().userThemeSystem) { if (window.matchMedia('(prefers-color-scheme: dark)').matches) this.changeColorScheme(ColorScheme.Dark); if (window.matchMedia('(prefers-color-scheme: light)').matches) this.changeColorScheme(ColorScheme.Light); } // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss) }); } matchSystem = () => { if (Doc.UserDoc().userThemeSystem) { if (window.matchMedia('(prefers-color-scheme: dark)').matches) this.changeColorScheme(ColorScheme.Dark); if (window.matchMedia('(prefers-color-scheme: light)').matches) this.changeColorScheme(ColorScheme.Light); } }; public close = action(() => (this.isOpen = false)); public open = action(() => (this.isOpen = true)); private googleAuthorize = action(() => GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true)); private changePassword = async () => { if (!(this.curr_password && this.new_password && this.new_confirm)) { runInAction(() => (this.passwordResultText = "Error: Hey, we're missing some fields!")); } else { const passwordBundle = { curr_pass: this.curr_password, new_pass: this.new_password, new_confirm: this.new_confirm }; const { error } = await Networking.PostToServer('/internalResetPassword', passwordBundle); runInAction(() => (this.passwordResultText = error ? 'Error: ' + error[0].msg + '...' : 'Password successfully updated!')); } }; @computed public static get userColor() { return StrCast(Doc.UserDoc().userColor); } @computed public static get userVariantColor() { return StrCast(Doc.UserDoc().userVariantColor); } @computed public static get userBackgroundColor() { return StrCast(Doc.UserDoc().userBackgroundColor); } @undoBatch selectUserMode = action((mode: string) => (Doc.noviceMode = mode === 'Novice')); @undoBatch changelayout_showTitle = action((e: React.ChangeEvent) => (Doc.UserDoc().layout_showTitle = (e.currentTarget as any).value ? 'title' : undefined)); @undoBatch changeFontFamily = action((font: string) => (Doc.UserDoc().fontFamily = font)); @undoBatch changeFontSize = action((val: number) => (Doc.UserDoc().fontSize = val)); @undoBatch switchUserBackgroundColor = action((color: string) => { Doc.UserDoc().userBackgroundColor = color; addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: `${color} !important` }); }); @undoBatch switchUserColor = action((color: string) => (Doc.UserDoc().userColor = color)); @undoBatch switchUserVariantColor = action((color: string) => (Doc.UserDoc().userVariantColor = color)); @undoBatch userThemeSystemToggle = action(() => { Doc.UserDoc().userThemeSystem = !Doc.UserDoc().userThemeSystem; this.matchSystem(); }); @undoBatch playgroundModeToggle = action(() => { this.playgroundMode = !this.playgroundMode; if (this.playgroundMode) { DocServer.Control.makeReadOnly(); addStyleSheetRule(SettingsManager._settingsStyle, 'topbar-inner-container', { background: 'red !important' }); } else Doc.CurrentUserEmail !== 'guest' && DocServer.Control.makeEditable(); }); @undoBatch @action changeColorScheme = action((scheme: string) => { Doc.UserDoc().userTheme = scheme; switch (scheme) { case ColorScheme.Light: this.switchUserColor('#323232'); this.switchUserBackgroundColor('#DFDFDF'); this.switchUserVariantColor('#BDDDF5'); break; case ColorScheme.Dark: this.switchUserColor('#DFDFDF'); this.switchUserBackgroundColor('#323232'); this.switchUserVariantColor('#4476F7'); break; case ColorScheme.CoolBlue: this.switchUserColor('#ADEAFF'); this.switchUserBackgroundColor('#060A15'); this.switchUserVariantColor('#3C51FF'); break; case ColorScheme.Cupcake: this.switchUserColor('#3BC7FF'); this.switchUserBackgroundColor('#fffdf7'); this.switchUserVariantColor('#FFD7F3'); break; case ColorScheme.Custom: break; } }); @computed get colorsContent() { const schemeMap = Array.from(Object.keys(ColorScheme)); const userTheme = StrCast(Doc.UserDoc().userTheme); return (