@material-ui/icons#NoteAdd TypeScript Examples

The following examples show how to use @material-ui/icons#NoteAdd. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SettingsPage.tsx    From shadowsocks-electron with GNU General Public License v3.0 4 votes vote down vote up
SettingsPage: React.FC = () => {
  const styles = useStyles();
  const { t } = useTranslation();

  const dispatch = useTypedDispatch();
  const [form] = Form.useForm();
  const settings = useTypedSelector(state => state.settings);
  const config = useTypedSelector(state => state.config);
  // const [aclVisible, setAclVisible] = useState(false);
  const inputFileRef = React.useRef<HTMLInputElement>(null);
  const [DialogConfirm, showDialog, closeDialog] = useDialogConfirm();
  const settingKeys = useRef(
    ['localPort', 'pacPort', 'gfwListUrl',
    'httpProxy', 'autoLaunch', 'fixedMenu',
    'darkMode', 'autoTheme', 'verbose', 'autoHide']
  );
  const cachedRef = useRef<any>(null);

  const enqueueSnackbar = (message: SnackbarMessage, options: Notification) => {
    dispatch(enqueueSnackbarAction(message, options))
  };

  useEffect(() => {
    dispatch<any>(getStartupOnBoot());
  }, [dispatch]);

  /* dark mode */
  useEffect(() => {
    if (
      (persistStore.get('darkMode') === 'true' && !settings.darkMode) ||
      (persistStore.get('darkMode') === 'false' && !!settings.darkMode) ||
      (persistStore.get('darkMode') === undefined && !!settings.darkMode)
    ) {
      dispatchEvent({
        type: 'theme:update',
        payload: {
          shouldUseDarkColors: !!settings.darkMode
        }
      });
    }
  }, [settings.darkMode]);

  /* restoreFromFile */
  useMemo(() => {
    const obj = {};
    if (cachedRef.current) {
      settingKeys.current.forEach(key => {
        if (cachedRef.current[key] !== (settings as any)[key]) {
          if (key === 'httpProxy') {
            Object.assign(obj, {
              httpProxy: settings.httpProxy.enable,
              httpProxyPort: settings.httpProxy.port,
            });
          } else {
            Object.assign(obj, { [key]: (settings as any)[key] });
          }
        }
      });
      form.setFieldsValue(obj);
    }
    cachedRef.current = settingKeys.current.reduce(
      (pre, cur) => Object.assign(pre, { [cur]: (settings as any)[cur] }),
      {}
    );
  }, settingKeys.current.map(key => (settings as any)[key]));

  const backupConfiguration = () => {
    return backupConfigurationToFile({
      config,
      settings
    });
  };

  const restoreConfiguration = () => {
    dispatch<any>(restoreConfigurationFromFile({
      success: t('the_recovery_is_successful'),
      error: {
        default: t('the_recovery_is_failed'),
        404: t('user_canceled')
      }
    }));
  }

  const checkPortValid = (parsedValue: number) => {
    if (!(parsedValue && parsedValue > 1024 && parsedValue <= 65535)) {
          return Promise.reject(t("invalid_port_range"));
    }
    return Promise.resolve();
  };

  const checkPortSame = () => {
    const localPort = +form.getFieldValue('localPort');
    const pacPort = +form.getFieldValue('pacPort');
    const httpPort = +form.getFieldValue('httpProxyPort');
    const num = localPort ^ pacPort ^ httpPort;
    if (num === localPort || num === pacPort || num === httpPort) {
      return Promise.reject(t("the_same_port_is_not_allowed"));
    }
    return Promise.resolve();
  };

  const handleOpenLog = async () => {
    await MessageChannel.invoke('main', 'service:desktop', {
      action: 'openLogDir',
      params: {}
    });
  };

  const handleOpenProcessManager = async () => {
    await MessageChannel.invoke('main', 'service:desktop', {
      action: 'openProcessManager',
      params: {}
    });
  };

  const handleReset = () => {
    dispatch({
      type: CLEAR_STORE
    } as any);
    closeDialog();
    MessageChannel.invoke('main', 'service:main', {
      action: 'stopClient',
      params: {}
    });
    enqueueSnackbar(t('cleared_all_data'), { variant: 'success' });
  };

  const handleAlertDialogOpen = () => {
    showDialog(t('reset_all_data'), t('reset_all_data_tips'));
  };

  const handleAlertDialogClose = () => {
    closeDialog();
  };

  const reGeneratePacFileWithFile = () => {
    inputFileRef.current?.click();
  }

  const reGeneratePacFileWithUrl = () => {
    reGeneratePacFile({
      url: settings.gfwListUrl
    });
  }

  const onGFWListFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = (e: any) => {
        const text = e.target.result;
        if (text) {
          reGeneratePacFile({
            text: text
          });
        }
      };
      reader.readAsText(file);
    }
  }

  const reGeneratePacFile = (params: { url?: string, text?: string }) => {
    dispatch<any>(setStatus('waiting', true));
    MessageChannel.invoke('main', 'service:main', {
      action: 'reGeneratePacFile',
      params
    }).then((rsp) => {
      setTimeout(() => { dispatch<any>(setStatus('waiting', false)); }, 1e3);
      if (rsp.code === 200) {
        enqueueSnackbar(t('successful_operation'), { variant: 'success' });
      } else {
        enqueueSnackbar(t('failed_to_download_file'), { variant: 'error' });
      }
    });
  }

  const onLangChange = (e: React.ChangeEvent<{ name?: string | undefined, value: unknown; }>) => {
    if (persistStore.get('lang') === e.target.value) return;
    persistStore.set('lang', e.target.value as string);
    MessageChannel.invoke('main', 'service:desktop', {
      action: 'reloadMainWindow',
      params: {}
    });
    MessageChannel.invoke('main', 'service:desktop', {
      action: 'setLocale',
      params: getFirstLanguage(e.target.value as string)
    });
  }

  const onAutoThemeChange = (e: React.ChangeEvent<{ name?: string | undefined, checked: boolean; }>) => {
    const checked = e.target.checked;
    MessageChannel.invoke('main', 'service:theme', {
      action: checked ? 'listenForUpdate' : 'unlistenForUpdate',
      params: {}
    }).then(rsp => {
      if (rsp.code === 200) {
        persistStore.set('autoTheme', checked ? 'true' : 'false');
      }
    });
    MessageChannel.invoke('main', 'service:theme', {
      action: 'getSystemThemeInfo',
      params: {}
    })
    .then(rsp => {
      if (rsp.code === 200) {
        dispatchEvent({
          type: 'theme:update',
          payload: rsp.result
        });
        if (!checked) {
          form.setFieldsValue({
            darkMode: rsp.result?.shouldUseDarkColors
          });
        }
      }
    });

  }

  const checkPortField = (rule: any, value: any) => {
    return Promise.all([checkPortSame(), checkPortValid(value)]);
  };

  const onFieldChange = (changedFields: { [key: string]: any }, allFields: { [key: string]: any }) => {
    const keys = Object.keys(changedFields);
    keys.forEach((key) => {
      let value = changedFields[key];
      form.validateFields([key]).then(() => {
        switch (key) {
          case 'httpProxy':
            value = {
              ...settings.httpProxy,
              enable: value
            };
            dispatch(setSetting<'httpProxy'>(key, value))
            setHttpAndHttpsProxy({ ...value, type: 'http', proxyPort: settings.localPort });
            return;
          case 'httpProxyPort':
            value = {
              ...settings.httpProxy,
              port: value
            };
            dispatch(setSetting<'httpProxy'>('httpProxy', value))
            setHttpAndHttpsProxy({ ...value, type: 'http', proxyPort: settings.localPort });
            return;
          case 'acl':
            dispatch(setSetting<'acl'>(key, {
              ...settings.acl,
              text: value
            }));
            return;
          case 'autoLaunch':
            dispatch<any>(setStartupOnBoot(value));
            return;
          case 'darkMode':
            dispatchEvent({
              type: 'theme:update',
              payload: {
                shouldUseDarkColors: value
              }
            });
            break;
          default:
            break;
        }

        dispatch(setSetting<any>(key, value));
      }).catch((reason: { errorFields: { errors: string[] }[] }) => {
        enqueueSnackbar(reason?.errorFields?.map(item => item.errors.join()).join(), { variant: 'error' });
      });
    });
  }

  return (
    <Container className={styles.container}>
      <Form
        form={form}
        initialValues={
          {
            localPort: settings.localPort,
            pacPort: settings.pacPort,
            gfwListUrl: settings.gfwListUrl,
            httpProxy: settings.httpProxy.enable,
            httpProxyPort: settings.httpProxy.port,
            autoLaunch: settings.autoLaunch,
            fixedMenu: settings.fixedMenu,
            darkMode: settings.darkMode,
            autoTheme: settings.autoTheme,
            verbose: settings.verbose,
            autoHide: settings.autoHide,
          }
        }
        onValuesChange={onFieldChange}
      >
        <Field
          name="localPort"
          rules={[
            { required: true, message: t('invalid_value') },
            { validator: checkPortField },
          ]}
          normalize={(value: string) => +(value.trim())}
          validateTrigger={false}
        >
          <TextField
            className={styles.textField}
            required
            fullWidth
            size="small"
            type="number"
            label={t('local_port')}
            placeholder={t('local_port_tips')}
          />
        </Field>
        <Field
          name="pacPort"
          rules={[
            { required: true, message: t('invalid_value') },
            { validator: checkPortField }
          ]}
          normalize={(value: string) => +(value.trim())}
          validateTrigger={false}
        >
          <TextField
            className={styles.textField}
            required
            fullWidth
            type="number"
            size="small"
            label={t('pac_port')}
            placeholder={t('pac_port_tips')}
          />
        </Field>
        <Field
          name="gfwListUrl"
          validateTrigger={false}
        >
          <TextField
          className={styles.textField}
          required
          fullWidth
          type="url"
          size="small"
          label={
            <TextWithTooltip
              text={t('gfwlist_url')}
              icon={
                <span>
                  <Tooltip arrow placement="top" title={t('recover_pac_file_with_link') as string}>
                    <RestorePage className={styles.cursorPointer} onClick={reGeneratePacFileWithUrl} />
                  </Tooltip>
                  <Tooltip arrow placement="top" title={t('recover_pac_file_with_file') as string}>
                    <NoteAdd className={styles.cursorPointer} onClick={reGeneratePacFileWithFile}/>
                  </Tooltip>
                </span>
              }
            />
          }
          placeholder={t('gfwlist_url_tips')}
        />
        </Field>
        <input onChange={onGFWListFileChange} ref={inputFileRef} type={'file'} multiple={false} style={{ display: 'none' }}></input>
        <List className={styles.list}>
          <ListItem>
              <ListItemText
                primary={t('http_proxy')}
              />
              <ListItemSecondaryAction>
                <Field name="httpProxy" valuePropName="checked">
                  <AdaptiveSwitch
                    edge="end"
                  />
                </Field>
              </ListItemSecondaryAction>
          </ListItem>
          {
            settings.httpProxy.enable && (
              <ListItem>
                <ListItemText
                  primary={t('http_proxy_port')}
                  secondary={t('restart_when_changed')}
                />
                <ListItemSecondaryAction>
                  <Field
                    name="httpProxyPort"
                    rules={[
                      { required: true, message: t('invalid_value') },
                      { validator: checkPortField }
                    ]}
                    normalize={(value: string) => +(value.trim())}
                    validateTrigger={false}
                  >
                    <TextField
                      className={`${styles.textField} ${styles.indentInput}`}
                      required
                      size="small"
                      type="number"
                      placeholder={t('http_proxy_port')}
                    />
                  </Field>
                </ListItemSecondaryAction>
              </ListItem>
            )
          }
          {/* <ListItem>
              <ListItemText
                primary={'ACL'}
                // secondary="Not applicable to Linux"
              />
              <ListItemSecondaryAction>
                <AdaptiveSwitch
                  edge="end"
                  checked={settings.acl.enable}
                  onChange={e => handleSwitchValueChange("acl", e)}
                />
              </ListItemSecondaryAction>
          </ListItem>
          {
            settings.acl.enable && (
              <ListItem>
                <ListItemText
                  primary={t('acl_content')}
                />
                <ListItemSecondaryAction>
                  <TextField
                    className={`${styles.textField} ${styles.indentInput}`}
                    style={{ width: '120px', textAlign: 'right' }}
                    required
                    size="small"
                    type="text"
                    placeholder={t('click_to_edit')}
                    onClick={() => setAclVisible(true)}
                    value={'*****'}
                  />
                </ListItemSecondaryAction>
              </ListItem>
            )
          } */}
          <ListItem>
            <ListItemText
              primary={t('launch_on_boot')}
              secondary={t('not_applicable_to_linux_snap_application')}
            />
            <ListItemSecondaryAction>
              <Field name="autoLaunch" valuePropName="checked">
                <AdaptiveSwitch
                  edge="end"
                />
              </Field>
            </ListItemSecondaryAction>
          </ListItem>
          <ListItem>
            <ListItemText
              primary={t('fixed_menu')}
            />
            <ListItemSecondaryAction>
              <Field name="fixedMenu" valuePropName="checked">
                <AdaptiveSwitch
                  edge="end"
                />
              </Field>
            </ListItemSecondaryAction>
          </ListItem>
          <ListItem>
            <ListItemText
              primary={t('auto_hide')}
              secondary={t('minimize_on_start')}
            />
            <ListItemSecondaryAction>
              <Field name="autoHide" valuePropName="checked">
                <AdaptiveSwitch
                  edge="end"
                />
              </Field>
            </ListItemSecondaryAction>
          </ListItem>
          <ListItem>
            <ListItemText
              primary={t('autoTheme')}
              secondary={t('autoThemeTips')}
            />
            <ListItemSecondaryAction>
              <Field name="autoTheme" valuePropName="checked">
                <AdaptiveSwitch
                  edge="end"
                  onChange={onAutoThemeChange}
                />
              </Field>
            </ListItemSecondaryAction>
          </ListItem>
          <ListItem>
            <ListItemText
              primary={t('darkMode')}
            />
            <ListItemSecondaryAction>
              <Field name="darkMode" valuePropName="checked">
                <AdaptiveSwitch
                  edge="end"
                  disabled={settings.autoTheme}
                />
              </Field>
            </ListItemSecondaryAction>
          </ListItem>
          <ListItem>
            <ListItemText
              primary={'Language'}
            />
            <ListItemSecondaryAction>
              <Select
                value={getDefaultLang()}
                onChange={onLangChange}
              >
              <MenuItem value={'en-US'}>English</MenuItem>
              <MenuItem value={'zh-CN'}>中文简体</MenuItem>
            </Select>
            </ListItemSecondaryAction>
          </ListItem>

          <ListItem button onClick={backupConfiguration}>
              <ListItemText primary={t('backup')} />
          </ListItem>
          <ListItem button onClick={() => restoreConfiguration()}>
              <ListItemText primary={t('restore')} />
          </ListItem>
          <ListItem button onClick={handleAlertDialogOpen}>
            <ListItemText primary={t('reset_data')} />
          </ListItem>

          <Divider className={styles.margin} />

          <ListSubheader>{t('debugging')}</ListSubheader>

          <ListItem>
            <ListItemText
              primary="Verbose"
              secondary={t('verbose_output')}
            />
            <ListItemSecondaryAction>
              <Field name="verbose" valuePropName="checked">
                <AdaptiveSwitch
                  edge="end"
                />
              </Field>
            </ListItemSecondaryAction>
          </ListItem>
          <ListItem button onClick={handleOpenLog}>
            <ListItemText primary={t('open_log_dir')} />
          </ListItem>
          <ListItem button onClick={handleOpenProcessManager}>
            <ListItemText primary={t('open_process_manager')} />
          </ListItem>
        </List>

      </Form>

      {/* dialog */}

      {/* <EditAclDialog
        open={aclVisible}
        onClose={() => setAclVisible(false)}
        children={undefined}
        onTextChange={handleValueChange}
      /> */}

      <DialogConfirm onClose={handleAlertDialogClose} onConfirm={handleReset} />
    </Container>
  );
}