<commit_before>import React, { FC, useContext, ReactNode, useMemo } from 'react'
import { Form, Button, Modal } from 'antd'
import { FormItemProps } from 'antd/lib/form'
import { ExclamationCircleOutlined, BlockOutlined } from '@ant-design/icons'
import get from 'lodash/get'
import mapValues from 'lodash/mapValues'
import { startWith, map, distinctUntilChanged } from 'rxjs/operators'
import { useObservableState } from 'observable-hooks'
import { resetConfig } from '@/_helpers/config-manager'
import { resetAllProfiles } from '@/_helpers/profile-manager'
import { useTranslate } from '@/_helpers/i18n'
import { isFirefox } from '@/_helpers/saladict'
import { openURL } from '@/_helpers/browser-api'
import { GlobalsContext } from '@/options/data'
import { formItemLayout, formItemHeadLayout } from '@/options/helpers/layout'
import { uploadResult$$, upload } from '@/options/helpers/upload'
import shallowEqual from 'shallowequal'

import './_style.scss'

interface FieldValues {
  [name: string]: any
}

interface FieldShow {
  [name: string]: boolean
}

export interface SaladictFormItem
  extends Omit<FormItemProps, 'name' | 'children'> {
  /** Must set name or key. Set name if the item has value. */
  name?: string
  /** Must set name or key. Set key if the item does not carry value. */
  key?: string
  /** Hide item based on other fields */
  hide?: (values: FieldValues) => boolean
  /** Nested items. Must set items or children. */
  items?: SaladictFormItem[]
  /** Must set items or children. */
  children?: ReactNode
}

export interface SaladictFormProps {
  items: SaladictFormItem[]
}

export const SaladictForm: FC<SaladictFormProps> = props => {
  const { t, i18n, ready } = useTranslate(['options', 'common'])
  const globals = useContext(GlobalsContext)
  const { loading: uploading } = useObservableState(uploadResult$$, {
    loading: false
  })

  function extractInitial(
    items: SaladictFormItem[],
    result: {
      initialValues: { [index: string]: any }
      hideFieldFns: { [index: string]: (values: FieldValues) => boolean }
    } = { initialValues: {}, hideFieldFns: {} }
  ): { [index: string]: any } {
    for (const item of items) {
      if (item.items) {
        extractInitial(item.items, result)
      } else {
        const name = (item.key || item.name)!

        if (item.hide) {
          result.hideFieldFns[name] = item.hide
        }

        const value = get(globals, name, globals)
        if (value !== globals) {
          result.initialValues[name] = value
        } else if (process.env.DEBUG) {
          console.warn(new Error('Missing value for form key: ' + item.name))
        }
      }
    }
    return result
  }

  const { initialValues, hideFieldFns } = useMemo(
    () => extractInitial(props.items),
    [props.items]
  )

  const [hideFields, setHideFields] = useObservableState<
    FieldShow,
    FieldValues,<commit_msg>fix(options): only get values from item name<commit_after>import React, { FC, useContext, ReactNode, useMemo } from 'react'
import { Form, Button, Modal } from 'antd'
import { FormItemProps } from 'antd/lib/form'
import { ExclamationCircleOutlined, BlockOutlined } from '@ant-design/icons'
import get from 'lodash/get'
import mapValues from 'lodash/mapValues'
import { startWith, map, distinctUntilChanged } from 'rxjs/operators'
import { useObservableState } from 'observable-hooks'
import { resetConfig } from '@/_helpers/config-manager'
import { resetAllProfiles } from '@/_helpers/profile-manager'
import { useTranslate } from '@/_helpers/i18n'
import { isFirefox } from '@/_helpers/saladict'
import { openURL } from '@/_helpers/browser-api'
import { GlobalsContext } from '@/options/data'
import { formItemLayout, formItemHeadLayout } from '@/options/helpers/layout'
import { uploadResult$$, upload } from '@/options/helpers/upload'
import shallowEqual from 'shallowequal'

import './_style.scss'

interface FieldValues {
  [name: string]: any
}

interface FieldShow {
  [name: string]: boolean
}

export interface SaladictFormItem
  extends Omit<FormItemProps, 'name' | 'children'> {
  /** Must set name or key. Set name if the item has value. */
  name?: string
  /** Must set name or key. Set key if the item does not carry value. */
  key?: string
  /** Hide item based on other fields */
  hide?: (values: FieldValues) => boolean
  /** Nested items. Must set items or children. */
  items?: SaladictFormItem[]
  /** Must set items or children. */
  children?: ReactNode
}

export interface SaladictFormProps {
  items: SaladictFormItem[]
}

export const SaladictForm: FC<SaladictFormProps> = props => {
  const { t, i18n, ready } = useTranslate(['options', 'common'])
  const globals = useContext(GlobalsContext)
  const { loading: uploading } = useObservableState(uploadResult$$, {
    loading: false
  })

  function extractInitial(
    items: SaladictFormItem[],
    result: {
      initialValues: { [index: string]: any }
      hideFieldFns: { [index: string]: (values: FieldValues) => boolean }
    } = { initialValues: {}, hideFieldFns: {} }
  ): { [index: string]: any } {
    for (const item of items) {
      if (item.items) {
        extractInitial(item.items, result)
      } else {
        if (item.hide) {
          result.hideFieldFns[(item.key || item.name)!] = item.hide
        }

        if (item.name) {
          const value = get(globals, item.name, globals)
          if (value !== globals) {
            result.initialValues[item.name] = value
          } else if (process.env.DEBUG) {
            console.warn(new Error('Missing value for form key: ' + item.name))
          }
        }
      }
    }
    return result
  }

  const { initialValues, hideFieldFns } = useMemo(
    () => extractInitial(props.items),
    [props.items]
  )

  const [hideFields, setHideFields] = useObservableState<
    FieldShow,
    FieldValues,
{'fraction_non_alphanumeric': 0.12749615975422426, 'fraction_numerical': 0.00136542072025943, 'mean_word_length': 3.449506454062263, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2003386', 'n_tokens_mistral': 1802, 'n_tokens_neox': 1784, 'n_words': 506}