{"version":3,"sources":["webpack:///./src/components/primary-buttons/primary-buttons.tsx","webpack:///./src/components/pages/contribution/speak/utility.ts","webpack:///./src/components/pages/contribution/speak/audio-web.ts","webpack:///./src/audio-recorder-polyfill/index.cjs","webpack:///./src/audio-recorder-polyfill/wave-encoder/index.cjs","webpack:///./src/components/pages/dashboard/challenge/images/ibm.svg","webpack:///./src/components/pages/dashboard/challenge/images/lenovo.svg","webpack:///./src/components/pages/dashboard/challenge/images/mozilla.svg","webpack:///./src/components/pages/dashboard/challenge/images/sap.svg","webpack:///../node_modules/lodash.pick/index.js","webpack:///./src/components/pages/profile/settings/settings-image.svg","webpack:///./src/components/pages/profile/avatar-setup/avatar-setup.tsx","webpack:///./src/components/search/index.tsx","webpack:///./src/stores/demographics.ts","webpack:///./src/components/pages/dashboard/challenge/constants.ts","webpack:///./src/components/pages/profile/info/info.tsx","webpack:///./src/components/pages/profile/settings/settings.tsx","webpack:///./src/components/pages/profile/layout.tsx"],"names":["PrimaryButton","className","to","trackClass","props","disabled","join","type","PlayTTSButton","status","id","RecordButton","Voice","PlayButton","isPlaying","shouldUseFixForIOSDevice","os_name","AudioRecorder","AudioError","AudioWeb","this","recorderListeners","start","dataavailable","stop","analyze","bind","microphone","Promise","res","rej","deny","error","NotAllowedError","NOT_ALLOWED","NotFoundError","NO_MIC","name","resolve","stream","navigator","mediaDevices","getUserMedia","audio","then","webkitGetUserMedia","mozGetUserMedia","NO_SUPPORT","window","MediaRecorder","notSupported","analyzerNode","getByteFrequencyData","frequencyBins","volumeCallback","Math","max","cb","bufferSize","isReady","getMicrophone","audioContext","AudioContext","webkitAudioContext","sourceNode","createMediaStreamSource","volumeNode","createGain","createAnalyser","outputNode","createMediaStreamDestination","channelCount","connect","prototype","mimeType","recorder","fftSize","smoothingTimeConstant","Uint8Array","frequencyBinCount","jsNode","createScriptProcessor","destination","processor","_rej","chunks","removeEventListener","_e","e","push","data","addEventListener","onaudioprocess","console","undefined","blob","Blob","recordingDevice","device_default_input_label","label","device_default_input_is_bluetooth","toLocaleLowerCase","includes","url","URL","createObjectURL","created_at","Date","toISOString","reject","track","getTracks","context","waveEncoder","method","event","Event","Error","config","state","em","document","createDocumentFragment","encoder","fn","js","toString","replace","Worker","createWorker","dispatchEvent","timeslice","contextExternal","processorExternal","clone","input","postMessage","sampleRate","inputBuffer","getChannelData","slicing","setInterval","requestData","forEach","disconnect","clearInterval","args","isTypeSupported","module","exports","recorded","onmessage","buffer","length","i","index","sample","encode","bufferLength","wav","view","DataView","setUint32","setUint16","set","dump","freeGlobal","global","Object","freeSelf","self","root","Function","apply","func","thisArg","call","arrayPush","array","values","offset","objectProto","hasOwnProperty","objectToString","Symbol","propertyIsEnumerable","spreadableSymbol","isConcatSpreadable","nativeMax","isFlattenable","value","isArray","isObjectLike","isLength","tag","isObject","isFunction","isArrayLike","isArrayLikeObject","isArguments","toKey","isSymbol","result","Array","pick","object","predicate","key","basePickBy","basePick","iteratee","arrayMap","baseFlatten","depth","isStrict","arguments","otherArgs","Lottie","animationData","resizeImage","file","maxSize","reader","FileReader","image","Image","canvas","createElement","resize","width","height","getContext","drawImage","dataURI","bytes","split","indexOf","atob","unescape","mime","ia","charCodeAt","dataURItoBlob","toDataURL","ok","no","match","onload","readerEvent","src","target","readAsDataURL","isSaving","isRecording","counter","clipStatus","blobUrl","avatarClipUrl","isUnsupportedPlatform","maxVolume","recordingStartTime","recordingStopTime","avatarRecordedBlobUrl","audioRef","updateVolume","volume","playAvatarClip","locale","current","pause","currentTime","setState","play","playRecordedAvatarClip","log","handleRecordClick","saveRecording","startRecording","setTimeout","err","now","info","release","init","downloadTimer","tl","updateAvatarClip","cancelRecording","clip","api","fetchAvatarClip","setVolumeCallback","isMicrophoneSupported","isAudioRecordingSupported","user","account","avatar_clip_url","files","addNotification","getString","refreshUser","item","saveAvatar","addUpload","saveAvatarClip","confirm","deleteAvatarClip","avatarType","avatar_url","startsWith","defaultOptions","loop","autoplay","rendererSettings","preserveAspectRatio","hasClip","preload","ref","onEnded","onError","onClick","fallback","options","eventListeners","outline","rounded","uploadAvatarClip","onDragOver","preventDefault","onDrop","saveFileAvatar","dataTransfer","elems","browseWrap","accept","onChange","actions","addPill","refresh","add","Option","option","selected","countries","mostUsedCountries","placeholder","placeholderText","displayName","country","toLowerCase","wrapperRef","isOpened","setIsOpened","searchString","setSearchString","countriesToDisplay","setCountriesToDisplay","mostUsedCountriesToDisplay","setMostUsedCountriesToDisplay","handleClickOutside","contains","handleSelectValue","find","c","query","filter","shouldDisplayMostUsed","attrs","required","map","style","margin","AGES","twenties","thirties","fourties","fifties","sixties","seventies","eighties","nineties","LEGACY_AGES","teens","SEXES","male","female","other","DIAGNOSES","cp","tbi","ds","stroke_nerve_injury","ms","als_mnd","autism","parkinsons","apraxia_of_speech","hearing_loss","glossectomy","electrolarynx","rather_not_say","LEGACY_DIAGNOSES","cerebral_palsy","stroke","als","parkinsons_disease","down_syndrome","multiple_sclerosis","oral_injury","Tooltip","Options","children","entries","history","toLocaleRoute","userClients","addUploads","saveAccount","subscriptions","fetchSubscriptions","userFields","setUserFields","username","visible","age","gender","diagnosis","sendEmails","privacyAgreed","termsAgreed","country_id","ageOptions","isUnderage","diagnosisOptions","setCountries","locales","setLocales","isInitialized","setIsInitialized","setIsSaving","isSubmitted","setIsSubmitted","isEnrolledInChallenge","enrollment","challenge","isEnrolled","fetchCountries","inMailingList","isFetchingAccount","reduce","u","Boolean","concat","l1","findIndex","l2","handleChangeFor","field","checked","JOIN_MAILING_LIST","LEAVE_MAILING_LIST","CHECKBOX_USAGE","submit","PROFILE_UPDATED","BUTTON_USAGE","CREATE_ACCOUNT","isUserProfileUpdate","userDataFromLocalStorage","JSON","parse","localStorage","getItem","auth_token","l","client_id","client_id_to_delete","userId","team","invite","subscribeToEnsembleMailingList","email","pathname","DASHBOARD","CHALLENGE","showOnboardingModal","earlyEnroll","location","search","shouldDisableSubmit","trim","role","basket_token","arrow","html","color","theme","privacyLink","href","PRIVACY","termsLink","TERMS","Section","title","titleAction","isSubscribed","replaceState","rel","blank","offText","onText","defaultChecked","skip_submission_feedback","alt","infoRoute","avatarRoute","prefRoute","PROFILE_INFO","r","route","icon","slice","Infinity","exact","path","component","Component","render","_props"],"mappings":"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","file":"5.js?id=e7faaec273dfbad7f56b","sourcesContent":["import * as React from 'react';\nimport { Localized } from '@fluent/react';\n\nimport URLS from '../../urls';\nimport { LocaleLink } from '../locale-helpers';\nimport { getTrackClass } from '../../services/tracker';\nimport { MicIcon, OldPlayIcon, StopIcon, PlayBlueIcon, PauseBlueIcon } from '../ui/icons';\n\nimport './primary-buttons.css';\n\nexport const PrimaryButton = ({\n  className,\n  to,\n  trackClass,\n  ...props\n}: { to?: string; trackClass?: string } & React.ButtonHTMLAttributes<any>) => (\n  <div\n    className={[\n      'primary-button',\n      className,\n      props.disabled ? 'disabled' : '',\n      trackClass ? getTrackClass('fs', trackClass) : '',\n    ].join(' ')}>\n    {to ? (\n      <LocaleLink to={to} {...props} />\n    ) : (\n      <button type=\"button\" {...props} />\n    )}\n    <div className=\"background\" />\n  </div>\n);\n\nexport type RecordingStatus = null | 'waiting' | 'recording';\nexport type PlayTTSStatus = null | 'playing' | 'listen';\n\nexport const PlayTTSButton = ({\n  status,\n  disabled,\n  ...props\n}: {\n  status: PlayTTSStatus;\n  disabled: boolean;\n} & React.ButtonHTMLAttributes<any>) => {\n  const className = `play-tts-button ${status === 'playing' ? 'pause' : 'listen'} ${disabled ? 'disabled' : ''}`;\n\n  return (\n    <>\n      {\n        status === 'playing' && (\n          <button {...props} disabled={disabled} className={className}>\n            <PauseBlueIcon />\n            <Localized id=\"pause-tts\">\n              <span />\n            </Localized>\n          </button>\n        )\n      }\n      {\n        status === 'listen' && (\n          <button {...props} disabled={disabled} className={className}>\n            <PlayBlueIcon />\n            <Localized id=\"play-tts\">\n              <span />\n            </Localized>\n          </button>\n        )\n      }\n    </>\n  )\n}\n\nexport const RecordButton = ({\n  status,\n  disabled,\n  trackClass,\n  ...props\n}: {\n  status: RecordingStatus;\n  disabled: boolean;\n  trackClass?: string;\n} & React.ButtonHTMLAttributes<any>) => (\n  <PrimaryButton\n    className={status === null ? 'stop' : 'record'}\n    {...props}\n    trackClass={trackClass}\n    disabled={status === 'waiting' || disabled}>\n    {status === null && <MicIcon />}\n    {status === 'recording' && <StopIcon />}\n  </PrimaryButton>\n);\n\nexport const RecordLink = (props: any) => (\n  <PrimaryButton className=\"stop\" to={URLS.SPEAK} {...props}>\n    <MicIcon />\n  </PrimaryButton>\n);\n\nexport const Voice = (props: any) => (\n  <PrimaryButton className=\"stop\" {...props} />\n);\n\nexport const PlayButton = ({\n  isPlaying,\n  trackClass,\n  ...props\n}: { isPlaying: boolean; trackClass?: string } & React.ButtonHTMLAttributes<\n  any\n>) => (\n  <PrimaryButton\n    className={isPlaying ? 'stop' : 'play'}\n    trackClass={trackClass}\n    {...props}>\n    {isPlaying ? <StopIcon /> : <OldPlayIcon />}\n  </PrimaryButton>\n);\n","import { getDeviceMetadata } from '../../../../utility';\n\nexport const shouldUseFixForIOSDevice = (): boolean => {\n  const metadata = getDeviceMetadata();\n\n  return metadata.os_name === 'iOS';\n}\n","import { getRecordingDevice, getAudioFormat } from '../../../../utility';\n// import AudioRecorder from 'audio-recorder-polyfill';\nconst AudioRecorder = require('../../../../audio-recorder-polyfill/index.cjs');\n\ninterface BlobEvent extends Event {\n  data: Blob;\n}\n\nexport enum AudioError {\n  NOT_ALLOWED = 'NOT_ALLOWED',\n  NO_MIC = 'NO_MIC',\n  NO_SUPPORT = 'NO_SUPPORT',\n}\n\nexport interface AudioInfo {\n  url: string;\n  blob: Blob;\n  device_default_input_label: string;\n  device_default_input_is_bluetooth: boolean;\n  created_at: string;\n}\n\nexport default class AudioWeb {\n  microphone: MediaStream;\n  analyzerNode: AnalyserNode;\n  audioContext: AudioContext;\n  recorder: any;\n  chunks: any[];\n  frequencyBins: Uint8Array;\n  volumeCallback: Function;\n  jsNode: any;\n  recorderListeners: {\n    start: Function | null;\n    dataavailable: Function | null;\n    stop: Function | null;\n  };\n\n  constructor() {\n    this.recorderListeners = {\n      start: null,\n      dataavailable: null,\n      stop: null,\n    };\n    this.analyze = this.analyze.bind(this);\n  }\n\n  private isReady(): boolean {\n    return !!this.microphone;\n  }\n\n  private getMicrophone(): Promise<MediaStream> {\n    return new Promise(function (res: Function, rej: Function) {\n      function deny(error: MediaStreamError) {\n        rej(\n          ({\n            NotAllowedError: AudioError.NOT_ALLOWED,\n            NotFoundError: AudioError.NO_MIC,\n          } as { [errorName: string]: AudioError })[error.name] || error\n        );\n      }\n      function resolve(stream: MediaStream) {\n        res(stream);\n      }\n\n      if (navigator.mediaDevices?.getUserMedia) {\n        navigator.mediaDevices\n          .getUserMedia({ audio: true })\n          .then(resolve, deny);\n      } else if (navigator.getUserMedia) {\n        navigator.getUserMedia({ audio: true }, resolve, deny);\n      } else if (navigator.webkitGetUserMedia) {\n        navigator.webkitGetUserMedia({ audio: true }, resolve, deny);\n      } else if (navigator.mozGetUserMedia) {\n        navigator.mozGetUserMedia({ audio: true }, resolve, deny);\n      } else {\n        // Browser does not support getUserMedia\n        rej(AudioError.NO_SUPPORT);\n      }\n    });\n  }\n\n  // Check all the browser prefixes for microhpone support.\n  isMicrophoneSupported() {\n    return (\n      navigator.mediaDevices?.getUserMedia ||\n      navigator.getUserMedia ||\n      navigator.webkitGetUserMedia ||\n      navigator.mozGetUserMedia\n    );\n  }\n\n  // Check if audio recording is supported\n  isAudioRecordingSupported() {\n    return (\n      typeof window.MediaRecorder !== 'undefined' &&\n      !window.MediaRecorder.notSupported\n    );\n  }\n\n  private analyze() {\n    this.analyzerNode.getByteFrequencyData(this.frequencyBins);\n\n    if (this.volumeCallback) {\n      this.volumeCallback(Math.max(...this.frequencyBins));\n    }\n  }\n\n  setVolumeCallback(cb: Function) {\n    this.volumeCallback = cb;\n  }\n\n  /**\n   * Initialize the recorder, opening the microphone media stream.\n   *\n   * If microphone access is currently denied, the user is asked to grant\n   * access. Since these permission changes take effect only after a reload,\n   * the page is reloaded if the user decides to do so.\n   *\n   */\n  async init(bufferSize: number = 0) {\n    if (this.isReady()) {\n      return;\n    }\n\n    const microphone = await this.getMicrophone();\n\n    this.microphone = microphone;\n    const audioContext = new (window.AudioContext ||\n      window.webkitAudioContext)();\n    const sourceNode = audioContext.createMediaStreamSource(microphone);\n    const volumeNode = audioContext.createGain();\n    const analyzerNode = audioContext.createAnalyser();\n    const outputNode = audioContext.createMediaStreamDestination();\n\n    // Make sure we're doing mono everywhere.\n    sourceNode.channelCount = 1;\n    volumeNode.channelCount = 1;\n    analyzerNode.channelCount = 1;\n    outputNode.channelCount = 1;\n\n    // Connect the nodes together\n    sourceNode.connect(volumeNode);\n    volumeNode.connect(analyzerNode);\n    analyzerNode.connect(outputNode);\n\n    // and set up the recorder.\n    AudioRecorder.prototype.mimeType = 'audio/wav'\n    this.recorder = new window.MediaRecorder(outputNode.stream);\n\n    // Set up the analyzer node, and allocate an array for its data\n    // FFT size 64 gives us 32 bins. But those bins hold frequencies up to\n    // 22kHz or more, and we only care about lower frequencies which is where\n    // most human voice lies, so we use fewer bins.\n    analyzerNode.fftSize = 128;\n    analyzerNode.smoothingTimeConstant = 0.96;\n    this.frequencyBins = new Uint8Array(analyzerNode.frequencyBinCount);\n\n    // Setup jsNode for audio analysis callbacks.\n    // TODO: `createScriptProcessor` is deprecated, and is a heavy solution for\n    //       what it’s doing (checking recording volume). It should be replaced\n    //       with something lighter, or AudioWorklets once they become more\n    //       widely adopted.\n    this.jsNode = audioContext.createScriptProcessor(bufferSize, 1, 1);\n    this.jsNode.connect(audioContext.destination);\n\n    this.analyzerNode = analyzerNode;\n    this.audioContext = audioContext;\n  }\n\n  start(audioContext: AudioContext, processor: ScriptProcessorNode): Promise<void> {\n    if (!this.isReady()) {\n      console.error('Cannot record audio before microhphone is ready.');\n      return Promise.resolve();\n    }\n\n    return new Promise<void>((res: Function, _rej: Function) => {\n      this.chunks = [];\n      // Remove the old listeners.\n      this.recorder.removeEventListener('start', this.recorderListeners.start);\n      this.recorder.removeEventListener(\n        'dataavailable',\n        this.recorderListeners.dataavailable\n      );\n\n      // Update the stored listeners.\n      this.recorderListeners.start = (_e: Event) => res();\n      this.recorderListeners.dataavailable = (e: BlobEvent) => {\n        this.chunks.push(e.data);\n      };\n\n      // Add the new listeners.\n      this.recorder.addEventListener('start', this.recorderListeners.start);\n      this.recorder.addEventListener(\n        'dataavailable',\n        this.recorderListeners.dataavailable\n      );\n\n      // Finally, start it up.\n      // We want to be able to record up to 60s of audio in a single blob.\n      // Without this argument to start(), Chrome will call dataavailable\n      // very frequently.\n      this.jsNode.onaudioprocess = this.analyze;\n      this.recorder.start(20000, audioContext, processor);\n    });\n  }\n\n  stop(): Promise<AudioInfo> {\n    if (!this.isReady()) {\n      console.error('Cannot stop audio before microphone is ready.');\n      return Promise.reject();\n    }\n\n    return new Promise((res: Function, _rej: Function) => {\n      this.jsNode.onaudioprocess = undefined;\n      this.recorder.removeEventListener('stop', this.recorderListeners.stop);\n      this.recorderListeners.stop = async (_e: Event) => {\n        const blob = new Blob(this.chunks, { type: getAudioFormat() });\n        \n        const recordingDevice = await getRecordingDevice();\n        const device_default_input_label = recordingDevice && recordingDevice.label\n        const device_default_input_is_bluetooth = recordingDevice?.label.toLocaleLowerCase().includes('bluetooth')\n\n        res({\n          url: URL.createObjectURL(blob),\n          blob: blob,\n          device_default_input_label,\n          device_default_input_is_bluetooth,\n          created_at: new Date().toISOString()\n        });\n      };\n      this.recorder.addEventListener('stop', this.recorderListeners.stop);\n      this.recorder.stop();\n    });\n  }\n\n  release() {\n    if (this.microphone) {\n      for (const track of this.microphone.getTracks()) {\n        track.stop();\n      }\n    }\n    this.microphone = null;\n  }\n}\n","let waveEncoder = require('./wave-encoder/index.cjs')\n\nlet AudioContext = window.AudioContext || window.webkitAudioContext\n\nlet createWorker = fn => {\n  let js = fn\n    .toString()\n    .replace(/^(\\(\\)\\s*=>|function\\s*\\(\\))\\s*{/, '')\n    .replace(/}$/, '')\n  let blob = new Blob([js])\n  return new Worker(URL.createObjectURL(blob))\n}\n\nlet error = method => {\n  let event = new Event('error')\n  event.data = new Error('Wrong state for ' + method)\n  return event\n}\n\nlet context\n\n/**\n * Audio Recorder with MediaRecorder API.\n *\n * @example\n * navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {\n *   let recorder = new MediaRecorder(stream)\n * })\n */\nclass MediaRecorder {\n  /**\n   * @param {MediaStream} stream The audio stream to record.\n   */\n  constructor (stream, config = null) {\n    /**\n     * The `MediaStream` passed into the constructor.\n     * @type {MediaStream}\n     */\n    this.stream = stream\n    this.config = config\n    /**\n     * The current state of recording process.\n     * @type {\"inactive\"|\"recording\"|\"paused\"}\n     */\n    this.state = 'inactive'\n\n    this.em = document.createDocumentFragment()\n    this.encoder = createWorker(MediaRecorder.encoder)\n\n    let recorder = this\n    this.encoder.addEventListener('message', e => {\n      let event = new Event('dataavailable')\n      event.data = new Blob([e.data], { type: recorder.mimeType })\n      recorder.em.dispatchEvent(event)\n      if (recorder.state === 'inactive') {\n        recorder.em.dispatchEvent(new Event('stop'))\n      }\n    })\n  }\n\n  /**\n   * Begins recording media.\n   *\n   * @param {number} [timeslice] The milliseconds to record into each `Blob`.\n   *                             If this parameter isn’t included, single `Blob`\n   *                             will be recorded.\n   *\n   * @param {object} [contextExternal]   ios/safari only - Audio context created in user click ctx.\n   * @param {object} [processorExternal] ios/safari only - Script processor created in user click ctx.\n   *\n   * @return {undefined}\n   *\n   * @example\n   * recordButton.addEventListener('click', () => {\n   *   recorder.start()\n   * })\n   */\n  start (timeslice, contextExternal, processorExternal) {\n    // trying to fix no_wav_data_length error using this example https://github.com/ai/audio-recorder-polyfill/compare/main...kaliatech:issue-4-ios-safari-hack?expand=1\n    // from this thread https://github.com/ai/audio-recorder-polyfill/issues/4\n    if (this.state !== 'inactive') {\n      return this.em.dispatchEvent(error('start'))\n    }\n\n    this.state = 'recording'\n\n    if (contextExternal) {\n      context = contextExternal\n    } else {\n      context = new AudioContext(this.config)\n    }\n\n    this.clone = this.stream.clone()\n    this.input = context.createMediaStreamSource(this.clone)\n\n    if (processorExternal) {\n      this.processor = processorExternal\n    } else {\n      this.processor = context.createScriptProcessor(2048, 1, 1)\n    }\n\n    this.encoder.postMessage(['init', context.sampleRate])\n\n    this.processor.onaudioprocess = e => {\n      if (this.state === 'recording') {\n        this.encoder.postMessage(['encode', e.inputBuffer.getChannelData(0)])\n      }\n    }\n\n    this.input.connect(this.processor)\n    this.processor.connect(context.destination)\n\n    this.em.dispatchEvent(new Event('start'))\n\n    if (timeslice) {\n      this.slicing = setInterval(() => {\n        if (this.state === 'recording') this.requestData()\n      }, timeslice)\n    }\n\n    return undefined\n  }\n\n  /**\n   * Stop media capture and raise `dataavailable` event with recorded data.\n   *\n   * @return {undefined}\n   *\n   * @example\n   * finishButton.addEventListener('click', () => {\n   *   recorder.stop()\n   * })\n   */\n  stop () {\n    if (this.state === 'inactive') {\n      return this.em.dispatchEvent(error('stop'))\n    }\n\n    this.requestData()\n    this.state = 'inactive'\n    this.clone.getTracks().forEach(track => {\n      track.stop()\n    })\n    this.processor.disconnect()\n    this.input.disconnect()\n    return clearInterval(this.slicing)\n  }\n\n  /**\n   * Pauses recording of media streams.\n   *\n   * @return {undefined}\n   *\n   * @example\n   * pauseButton.addEventListener('click', () => {\n   *   recorder.pause()\n   * })\n   */\n  pause () {\n    if (this.state !== 'recording') {\n      return this.em.dispatchEvent(error('pause'))\n    }\n\n    this.state = 'paused'\n    return this.em.dispatchEvent(new Event('pause'))\n  }\n\n  /**\n   * Resumes media recording when it has been previously paused.\n   *\n   * @return {undefined}\n   *\n   * @example\n   * resumeButton.addEventListener('click', () => {\n   *   recorder.resume()\n   * })\n   */\n  resume () {\n    if (this.state !== 'paused') {\n      return this.em.dispatchEvent(error('resume'))\n    }\n\n    this.state = 'recording'\n    return this.em.dispatchEvent(new Event('resume'))\n  }\n\n  /**\n   * Raise a `dataavailable` event containing the captured media.\n   *\n   * @return {undefined}\n   *\n   * @example\n   * this.on('nextData', () => {\n   *   recorder.requestData()\n   * })\n   */\n  requestData () {\n    if (this.state === 'inactive') {\n      return this.em.dispatchEvent(error('requestData'))\n    }\n\n    return this.encoder.postMessage(['dump', context.sampleRate])\n  }\n\n  /**\n   * Add listener for specified event type.\n   *\n   * @param {\"start\"|\"stop\"|\"pause\"|\"resume\"|\"dataavailable\"|\"error\"}\n   * type Event type.\n   * @param {function} listener The listener function.\n   *\n   * @return {undefined}\n   *\n   * @example\n   * recorder.addEventListener('dataavailable', e => {\n   *   audio.src = URL.createObjectURL(e.data)\n   * })\n   */\n  addEventListener (...args) {\n    this.em.addEventListener(...args)\n  }\n\n  /**\n   * Remove event listener.\n   *\n   * @param {\"start\"|\"stop\"|\"pause\"|\"resume\"|\"dataavailable\"|\"error\"}\n   * type Event type.\n   * @param {function} listener The same function used in `addEventListener`.\n   *\n   * @return {undefined}\n   */\n  removeEventListener (...args) {\n    this.em.removeEventListener(...args)\n  }\n\n  /**\n   * Calls each of the listeners registered for a given event.\n   *\n   * @param {Event} event The event object.\n   *\n   * @return {boolean} Is event was no canceled by any listener.\n   */\n  dispatchEvent (...args) {\n    this.em.dispatchEvent(...args)\n  }\n}\n\n/**\n * The MIME type that is being used for recording.\n * @type {string}\n */\nMediaRecorder.prototype.mimeType = 'audio/wav'\n\n/**\n * Returns `true` if the MIME type specified is one the polyfill can record.\n *\n * This polyfill supports `audio/wav` and `audio/mpeg`.\n *\n * @param {string} mimeType The mimeType to check.\n *\n * @return {boolean} `true` on `audio/wav` and `audio/mpeg` MIME type.\n */\nMediaRecorder.isTypeSupported = mimeType => {\n  return MediaRecorder.prototype.mimeType === mimeType\n}\n\n/**\n * `true` if MediaRecorder can not be polyfilled in the current browser.\n * @type {boolean}\n *\n * @example\n * if (MediaRecorder.notSupported) {\n *   showWarning('Audio recording is not supported in this browser')\n * }\n */\nMediaRecorder.notSupported = !navigator.mediaDevices || !AudioContext\n\n/**\n * Converts RAW audio buffer to compressed audio files.\n * It will be loaded to Web Worker.\n * By default, WAVE encoder will be used.\n * @type {function}\n *\n * @example\n * MediaRecorder.prototype.mimeType = 'audio/ogg'\n * MediaRecorder.encoder = oggEncoder\n */\nMediaRecorder.encoder = waveEncoder\n\nmodule.exports = MediaRecorder\n","// Copied from https://github.com/chris-rudmin/Recorderjs\n\nmodule.exports = () => {\n  let BYTES_PER_SAMPLE = 2\n\n  let recorded = []\n\n  function encode (buffer) {\n    let length = buffer.length\n    let data = new Uint8Array(length * BYTES_PER_SAMPLE)\n    for (let i = 0; i < length; i++) {\n      let index = i * BYTES_PER_SAMPLE\n      let sample = buffer[i]\n      if (sample > 1) {\n        sample = 1\n      } else if (sample < -1) {\n        sample = -1\n      }\n      sample = sample * 32768\n      data[index] = sample\n      data[index + 1] = sample >> 8\n    }\n    recorded.push(data)\n  }\n\n  function dump (sampleRate) {\n    let bufferLength = recorded.length ? recorded[0].length : 0\n    let length = recorded.length * bufferLength\n    let wav = new Uint8Array(44 + length)\n    let view = new DataView(wav.buffer)\n\n    // RIFF identifier 'RIFF'\n    view.setUint32(0, 1380533830, false)\n    // file length minus RIFF identifier length and file description length\n    view.setUint32(4, 36 + length, true)\n    // RIFF type 'WAVE'\n    view.setUint32(8, 1463899717, false)\n    // format chunk identifier 'fmt '\n    view.setUint32(12, 1718449184, false)\n    // format chunk length\n    view.setUint32(16, 16, true)\n    // sample format (raw)\n    view.setUint16(20, 1, true)\n    // channel count\n    view.setUint16(22, 1, true)\n    // sample rate\n    view.setUint32(24, sampleRate, true)\n    // byte rate (sample rate * block align)\n    view.setUint32(28, sampleRate * BYTES_PER_SAMPLE, true)\n    // block align (channel count * bytes per sample)\n    view.setUint16(32, BYTES_PER_SAMPLE, true)\n    // bits per sample\n    view.setUint16(34, 8 * BYTES_PER_SAMPLE, true)\n    // data chunk identifier 'data'\n    view.setUint32(36, 1684108385, false)\n    // data chunk length\n    view.setUint32(40, length, true)\n\n    // eslint-disable-next-line unicorn/no-for-loop\n    for (let i = 0; i < recorded.length; i++) {\n      wav.set(recorded[i], i * bufferLength + 44)\n    }\n\n    recorded = []\n    postMessage(wav.buffer, [wav.buffer])\n  }\n\n  onmessage = e => {\n    if (e.data[0] === 'encode') {\n      encode(e.data[1])\n    } else if (e.data[0] === 'dump') {\n      dump(e.data[1])\n    }\n  }\n}\n","module.exports = __webpack_public_path__ + \"d88c16c3d756a31c343700e0e26d9192.svg\";","module.exports = __webpack_public_path__ + \"6a6a438d4cddcfec4d51f0bd644f154a.svg\";","module.exports = __webpack_public_path__ + \"a914cfc32246a0eee02b5fa521269781.svg\";","module.exports = __webpack_public_path__ + \"723827e558eaea61ef4e2741e9fcd8f4.svg\";","/**\n * lodash (Custom Build) <https://lodash.com/>\n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors <https://jquery.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0,\n    MAX_SAFE_INTEGER = 9007199254740991;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    funcTag = '[object Function]',\n    genTag = '[object GeneratorFunction]',\n    symbolTag = '[object Symbol]';\n\n/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\n/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n  switch (args.length) {\n    case 0: return func.call(thisArg);\n    case 1: return func.call(thisArg, args[0]);\n    case 2: return func.call(thisArg, args[0], args[1]);\n    case 3: return func.call(thisArg, args[0], args[1], args[2]);\n  }\n  return func.apply(thisArg, args);\n}\n\n/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n  var index = -1,\n      length = array ? array.length : 0,\n      result = Array(length);\n\n  while (++index < length) {\n    result[index] = iteratee(array[index], index, array);\n  }\n  return result;\n}\n\n/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n  var index = -1,\n      length = values.length,\n      offset = array.length;\n\n  while (++index < length) {\n    array[offset + index] = values[index];\n  }\n  return array;\n}\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar Symbol = root.Symbol,\n    propertyIsEnumerable = objectProto.propertyIsEnumerable,\n    spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * The base implementation of `_.flatten` with support for restricting flattening.\n *\n * @private\n * @param {Array} array The array to flatten.\n * @param {number} depth The maximum recursion depth.\n * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n * @param {Array} [result=[]] The initial result value.\n * @returns {Array} Returns the new flattened array.\n */\nfunction baseFlatten(array, depth, predicate, isStrict, result) {\n  var index = -1,\n      length = array.length;\n\n  predicate || (predicate = isFlattenable);\n  result || (result = []);\n\n  while (++index < length) {\n    var value = array[index];\n    if (depth > 0 && predicate(value)) {\n      if (depth > 1) {\n        // Recursively flatten arrays (susceptible to call stack limits).\n        baseFlatten(value, depth - 1, predicate, isStrict, result);\n      } else {\n        arrayPush(result, value);\n      }\n    } else if (!isStrict) {\n      result[result.length] = value;\n    }\n  }\n  return result;\n}\n\n/**\n * The base implementation of `_.pick` without support for individual\n * property identifiers.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} props The property identifiers to pick.\n * @returns {Object} Returns the new object.\n */\nfunction basePick(object, props) {\n  object = Object(object);\n  return basePickBy(object, props, function(value, key) {\n    return key in object;\n  });\n}\n\n/**\n * The base implementation of  `_.pickBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} props The property identifiers to pick from.\n * @param {Function} predicate The function invoked per property.\n * @returns {Object} Returns the new object.\n */\nfunction basePickBy(object, props, predicate) {\n  var index = -1,\n      length = props.length,\n      result = {};\n\n  while (++index < length) {\n    var key = props[index],\n        value = object[key];\n\n    if (predicate(value, key)) {\n      result[key] = value;\n    }\n  }\n  return result;\n}\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n  start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n  return function() {\n    var args = arguments,\n        index = -1,\n        length = nativeMax(args.length - start, 0),\n        array = Array(length);\n\n    while (++index < length) {\n      array[index] = args[start + index];\n    }\n    index = -1;\n    var otherArgs = Array(start + 1);\n    while (++index < start) {\n      otherArgs[index] = args[index];\n    }\n    otherArgs[start] = array;\n    return apply(func, this, otherArgs);\n  };\n}\n\n/**\n * Checks if `value` is a flattenable `arguments` object or array.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n */\nfunction isFlattenable(value) {\n  return isArray(value) || isArguments(value) ||\n    !!(spreadableSymbol && value && value[spreadableSymbol]);\n}\n\n/**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\nfunction toKey(value) {\n  if (typeof value == 'string' || isSymbol(value)) {\n    return value;\n  }\n  var result = (value + '');\n  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n *  else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nfunction isArguments(value) {\n  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&\n    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);\n}\n\n/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n  return value != null && isLength(value.length) && !isFunction(value);\n}\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n *  else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n  return isObjectLike(value) && isArrayLike(value);\n}\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n  // The use of `Object#toString` avoids issues with the `typeof` operator\n  // in Safari 8-9 which returns 'object' for typed array and other constructors.\n  var tag = isObject(value) ? objectToString.call(value) : '';\n  return tag == funcTag || tag == genTag;\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n  return typeof value == 'number' &&\n    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n  var type = typeof value;\n  return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n  return !!value && typeof value == 'object';\n}\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n  return typeof value == 'symbol' ||\n    (isObjectLike(value) && objectToString.call(value) == symbolTag);\n}\n\n/**\n * Creates an object composed of the picked `object` properties.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [props] The property identifiers to pick.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pick(object, ['a', 'c']);\n * // => { 'a': 1, 'c': 3 }\n */\nvar pick = baseRest(function(object, props) {\n  return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey));\n});\n\nmodule.exports = pick;\n","module.exports = __webpack_public_path__ + \"bb28a2b91e02ae3241aab24a69ec649c.svg\";","import {\n  Localized,\n  withLocalization,\n  WithLocalizationProps,\n} from '@fluent/react';\nimport * as React from 'react';\nimport { connect } from 'react-redux';\nimport API from '../../../../services/api';\nimport { trackProfile, trackVoiceAvatar } from '../../../../services/tracker';\nimport { Locale } from '../../../../stores/locale';\nimport { Notifications } from '../../../../stores/notifications';\nimport StateTree from '../../../../stores/tree';\nimport { User } from '../../../../stores/user';\nimport { Uploads } from '../../../../stores/uploads';\nimport {\n  CheckIcon,\n  LinkIcon,\n  MicIcon,\n  StopIcon,\n  ShareIcon,\n  RedoIcon,\n  CrossIcon,\n  TrashIcon,\n} from '../../../ui/icons';\nimport { Button } from '../../../ui/ui';\nimport { Voice, PlayButton } from '../../../primary-buttons/primary-buttons';\nimport AudioWeb, { AudioError } from '../../contribution/speak/audio-web';\nimport { isProduction } from '../../../../utility';\nimport { Suspense, lazy } from 'react';\nconst Lottie = lazy(() => import('react-lottie'));\nconst animationData = require('../../../layout/data.json');\nimport { shouldUseFixForIOSDevice } from '../../contribution/speak/utility';\n\nimport './avatar-setup.css';\n\nfunction resizeImage(file: File, maxSize: number): Promise<Blob> {\n  const reader = new FileReader();\n  const image = new Image();\n  const canvas = document.createElement('canvas');\n  const dataURItoBlob = (dataURI: string) => {\n    const bytes =\n      dataURI.split(',')[0].indexOf('base64') >= 0\n        ? atob(dataURI.split(',')[1])\n        : unescape(dataURI.split(',')[1]);\n    const mime = dataURI.split(',')[0].split(':')[1].split(';')[0];\n    const max = bytes.length;\n    const ia = new Uint8Array(max);\n    for (let i = 0; i < max; i++) ia[i] = bytes.charCodeAt(i);\n    return new Blob([ia], { type: mime });\n  };\n  const resize = () => {\n    let width = image.width;\n    let height = image.height;\n\n    if (width > height) {\n      if (width > maxSize) {\n        height *= maxSize / width;\n        width = maxSize;\n      }\n    } else {\n      if (height > maxSize) {\n        width *= maxSize / height;\n        height = maxSize;\n      }\n    }\n\n    canvas.width = width;\n    canvas.height = height;\n    canvas.getContext('2d').drawImage(image, 0, 0, width, height);\n    let dataUrl = canvas.toDataURL('image/jpeg');\n    return dataURItoBlob(dataUrl);\n  };\n\n  return new Promise((ok, no) => {\n    if (!file || !file.type.match(/image.*/)) {\n      no(new Error('Not an image'));\n      return;\n    }\n\n    reader.onload = (readerEvent: any) => {\n      image.onload = () => ok(resize());\n      image.src = readerEvent.target.result;\n    };\n    reader.readAsDataURL(file);\n  });\n}\n\ninterface PropsFromState {\n  api: API;\n  locale: Locale.State;\n  user: User.State;\n}\n\ninterface PropsFromDispatch {\n  addNotification: typeof Notifications.actions.addPill;\n  refreshUser: typeof User.actions.refresh;\n  addUpload: typeof Uploads.actions.add;\n}\n\ninterface Props\n  extends WithLocalizationProps,\n    PropsFromState,\n    PropsFromDispatch {}\n\ninterface State {\n  isSaving: boolean;\n  isRecording: boolean;\n  isPlaying: boolean;\n  counter: number;\n  clipStatus: 'fetching' | 'notStarted' | 'started' | 'starting' | 'recorded';\n  blobUrl: Blob;\n  avatarClipUrl: string | null;\n}\n\nclass AvatarSetup extends React.Component<Props, State> {\n  state: State = {\n    isSaving: false,\n    isRecording: false,\n    isPlaying: false,\n    counter: 3,\n    clipStatus: 'fetching',\n    blobUrl: new Blob(),\n    avatarClipUrl: null,\n  };\n\n  audio: AudioWeb;\n  isUnsupportedPlatform = false;\n  maxVolume = 0;\n  recordingStartTime = 0;\n  recordingStopTime = 0;\n  avatarRecordedBlobUrl: any = null;\n  audioRef = React.createRef<HTMLAudioElement>();\n\n  async componentDidMount() {\n    this.audio = new AudioWeb();\n    this.audio.setVolumeCallback(this.updateVolume.bind(this));\n\n    if (\n      !this.audio.isMicrophoneSupported() ||\n      !this.audio.isAudioRecordingSupported()\n    ) {\n      this.isUnsupportedPlatform = true;\n    }\n    let clip;\n    if (this.props.user.account.avatar_clip_url) {\n      clip = await this.props.api.fetchAvatarClip();\n    }\n    if (clip) this.setState({ avatarClipUrl: clip });\n    this.setState({ clipStatus: 'notStarted' });\n  }\n\n  async componentWillUnmount() {\n    if (!this.state.isRecording) return;\n    await this.audio.stop();\n  }\n\n  async saveFileAvatar(files: FileList) {\n    const { addNotification, api, getString, locale, refreshUser } = this.props;\n    this.setState({ isSaving: true });\n    const image = await resizeImage(files.item(0), 200);\n    const { error } = await api.saveAvatar('file', image);\n    if (['too_large'].includes(error)) {\n      addNotification(getString('file_' + error));\n    }\n    trackProfile('give-avatar', locale);\n\n    refreshUser();\n    this.setState({ isSaving: false });\n  }\n\n  private updateVolume = (volume: number) => {\n    if (volume !== 100 && volume > this.maxVolume) {\n      this.maxVolume = volume;\n    }\n  };\n\n  private playAvatarClip = async () => {\n    const { locale } = this.props;\n    trackVoiceAvatar('self-listen', locale);\n    if (!this.state.isPlaying) {\n      this.audioRef.current.src = this.state.avatarClipUrl;\n      this.audioRef.current.play();\n      this.setState({ isPlaying: true });\n    } else {\n      this.audioRef.current.pause();\n      this.audioRef.current.currentTime = 0;\n      this.setState({ isPlaying: false });\n    }\n  };\n\n  private playRecordedAvatarClip = async () => {\n    console.log(this.avatarRecordedBlobUrl);\n    if (!this.state.isPlaying) {\n      this.audioRef.current.src = this.avatarRecordedBlobUrl;\n      this.audioRef.current.play();\n      this.setState({ isPlaying: true });\n    } else {\n      this.audioRef.current.pause();\n      this.audioRef.current.currentTime = 0;\n      this.setState({ isPlaying: false });\n    }\n  };\n\n  private handleRecordClick = async () => {\n    if (this.state.isRecording) {\n      this.saveRecording();\n      return;\n    }\n\n    try {\n      await this.startRecording();\n\n      const clipTime = 5000;\n      setTimeout(async () => {\n        this.saveRecording();\n      }, clipTime);\n    } catch (err) {\n      if (!(err in AudioError)) {\n        throw err;\n      }\n    }\n  };\n\n  private startRecording = async () => {\n    const audioContext = new (window.AudioContext ||\n      window.webkitAudioContext)();\n    const processor = audioContext.createScriptProcessor(\n      shouldUseFixForIOSDevice() ? 2048 : 0,\n      1,\n      1\n    );\n    await this.audio.start(audioContext, processor);\n    this.maxVolume = 0;\n    this.recordingStartTime = Date.now();\n    this.recordingStopTime = 0;\n    this.setState({\n      isRecording: true,\n    });\n  };\n\n  private saveRecording = () => {\n    if (this.state.clipStatus === 'started') {\n      const RECORD_STOP_DELAY = 500;\n      setTimeout(async () => {\n        const info = await this.audio.stop();\n        this.avatarRecordedBlobUrl = info.url;\n        this.setState({ blobUrl: info.blob, clipStatus: 'recorded' });\n      }, RECORD_STOP_DELAY);\n      this.recordingStopTime = Date.now();\n      this.setState({\n        isRecording: false,\n      });\n    }\n  };\n\n  private async uploadAvatarClip() {\n    const {\n      api,\n      refreshUser,\n      addNotification,\n      addUpload,\n      getString,\n    } = this.props;\n    addUpload([\n      async () => {\n        try {\n          await api.saveAvatarClip(this.state.blobUrl);\n          this.setState({ clipStatus: 'notStarted' });\n          let clip = await this.props.api.fetchAvatarClip();\n          if (clip) this.setState({ avatarClipUrl: clip });\n        } catch (error) {\n          confirm(getString('upload-avatar-keeps-failing-retry'));\n        }\n      },\n      async () => {\n        addNotification(\n          <React.Fragment>\n            <CheckIcon />{' '}\n            <Localized id=\"clips-uploaded\">\n              <span />\n            </Localized>\n          </React.Fragment>\n        );\n      },\n    ]);\n    refreshUser();\n  }\n\n  private async deleteAvatarClip() {\n    const { api, refreshUser, addNotification, addUpload } = this.props;\n\n    try {\n      await api.deleteAvatarClip();\n      console.log('done');\n      this.setState({ clipStatus: 'notStarted' });\n      let clip = await this.props.api.fetchAvatarClip();\n      this.setState({ avatarClipUrl: clip || null });\n    } catch (error) {\n      console.error(error);\n    }\n\n    refreshUser();\n  }\n\n  private counter = async () => {\n    if (this.state.clipStatus !== 'notStarted') return;\n    this.audio.release();\n    await this.audio.init();\n    this.setState({ clipStatus: 'starting', counter: 3 });\n    const downloadTimer = setInterval(() => {\n      let tl = this.state.counter - 1;\n      this.setState({ counter: tl });\n      if (this.state.counter <= 0 && this.state.clipStatus === 'starting') {\n        this.setState({ clipStatus: 'started' });\n        const { locale } = this.props;\n        trackVoiceAvatar('create-voice-avatar', locale);\n        this.handleRecordClick();\n        clearInterval(downloadTimer);\n      }\n    }, 1000);\n  };\n\n  private updateAvatarClip = () => {\n    this.setState({\n      avatarClipUrl: null,\n      counter: 3,\n      clipStatus: 'notStarted',\n    });\n  };\n\n  private cancelRecording = async () => {\n    let clip = await this.props.api.fetchAvatarClip();\n    clip\n      ? this.setState({\n          avatarClipUrl: clip,\n          clipStatus: 'notStarted',\n          isRecording: false,\n        })\n      : this.setState({ clipStatus: 'notStarted', isRecording: false });\n  };\n\n  render() {\n    const {\n      addNotification,\n      api,\n      getString,\n      refreshUser,\n      user: { account },\n    } = this.props;\n    const { isPlaying, counter, clipStatus, avatarClipUrl } = this.state;\n    const avatarType =\n      account.avatar_url &&\n      account.avatar_url.startsWith('https://gravatar.com')\n        ? 'gravatar'\n        : null;\n\n    const defaultOptions = {\n      loop: true,\n      autoplay: true,\n      animationData: animationData,\n      rendererSettings: {\n        preserveAspectRatio: 'xMidYMid slice',\n      },\n    };\n\n    const hasClip = avatarClipUrl !== null;\n\n    return (\n      <div className=\"full-avatar-setup\">\n        {!isProduction() && (\n          <div className=\"clip\">\n            <audio\n              preload=\"auto\"\n              ref={this.audioRef}\n              onEnded={() => this.setState({ isPlaying: false })}\n              onError={() => this.setState({ isPlaying: false })}\n            />\n            {/*heading */}\n\n            {clipStatus === 'notStarted' && hasClip && (\n              <Localized id=\"change-your-avatar-clip\">\n                <h2 className=\"clip-title\" />\n              </Localized>\n            )}\n            {clipStatus === 'notStarted' && !hasClip && (\n              <Localized id=\"avatar-clip-title\">\n                <h2 className=\"clip-title\" />\n              </Localized>\n            )}\n            {clipStatus === 'starting' && (\n              <Localized id=\"avatar-clip-title\">\n                <h2 className=\"clip-title\" />\n              </Localized>\n            )}\n            {clipStatus === 'started' && (\n              <Localized id=\"recording-in-progress\">\n                <h2 className=\"clip-title\" />\n              </Localized>\n            )}\n            {clipStatus === 'recorded' && (\n              <Localized id=\"avatar-clip-recorded\">\n                <h2 className=\"clip-title\" />\n              </Localized>\n            )}\n            {/* Below fix div is for middle content of avatar setup like wave image, lottie animation */}\n            <div className=\"fix\">\n              {(clipStatus === 'notStarted' || clipStatus === 'starting') &&\n                (hasClip ? (\n                  <div className=\"group-1\">\n                    <div className=\"counter\">\n                      <PlayButton\n                        isPlaying={isPlaying}\n                        onClick={this.playAvatarClip}\n                      />\n                    </div>\n                  </div>\n                ) : (\n                  <div className=\"group-1\">\n                    {clipStatus === 'starting' && (\n                      <div className=\"counter\">\n                        <Voice>\n                          <div\n                            className={\n                              'counter-animation ' +\n                              (counter === 2 ? 'counter-2 ' : '') +\n                              (counter === 1 ? 'counter-1 ' : '') +\n                              (counter <= 0 ? 'counter-0 ' : '')\n                            }>\n                            <div>\n                              <span className=\"start-in\">\n                                Start in{' '}\n                                <p className=\"counter-digit\">{counter}</p>\n                              </span>\n                            </div>\n                          </div>\n                        </Voice>\n                      </div>\n                    )}\n                  </div>\n                ))}\n              {clipStatus === 'started' && (\n                <Suspense fallback={<div />}>\n                  <div className=\"lottie\">\n                    <Lottie options={defaultOptions} eventListeners={[]} />\n                    <div className=\"recording-stop\">\n                      <PlayButton\n                        isPlaying={true}\n                        onClick={this.handleRecordClick}\n                      />\n                    </div>\n                  </div>\n                </Suspense>\n              )}\n              {clipStatus === 'recorded' && (\n                <div className=\"lottiebg\">\n                  <div className=\"recorded-play\">\n                    <PlayButton\n                      isPlaying={isPlaying}\n                      onClick={this.playRecordedAvatarClip}\n                    />\n                  </div>\n                </div>\n              )}\n            </div>\n            {/* ALL buttons, first page delete and re-record buttons */}\n            {clipStatus === 'notStarted' && hasClip && (\n              <div>\n                <div className=\"but\">\n                  <div>\n                    <Button\n                      outline\n                      rounded\n                      className=\"primary-3 rerecord-but\"\n                      onClick={this.updateAvatarClip}>\n                      <MicIcon />\n                      <Localized id=\"re-record\">\n                        <span />\n                      </Localized>\n                    </Button>\n                  </div>\n                  <div>\n                    <Button\n                      outline\n                      rounded\n                      className=\"primary-2 delete-but\"\n                      onClick={this.deleteAvatarClip.bind(this)}>\n                      <TrashIcon />\n                      <Localized id=\"delete-voice\">\n                        <span />\n                      </Localized>\n                    </Button>\n                  </div>\n                </div>\n              </div>\n            )}\n\n            {clipStatus === 'notStarted' && !hasClip && (\n              <Button\n                outline\n                rounded\n                className=\"primary rerecord-but\"\n                onClick={this.counter}>\n                <MicIcon />\n                <Localized id=\"record-voice-wave\">\n                  <span />\n                </Localized>\n              </Button>\n            )}\n            {clipStatus === 'starting' && !hasClip && (\n              <Button\n                outline\n                rounded\n                className=\"primary cancel-but\"\n                onClick={this.cancelRecording}>\n                <CrossIcon />\n                <Localized id=\"cancel-avatar-clip-recording\">\n                  <span />\n                </Localized>\n              </Button>\n            )}\n            {clipStatus === 'started' && (\n              <Button\n                outline\n                rounded\n                className=\"primary cancel-but\"\n                onClick={this.cancelRecording}>\n                <CrossIcon />\n                <Localized id=\"cancel-avatar-clip-recording\">\n                  <span />\n                </Localized>\n              </Button>\n            )}\n            {clipStatus === 'recorded' && (\n              <div>\n                <div className=\"but\">\n                  <div>\n                    <Button\n                      outline\n                      rounded\n                      className=\"primary-3 \"\n                      onClick={this.cancelRecording}>\n                      <MicIcon />\n                      <Localized id=\"retry-voice-wave-recording\">\n                        <span />\n                      </Localized>\n                    </Button>\n                  </div>\n                  <div>\n                    <Button\n                      outline\n                      rounded\n                      className=\"primary-2 \"\n                      onClick={this.uploadAvatarClip.bind(this)}>\n                      <ShareIcon />\n                      <Localized id=\"ready-to-upload\">\n                        <span />\n                      </Localized>\n                    </Button>\n                  </div>\n                </div>\n                <div className=\"delete-voice\">\n                  <Localized id=\"delete-voice-clip\">\n                    <p\n                      className=\"delete-voice\"\n                      onClick={this.deleteAvatarClip.bind(this)}\n                    />\n                  </Localized>\n                </div>\n              </div>\n            )}\n            {hasClip ? (\n              <>\n                <Localized id=\"avatar-clip-fact\">\n                  <p className=\"create-a-custom-voice\" />\n                </Localized>\n              </>\n            ) : (\n              <Localized id=\"about-avatar-clip-recording\">\n                <p className=\"create-a-custom-voice voice-paragraph-2\" />\n              </Localized>\n            )}\n          </div>\n        )}\n        <div className=\"photo-avatar\">\n          <fieldset className=\"avatar-setup\" disabled={this.state.isSaving}>\n            <div className=\"file-upload\">\n              <label\n                onDragOver={event => {\n                  event.preventDefault();\n                }}\n                onDrop={event => {\n                  this.saveFileAvatar(event.dataTransfer.files);\n                  event.preventDefault();\n                }}>\n                <Localized id=\"browse-file-title\">\n                  <span className=\"title\" />\n                </Localized>\n                <Localized\n                  id=\"browse-file\"\n                  elems={{ browseWrap: <span className=\"browse\" /> }}>\n                  <span className=\"upload-label\" />\n                </Localized>\n                <input\n                  className=\"hide-input\"\n                  type=\"file\"\n                  accept=\"image/*\"\n                  onChange={event => {\n                    this.saveFileAvatar(event.target.files);\n                  }}\n                />\n              </label>\n            </div>\n\n            <button\n              className=\"connect\"\n              type=\"button\"\n              onClick={async () => {\n                this.setState({ isSaving: true });\n                const { error } = await api.saveAvatar(\n                  avatarType == 'gravatar' ? 'default' : 'gravatar'\n                );\n\n                if (['not_found'].includes(error)) {\n                  addNotification(getString('gravatar_' + error));\n                }\n\n                if (!error) {\n                  refreshUser();\n                }\n                this.setState({ isSaving: false });\n              }}>\n              <Localized id=\"connect-gravatar\">\n                <span />\n              </Localized>{' '}\n              {avatarType == 'gravatar' ? (\n                <CheckIcon className=\"check\" />\n              ) : (\n                <LinkIcon className=\"link\" />\n              )}\n            </button>\n          </fieldset>\n        </div>\n      </div>\n    );\n  }\n}\n\nexport default connect<PropsFromState, any>(\n  ({ api, locale, user }: StateTree) => ({ api, locale, user }),\n  {\n    addNotification: Notifications.actions.addPill,\n    refreshUser: User.actions.refresh,\n    addUpload: Uploads.actions.add,\n  }\n)(withLocalization(AvatarSetup));\n","import * as React from 'react';\nimport { useEffect, useState, useRef } from 'react';\nimport {\n  Localized,\n  withLocalization,\n  WithLocalizationProps,\n} from '@fluent/react';\nimport * as _ from 'lodash';\n\nimport { Country } from 'common';\nimport { LabeledInput } from '../ui/ui';\n\nimport './index.css';\n\nconst Option = ({\n  option,\n  label,\n  selected,\n  onClick,\n}: {\n  option: Country;\n  label: string;\n  selected: boolean;\n  onClick: Function;\n}) => {\n  return (\n    <div\n      className={`option ${selected ? 'selected' : ''}`}\n      key={option.id}\n      onClick={() => onClick(option)}>\n      <span>{label}</span>\n    </div>\n  );\n};\n\n/**\n * Countries live in the database under their English name, so the message id\n * is derived from it. Anything without a translation keeps the English name.\n */\nexport const countryNameId = (name: string) =>\n  'country-' +\n  name\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, '-')\n    .replace(/^-|-$/g, '');\n\nconst Search = ({\n  countries = [],\n  onChange,\n  value,\n  mostUsedCountries = [],\n  placeholder,\n  getString,\n}: {\n  countries: Array<Country>;\n  onChange: Function;\n  value: number;\n  mostUsedCountries: Array<number>;\n  placeholder?: string;\n} & WithLocalizationProps) => {\n  const placeholderText = placeholder || getString('select-option');\n  const displayName = (country: Country) =>\n    getString(countryNameId(country.name), null, country.name);\n  const wrapperRef = useRef(null);\n  const [isOpened, setIsOpened] = useState(false);\n  const [searchString, setSearchString] = useState('');\n  const [countriesToDisplay, setCountriesToDisplay] = useState([]);\n  const [mostUsedCountriesToDisplay, setMostUsedCountriesToDisplay] = useState(\n    []\n  );\n\n  const handleChange = (event: React.ChangeEvent<any>) => {\n    setSearchString(event.target.value);\n  };\n\n  const handleClickOutside = (event: any) => {\n    if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {\n      setIsOpened(false);\n    }\n  };\n\n  const handleSelectValue = (country: Country) => {\n    onChange(country.id);\n    setIsOpened(false);\n  };\n\n  useEffect(() => {\n    document.addEventListener('click', handleClickOutside, false);\n\n    return () => {\n      document.removeEventListener('click', handleClickOutside, false);\n    };\n  }, []);\n\n  useEffect(() => {\n    const mostUsedCountriesToDisplay = [];\n\n    for (let i = 0; i < mostUsedCountries.length; i++) {\n      const country = countries.find(\n        country => country.id === mostUsedCountries[i]\n      );\n      if (country) {\n        mostUsedCountriesToDisplay.push(country);\n      }\n    }\n\n    setMostUsedCountriesToDisplay(mostUsedCountriesToDisplay);\n  }, [countries, mostUsedCountries]);\n\n  useEffect(() => {\n    const countriesToDisplay = _.cloneDeep(countries);\n\n    setCountriesToDisplay(countriesToDisplay);\n  }, [countries, mostUsedCountries]);\n\n  useEffect(() => {\n    // if country is already selected then set search string to\n    // county name as a default search string\n    if (value) {\n      const selected = countries.find(c => c.id === value);\n\n      setSearchString(selected ? displayName(selected) : '');\n    }\n  }, [value, countries]);\n\n  useEffect(() => {\n    // if country is already selected then reset back to\n    // county name as a default search string when closing search popup\n    if (!isOpened && value) {\n      const selected = countries.find(c => c.id === value);\n\n      setSearchString(selected ? displayName(selected) : '');\n    }\n  }, [value, isOpened]);\n\n  useEffect(() => {\n    let countriesToDisplay;\n\n    if (searchString && !countries.find(c => displayName(c) === searchString)) {\n      const query = searchString.toLowerCase();\n      // match either what is on screen or the English name behind it\n      countriesToDisplay = countries.filter(\n        c =>\n          displayName(c).toLowerCase().includes(query) ||\n          c.name.toLowerCase().includes(query)\n      );\n    } else {\n      countriesToDisplay = _.cloneDeep(countries);\n    }\n\n    setCountriesToDisplay(countriesToDisplay);\n  }, [searchString, countries]);\n\n  // if there is no search string or it equals to some particular country (already selected/stored onn user) && we have mostUsedCountriesToDisplay option passed at all\n  // then we should display n top most used options\n  const shouldDisplayMostUsed =\n    (countries.find(c => displayName(c) === searchString) || !searchString) &&\n    mostUsedCountriesToDisplay.length;\n\n  return (\n    <div ref={wrapperRef} className=\"search-container\">\n      <Localized id=\"location-input\" attrs={{ label: true }}>\n        <LabeledInput\n          required\n          className=\"with-down-arrow\"\n          value={searchString}\n          onChange={handleChange}\n          onClick={() => setIsOpened(!isOpened)}\n          placeholder={placeholderText}\n        />\n      </Localized>\n      {isOpened && (\n        <div className=\"search-results\">\n          {shouldDisplayMostUsed && (\n            <div className=\"most-used\">\n              {mostUsedCountriesToDisplay.map(c => (\n                <Option\n                  option={c}\n                  label={displayName(c)}\n                  selected={c.id === value}\n                  onClick={handleSelectValue}\n                />\n              ))}\n              <hr style={{ margin: '0px' }} />\n            </div>\n          )}\n          {!!countriesToDisplay.length &&\n            countriesToDisplay\n              .filter(c =>\n                shouldDisplayMostUsed ? !mostUsedCountries.includes(c.id) : true\n              )\n              .map(c => (\n                <Option\n                  option={c}\n                  label={displayName(c)}\n                  selected={c.id === value}\n                  onClick={handleSelectValue}\n                />\n              ))}\n          {!countriesToDisplay.length && (\n            <Localized id=\"no-results\">\n              <div className=\"no-results\" />\n            </Localized>\n          )}\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport default withLocalization(Search);\n","import { UNDER_18 } from 'common';\n\nconst accents = {\n  '': 'Other Standard',\n  'English Standard': 'English Standard',\n  'English Dysarthric USA': 'English Dysarthric USA',\n  'English Dysarthric UK': 'English Dysarthric UK',\n  'English Dysarthric Australia': 'English Dysarthric Australia',\n  'English Dysarthric India': 'English Dysarthric India',\n  'English Dysarthric Canada': 'English Dysarthric Canada',\n  'English Dysarthric Other': 'English Dysarthric Other',\n  'Spanish Standard': 'Spanish Standard',\n  'Spanish Dysarthric': 'Spanish Dysarthric',\n  'Italian Standard': 'Italian Standard',\n  'Italian Dysarthric': 'Italian Dysarthric',\n  'German Standard': 'German Standard',\n  'German Dysarthric': 'German Dysarthric',\n  'French Standard': 'French Standard',\n  'French Dysarthric': 'French Dysarthric',\n  'Japanese Standard': 'Japanese Standard',\n  'Japanese Dysarthric': 'Japanese Dysarthric',\n  'Chinese Standard': 'Chinese Standard',\n  'Chinese Dysarthric': 'Chinese Dysarthric',\n  'Other Standard': 'Other Standard',\n  'Other Dysarthric': 'Other Dysarthric',\n};\n\nexport const ACCENTS: any = {\n  ca: {\n    balearic: 'balear',\n    central: 'central',\n    northwestern: 'nord-occidental',\n    northern: 'septentrional',\n    valencian: 'valencià',\n  },\n  cy: {\n    united_kingdom: 'Y Deyrnas Unedig Cymraeg',\n  },\n  de: {\n    germany: 'Deutschland Deutsch',\n    netherlands: 'Niederländisch Deutsch',\n    austria: 'Österreichisches Deutsch',\n    poland: 'Polnisch Deutsch',\n    switzerland: 'Schweizerdeutsch',\n    united_kingdom: 'Britisches Deutsch',\n    france: 'Französisch Deutsch',\n    denmark: 'Dänisch Deutsch',\n    belgium: 'Belgisches Deutsch',\n    hungary: 'Ungarisch Deutsch',\n    brazil: 'Brasilianisches Deutsch',\n    czechia: 'Tschechisch Deutsch',\n    united_states: 'Amerikanisches Deutsch',\n    slovakia: 'Slowakisch Deutsch',\n    russia: 'Russisch Deutsch',\n    kazakhstan: 'Kasachisch Deutsch',\n    italy: 'Italienisch Deutsch',\n    finland: 'Finnisch Deutsch',\n    slovenia: 'Slowenisch Deutsch',\n    canada: 'Kanadisches Deutsch',\n    bulgaria: 'Bulgarisch Deutsch',\n    greece: 'Griechisch Deutsch',\n    lithuania: 'Litauisch Deutsch',\n    luxembourg: 'Luxemburgisches Deutsch',\n    paraguay: 'Paraguayisch Deutsch',\n    romania: 'Rumänisch Deutsch',\n    liechtenstein: 'liechtensteinisches Deutscher',\n    namibia: 'Namibisch Deutsch',\n  },\n  en: {\n    us: 'United States English',\n    australia: 'Australian English',\n    england: 'England English',\n    canada: 'Canadian English',\n    philippines: 'Filipino',\n    hongkong: 'Hong Kong English',\n    indian: 'India and South Asia (India, Pakistan, Sri Lanka)',\n    ireland: 'Irish English',\n    malaysia: 'Malaysian English',\n    newzealand: 'New Zealand English',\n    scotland: 'Scottish English',\n    singapore: 'Singaporean English',\n    southatlandtic: 'South Atlantic (Falkland Islands, Saint Helena)',\n    african: 'Southern African (South Africa, Zimbabwe, Namibia)',\n    wales: 'Welsh English',\n    bermuda: 'West Indies and Bermuda (Bahamas, Bermuda, Jamaica, Trinidad)',\n  },\n  eo: {\n    internacia: 'Internacia',\n  },\n  fr: {\n    france: 'Français de France',\n    madagascar: 'Français de Madagascar',\n    cameroon: 'Français du Cameroun',\n    germany: 'Français d’Allemagne',\n    united_kingdom: 'Français du Royaume-Uni',\n    cote_d_ivoire: 'Français de Côte d’Ivoire',\n    tunisia: 'Français de Tunisie',\n    mali: 'Français du Mali',\n    algeria: 'Français d’Algérie',\n    canada: 'Français du Canada',\n    morocco: 'Français du Maroc',\n    burundi: 'Français du Burundi',\n    senegal: 'Français du Sénégal',\n    niger: 'Français du Niger',\n    netherlands: 'Français des Pays-Bas',\n    togo: 'Français de la République du Togo',\n    burkina_faso: 'Français du Burkina-Faso',\n    belgium: 'Français de Belgique',\n    congo_brazzaville: 'Français du Congo (Brazzaville)',\n    congo_kinshasa: 'Français du Congo (Kinshasa)',\n    italy: 'Français d’Italie',\n    benin: 'Français du Bénin',\n    romania: 'Français de Roumanie',\n    guinea: 'Français de Guinée',\n    chad: 'Français du Tchad',\n    central_african_republic: 'Français de République centrafricaine',\n    united_states: 'Français des États-Unis',\n    switzerland: 'Français de Suisse',\n    portugal: 'Français du Portugal',\n    gabon: 'Français du Gabon',\n    syria: 'Français de Syrie',\n    greece: 'Français de Grèce',\n    austria: 'Français d’Autriche',\n    ireland: 'Français d’Irlande',\n    reunion: 'Français de La Réunion',\n    mauritania: 'Français de Mauritanie',\n    luxembourg: 'Français du Luxembourg',\n    haiti: 'Français d’Haïti',\n    comoros: 'Français des Comores',\n    martinique: 'Français de Martinique',\n    guadeloupe: 'Français de Guadeloupe',\n    hungary: 'Français d’Hongrie',\n    new_caledonia: 'Français de Nouvelle-Calédonie',\n    french_polynesia: 'Français de Polynésie française',\n    french_guiana: 'Français de Guyane',\n    vanuatu: 'Français du Vanuatu',\n    mayotte: 'Français de Mayotte',\n    cyprus: 'Français de Chypre',\n    equatorial_guinea: 'Français de Guinée équatoriale',\n    seychelles: 'Français des Seychelles',\n    malta: 'Français de Malte',\n    mauritius: 'Français de l’Île Maurice',\n    st_martin: 'Français de Saint-Martin',\n    monaco: 'Français de Monaco',\n    lebanon: 'Français du Liban',\n    djibouti: 'Français de Djibouti',\n    wallis_et_futuna: 'Français de Wallis et Futuna',\n    st_barthelemy: 'Français de Saint-Barthélemy',\n    andorra: 'Français d’Andorre',\n    st_pierre_et_miquelon: 'Français de Saint-Pierre-et-Miquelon',\n    rwanda: 'Français du Rwanda',\n  },\n  nl: {\n    netherlands: 'Nederlands Nederlands',\n    belgium: 'Belgisch Nederlands',\n    suriname: 'Surinaams Nederlands',\n    france: 'Frans Nederlands',\n    germany: 'Duits Nederlands',\n    curacao: 'Nederlands van Curaçao',\n    aruba: 'Nederlands van Aruba',\n    sint_maarten: 'Nederlands van Sint-Maarten',\n    south_africa: 'Zuid-Afrikaans Nederlands',\n    namibia: 'Namibisch Nederlands',\n    indonesia: 'Indonesisch Nederlands',\n  },\n  'ga-IE': {\n    mumhain: 'Gaeilge na Mumhan',\n    connachta: 'Gaeilge Chonnacht',\n    ulaidh: 'Gaeilge Uladh',\n  },\n};\n\nexport const AGES = {\n  '': '',\n  [UNDER_18]: '< 18',\n  twenties: '18 - 29',\n  thirties: '30 - 39',\n  fourties: '40 - 49',\n  fifties: '50 - 59',\n  sixties: '60 - 69',\n  seventies: '70 - 79',\n  eighties: '80 - 89',\n  nineties: '> 89',\n};\n\n/**\n * Age brackets people could pick before the 18+ rule replaced them. \"teens\"\n * straddled the cutoff, so accounts already holding it keep rendering it -\n * otherwise reopening the form would show an empty field and quietly drop the\n * answer on the next save. Not offered to anyone choosing afresh.\n */\nexport const LEGACY_AGES = {\n  teens: '13 - 18',\n};\n\nexport const SEXES = {\n  '': '',\n  male: 'Male',\n  female: 'Female',\n  other: 'Other',\n};\n\nexport const DIAGNOSES = {\n  '': '',\n  cp: 'Cerebral Palsy (CP)',\n  tbi: 'Traumatic Brain Injury (TBI)',\n  ds: 'Down Syndrome (DS)',\n  stroke_nerve_injury: 'Stroke / Nerve Injury',\n  ms: 'Multiple Sclerosis (MS)',\n  als_mnd: 'ALS / Motor Neuron Disease (MND)',\n  autism: 'Autism Spectrum Disorder',\n  parkinsons: `Parkinson's Disease`,\n  apraxia_of_speech: 'Apraxia of Speech',\n  hearing_loss: 'Deafness / Severe Hearing Loss',\n  glossectomy: 'Glossectomy (partial / full)',\n  electrolarynx: 'Electrolarynx',\n  other: 'Other',\n  rather_not_say: 'Rather not say',\n};\n\n/**\n * Codes people were able to pick before the list above replaced them. They are\n * still stored against existing accounts, so the picker keeps rendering one\n * when it is the value already on the account - otherwise reopening the form\n * would show an empty field and quietly drop the answer on the next save.\n * Not offered to anyone choosing afresh.\n */\nexport const LEGACY_DIAGNOSES = {\n  cerebral_palsy: 'Cerebral Palsy (CP)',\n  stroke: 'Stroke / Nerve Injury',\n  als: 'ALS',\n  parkinsons_disease: `Parkinson's disease`,\n  down_syndrome: 'Down syndrome',\n  multiple_sclerosis: 'Multiple Sclerosis',\n  oral_injury: 'Oral injury',\n};\n","import { ChallengeDuration, ChallengeTeamToken } from 'common';\nimport { UserClient } from 'common';\n\nexport const challengeLogos: {\n  [key in ChallengeTeamToken]: {\n    background: string;\n    border: boolean;\n    url: string;\n  };\n} = {\n  ibm: { background: '#fff', border: true, url: require('./images/ibm.svg') },\n  lenovo: {\n    background: '#fff',\n    border: true,\n    url: require('./images/lenovo.svg'),\n  },\n  mozilla: {\n    background: '#000',\n    border: false,\n    url: require('./images/mozilla.svg'),\n  },\n  sap: { background: '#fff', border: true, url: require('./images/sap.svg') },\n};\n\nconst isValidDate = (dateStr: string) => {\n  const dateObj = new Date(dateStr);\n  return dateObj instanceof Date && !isNaN(dateObj.getTime());\n};\n\nconst getNow = () => {\n  const dateParam =\n    location.search && location.search.match(/date=(\\d+-\\d+-\\d+)/);\n  const date = dateParam?.[1];\n  return date && isValidDate(date) ? new Date(date) : new Date();\n};\n\nexport const isChallengeLive = (challenge: ChallengeDuration) => {\n  const now = getNow();\n  return now >= challenge.start && now < challenge.end;\n};\n\nexport const isBeforeChallenge = (challenge: ChallengeDuration) => {\n  const now = getNow();\n  return now < challenge.start;\n};\n\nexport const pilotDates: ChallengeDuration = {\n  start: new Date('2019-11-19'),\n  end: new Date('2019-12-10'),\n};\n\nexport const isEnrolled = (account: UserClient) =>\n  account?.enrollment?.challenge;\n\nexport const weeklyChallengeCopy = [\n  {\n    title: 'Sign up and Contribute',\n    subtitle: 'Win a prize by being the team with the highest sign up rate',\n    explanation:\n      'This is the percentage of team invites that have been accepted out of the current total sent.',\n  },\n  {\n    title: \"Let's get social\",\n    subtitle: 'The most socially active team wins the prize',\n    explanation:\n      'This is the number of invites your team has sent inviting others to join the Open Voice Challenge',\n  },\n  {\n    title: 'Top the Leaderboard',\n    subtitle:\n      'The team that validates the highest percentage of voice clips wins the prize',\n    explanation:\n      'This is the percentage of clips the team has accurately validated',\n  },\n];\n\nexport const FINAL_CHALLENGE_WEEK = weeklyChallengeCopy.length - 1;\n","import {\n  Localized,\n  withLocalization,\n  WithLocalizationProps,\n} from '@fluent/react';\nimport * as React from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Redirect, RouteComponentProps, withRouter } from 'react-router';\nimport Search from '../../../search';\nimport {\n  useAction,\n  useAPI,\n  useSubscriptions,\n} from '../../../../hooks/store-hooks';\nimport { Country, UNDER_18 } from 'common';\nimport { trackProfile } from '../../../../services/tracker';\nimport {\n  AGES,\n  SEXES,\n  DIAGNOSES,\n  LEGACY_AGES,\n  LEGACY_DIAGNOSES,\n} from '../../../../stores/demographics';\nimport { Notifications } from '../../../../stores/notifications';\nimport { useTypedSelector } from '../../../../stores/tree';\nimport { Uploads } from '../../../../stores/uploads';\nimport { User } from '../../../../stores/user';\nimport URLS from '../../../../urls';\nimport { useLocale } from '../../../locale-helpers';\n\nimport {\n  Hr,\n  LabeledCheckbox,\n  LabeledInput,\n  LabeledSelect,\n} from '../../../ui/ui';\nimport { isEnrolled } from '../../dashboard/challenge/constants';\n\nimport './info.css';\nimport { generateGUID, generateToken } from '../../../../utility';\nimport {\n  EVENT_CATEGORIES,\n  EVENT_NAMES,\n  trackGoogleAnalyticsEvent,\n} from '../../../../services/ga-event-tracker';\n\nconst pick = require('lodash.pick');\nconst { Tooltip } = require('react-tippy');\n\nconst Options = withLocalization(\n  ({\n    children,\n    getString,\n  }: {\n    children: { [key: string]: string };\n  } & WithLocalizationProps) => (\n    <>\n      {Object.entries(children).map(([key, value]) => (\n        <option key={key} value={key}>\n          {getString(key, null, value)}\n        </option>\n      ))}\n    </>\n  )\n);\n\ntype Locales = { locale: string; accent: string }[];\n\nfunction ProfilePage({\n  getString,\n  history,\n}: WithLocalizationProps & RouteComponentProps<any, any, any>) {\n  const api = useAPI();\n  const [locale, toLocaleRoute] = useLocale();\n  const user = useTypedSelector(({ user }) => user);\n  const { account, userClients } = user;\n\n  const addNotification = useAction(Notifications.actions.addPill);\n  const addUploads = useAction(Uploads.actions.add);\n  ``;\n  const saveAccount = useAction(User.actions.saveAccount);\n  const { subscriptions, fetchSubscriptions } = useSubscriptions();\n\n  const [userFields, setUserFields] = useState<{\n    username: string;\n    visible: number | string;\n    age: string;\n    gender: string;\n    diagnosis: string;\n    sendEmails: boolean;\n    privacyAgreed: boolean;\n    termsAgreed: boolean;\n    country_id: number | null;\n  }>({\n    username: '',\n    visible: 0,\n    age: '',\n    gender: '',\n    diagnosis: '',\n    sendEmails: true,\n    privacyAgreed: false,\n    termsAgreed: false,\n    country_id: null,\n  });\n  const {\n    username,\n    visible,\n    age,\n    gender,\n    diagnosis,\n    sendEmails,\n    privacyAgreed,\n    termsAgreed,\n    country_id,\n  } = userFields;\n\n  // A retired bracket stays selectable only for the account already carrying it.\n  const ageOptions =\n    age && !(age in AGES)\n      ? { ...AGES, [age]: LEGACY_AGES[age as keyof typeof LEGACY_AGES] || age }\n      : AGES;\n  const isUnderage = age === UNDER_18;\n  // A retired code stays selectable only for the account already carrying it.\n  const diagnosisOptions =\n    diagnosis && !(diagnosis in DIAGNOSES)\n      ? {\n          ...DIAGNOSES,\n          [diagnosis]:\n            LEGACY_DIAGNOSES[diagnosis as keyof typeof LEGACY_DIAGNOSES] ||\n            diagnosis,\n        }\n      : DIAGNOSES;\n  const [countries, setCountries] = useState<Array<Country>>([]);\n  const [locales, setLocales] = useState<Locales>([]);\n  const [isInitialized, setIsInitialized] = useState(false);\n  const [isSaving, setIsSaving] = useState(false);\n  const [isSubmitted, setIsSubmitted] = useState(false);\n  const isEnrolledInChallenge =\n    user?.userClients[0]?.enrollment || isEnrolled(account);\n\n  const fetchCountries = async () => {\n    try {\n      const countries = await api.fetchCountries();\n      setCountries(countries);\n    } catch (err) {\n      console.error(`Error occurred when fetching country list ${err}`);\n    }\n  };\n\n  useEffect(() => {\n    fetchCountries();\n  }, []);\n\n  useEffect(() => {\n    const isUserProfileUpdate = account && account.username;\n\n    if (isUserProfileUpdate) {\n      setUserFields({\n        ...userFields,\n        sendEmails: subscriptions.inMailingList,\n      });\n    }\n  }, [account, subscriptions.inMailingList]);\n\n  useEffect(() => {\n    if (user.isFetchingAccount || isInitialized) {\n      return;\n    }\n    setIsInitialized(true);\n\n    if (!account && userClients.length == 0) {\n      history.push('/');\n    }\n\n    setUserFields({\n      ...userFields,\n      visible: 0,\n      ...pick(user, 'age', 'username', 'gender', 'diagnosis', 'country_id'),\n      ...(account\n        ? pick(\n            account,\n            'age',\n            'username',\n            'gender',\n            'diagnosis',\n            'visible',\n            'country_id'\n          )\n        : {\n            age: userClients.reduce((init, u) => u.age || init, ''),\n            gender: userClients.reduce((init, u) => u.gender || init, ''),\n            diagnosis: userClients.reduce((init, u) => u.diagnosis || init, ''),\n          }),\n      privacyAgreed: Boolean(account) || user.privacyAgreed,\n      termsAgreed: Boolean(account) || user.termsAgreed,\n    });\n\n    let locales: Locales = [];\n    if (!account) {\n      locales = userClients.reduce(\n        (locales, u) => locales.concat(u.locales || []),\n        []\n      );\n      locales = locales.filter(\n        (l1, i) => i == locales.findIndex(l2 => l2.locale == l1.locale)\n      );\n    }\n    setLocales(account ? account.locales : locales);\n  }, [user]);\n\n  const handleChangeForLocation = (country_id: number) => {\n    setUserFields({\n      ...userFields,\n      ['country_id']: country_id,\n    });\n  };\n\n  const handleChangeFor = (field: string) => ({\n    target,\n  }: React.ChangeEvent<any>) => {\n    if (field === 'sendEmails') {\n      trackGoogleAnalyticsEvent(\n        target.checked\n          ? EVENT_NAMES.JOIN_MAILING_LIST\n          : EVENT_NAMES.LEAVE_MAILING_LIST,\n        EVENT_CATEGORIES.CHECKBOX_USAGE,\n        target.checked\n          ? 'Join mailing list is checked'\n          : 'Join mailing list is unchecked'\n      );\n    }\n    setUserFields({\n      ...userFields,\n      [field]: target.type == 'checkbox' ? target.checked : target.value,\n    });\n  };\n\n  const submit = useCallback(() => {\n    if (!user.account) {\n      trackGoogleAnalyticsEvent(\n        EVENT_NAMES.CREATE_ACCOUNT,\n        EVENT_CATEGORIES.BUTTON_USAGE,\n        'Save button is clicked'\n      );\n      trackProfile('create', locale);\n    } else {\n      trackGoogleAnalyticsEvent(\n        EVENT_NAMES.PROFILE_UPDATED,\n        EVENT_CATEGORIES.BUTTON_USAGE,\n        'Save button is clicked'\n      );\n    }\n\n    setIsSaving(true);\n    setIsSubmitted(true);\n\n    // if there is username on account it means that user completed registration process\n    // and now he just updates existing account\n    const isUserProfileUpdate = account && account.username;\n    const userDataFromLocalStorage = JSON.parse(\n      localStorage.getItem('userdata')\n    );\n\n    const data = {\n      ...pick(\n        userFields,\n        'username',\n        'age',\n        'gender',\n        'diagnosis',\n        'country_id'\n      ),\n      // generate token as well if it's newly created user\n      ...(isUserProfileUpdate && { auth_token: generateToken() }),\n      locales: locales.filter(l => l.locale),\n      visible: JSON.parse(visible.toString()),\n      // if it's profile update then just use existing userId (it's gonna be updated)\n      // otherwise generate new user id that is gonna be used for a newly registered user\n      client_id: isUserProfileUpdate\n        ? user?.account?.client_id\n        : generateGUID(),\n      ...(userDataFromLocalStorage && {\n        client_id_to_delete: userDataFromLocalStorage.userId,\n      }),\n      enrollment: user.userClients[0].enrollment || {\n        team: null,\n        challenge: null,\n        invite: null,\n      },\n    };\n\n    addUploads([\n      async () => {\n        await saveAccount(data);\n        await api.subscribeToEnsembleMailingList(\n          user.userClients[0].email,\n          sendEmails\n        );\n        fetchSubscriptions();\n\n        addNotification(getString('profile-form-submit-saved'));\n        setIsSaving(false);\n\n        if (!isUserProfileUpdate) {\n          history.push('/speak');\n        }\n      },\n    ]);\n  }, [api, getString, locale, locales, user, userFields]);\n\n  if (!isInitialized) {\n    return null;\n  }\n\n  if (!isSaving && isSubmitted && isEnrolledInChallenge) {\n    return (\n      <Redirect\n        to={{\n          pathname: toLocaleRoute(URLS.DASHBOARD + URLS.CHALLENGE),\n          state: {\n            showOnboardingModal: true,\n            earlyEnroll: window.location.search.includes('achievement=1'),\n          },\n        }}\n      />\n    );\n  }\n\n  const shouldDisableSubmit =\n    isSaving ||\n    !privacyAgreed ||\n    !termsAgreed ||\n    !username.trim() ||\n    !country_id ||\n    !age ||\n    isUnderage ||\n    !gender ||\n    !diagnosis;\n\n  return (\n    <div className=\"profile-info\">\n      {!user.account && (\n        <Localized id=\"thanks-for-account\">\n          <h2 />\n        </Localized>\n      )}\n\n      <div className=\"form-fields\">\n        <Localized id=\"profile-form-username\" attrs={{ label: true }}>\n          <LabeledInput\n            required\n            value={username}\n            onChange={handleChangeFor('username')}\n          />\n        </Localized>\n\n        <div>\n          <Localized id=\"profile-form-age\" attrs={{ label: true }}>\n            <LabeledSelect\n              required\n              value={age}\n              onChange={handleChangeFor('age')}>\n              <Options>{ageOptions}</Options>\n            </LabeledSelect>\n          </Localized>\n\n          {isUnderage && (\n            <Localized id=\"profile-form-age-under-18\">\n              <p className=\"field-error\" role=\"alert\" />\n            </Localized>\n          )}\n        </div>\n\n        <Localized id=\"profile-form-gender\" attrs={{ label: true }}>\n          <LabeledSelect\n            required\n            value={gender}\n            onChange={handleChangeFor('gender')}>\n            <Options>{SEXES}</Options>\n          </LabeledSelect>\n        </Localized>\n\n        <Localized id=\"profile-form-diagnosis\" attrs={{ label: true }}>\n          <LabeledSelect\n            required\n            value={diagnosis}\n            onChange={handleChangeFor('diagnosis')}>\n            <Options>{diagnosisOptions}</Options>\n          </LabeledSelect>\n        </Localized>\n      </div>\n\n      <Hr />\n\n      {!user.account?.basket_token && (\n        <>\n          <div className=\"email-location-section\">\n            <Search\n              countries={countries}\n              value={country_id}\n              onChange={handleChangeForLocation}\n              // Israel, USA, Great Britain, Canada, Australia\n              mostUsedCountries={[87, 190, 71, 33, 10]}\n              placeholder={getString('select-location')}\n            />\n\n            <div className=\"email-input-container\">\n              <Tooltip\n                arrow\n                html={\n                  <p style={{ color: 'black' }}>\n                    {getString('change-email-settings')}\n                  </p>\n                }\n                theme=\"grey-tooltip\">\n                <Localized id=\"email-input\" attrs={{ label: true }}>\n                  <LabeledInput value={user.userClients[0].email} disabled />\n                </Localized>\n              </Tooltip>\n            </div>\n          </div>\n\n          <div className=\"checkboxes\">\n            <div />\n\n            <div>\n              <LabeledCheckbox\n                label={\n                  <>\n                    <Localized id=\"email-opt-in-info-title\">\n                      <strong />\n                    </Localized>\n\n                    <br />\n\n                    <Localized id=\"email-opt-in-info-sub-with-challenge\">\n                      <span className=\"email-opt-in-info-sub-with-challenge\" />\n                    </Localized>\n                  </>\n                }\n                onChange={handleChangeFor('sendEmails')}\n                checked={sendEmails}\n              />\n\n              {!user.account && !isSubmitted && (\n                <>\n                  <LabeledCheckbox\n                    label={\n                      <>\n                        <Localized id=\"accept-privacy-title\">\n                          <strong />\n                        </Localized>\n                        <Localized\n                          id=\"accept-privacy\"\n                          elems={{\n                            privacyLink: (\n                              <a href={URLS.PRIVACY} target=\"_blank\" />\n                            ),\n                          }}>\n                          <span />\n                        </Localized>\n                      </>\n                    }\n                    checked={privacyAgreed}\n                    onChange={handleChangeFor('privacyAgreed')}\n                  />\n\n                  <LabeledCheckbox\n                    label={\n                      <>\n                        <Localized id=\"accept-terms-title\">\n                          <strong />\n                        </Localized>\n                        <Localized\n                          id=\"accept-terms\"\n                          elems={{\n                            termsLink: <a href={URLS.TERMS} target=\"_blank\" />,\n                          }}>\n                          <span />\n                        </Localized>\n                      </>\n                    }\n                    checked={termsAgreed}\n                    onChange={handleChangeFor('termsAgreed')}\n                  />\n                </>\n              )}\n            </div>\n          </div>\n\n          <Hr />\n        </>\n      )}\n\n      <div className=\"buttons\">\n        <Localized id=\"profile-form-submit-save\">\n          <button\n            className=\"btn btn-primary\"\n            disabled={shouldDisableSubmit}\n            onClick={submit}\n          />\n        </Localized>\n      </div>\n    </div>\n  );\n}\n\nexport default withLocalization(withRouter(ProfilePage));\n","import {\n  Localized,\n  withLocalization,\n  WithLocalizationProps,\n} from '@fluent/react';\nimport * as React from 'react';\nimport { useEffect } from 'react';\nimport { connect } from 'react-redux';\nimport { UserClient } from 'common';\nimport { Notifications } from '../../../../stores/notifications';\nimport StateTree from '../../../../stores/tree';\nimport { User } from '../../../../stores/user';\nimport URLS from '../../../../urls';\nimport { getManageSubscriptionURL } from '../../../../utility';\nimport { LocaleLink } from '../../../locale-helpers';\nimport { InfoIcon, PenIcon, SettingsIcon } from '../../../ui/icons';\nimport {\n  LabeledCheckbox,\n  LabeledInput,\n  LinkButton,\n  Toggle,\n} from '../../../ui/ui';\n\nimport './settings.css';\nimport { useIsSubscribed } from '../../../../hooks/store-hooks';\n\nconst Section = ({\n  title,\n  titleAction,\n  className = '',\n  children,\n  ...props\n}: {\n  title: string;\n  titleAction?: React.ReactNode;\n  className?: string;\n  children?: React.ReactNode;\n}) => (\n  <section className={'user-setting ' + className} {...props}>\n    <div className=\"section-title\">\n      <h2>{title}</h2>\n      {titleAction}\n    </div>\n    {children && <div className=\"section-body\">{children}</div>}\n  </section>\n);\n\ninterface PropsFromState {\n  account: UserClient;\n  locale: string;\n}\n\ninterface PropsFromDispatch {\n  addNotification: typeof Notifications.actions.addPill;\n  saveAccount: any;\n}\n\ninterface Props\n  extends WithLocalizationProps,\n    PropsFromState,\n    PropsFromDispatch {}\n\nfunction Settings(props: Props) {\n  const { account, addNotification, getString, saveAccount } = props;\n  const isSubscribed = useIsSubscribed();\n\n  useEffect(() => {\n    const { pathname, search } = location;\n    if (search.includes('success=false')) {\n      addNotification(\n        <Localized id=\"email-already-used\">\n          <span />\n        </Localized>,\n        'error'\n      );\n      history.replaceState({}, null, pathname);\n    } else if (search.includes('success=true')) {\n      addNotification(\n        <Localized id=\"profile-form-submit-saved\">\n          <span />\n        </Localized>\n      );\n      history.replaceState({}, null, pathname);\n    }\n  }, []);\n\n  return (\n    <div>\n      {account.basket_token && (\n        <Section\n          title={getString('email-subscriptions')}\n          titleAction={\n            <a\n              className=\"manage-subscriptions\"\n              href={getManageSubscriptionURL(account)}\n              target=\"_blank\"\n              rel=\"noopener noreferrer\">\n              <Localized id=\"manage-subscriptions\">\n                <span />\n              </Localized>\n              <SettingsIcon />\n            </a>\n          }>\n          <div className=\"email-section\">\n            {isSubscribed == null ? (\n              <div />\n            ) : (\n              <LabeledCheckbox\n                disabled={true}\n                checked={isSubscribed}\n                label={\n                  <Localized id=\"email-opt-in-info\">\n                    <span />\n                  </Localized>\n                }\n              />\n            )}\n            <div className=\"privacy-and-terms\">\n              <InfoIcon />\n              <div>\n                <Localized\n                  id=\"email-opt-in-privacy\"\n                  elems={{\n                    privacyLink: <LocaleLink to={URLS.PRIVACY} blank />,\n                  }}>\n                  <div />\n                </Localized>\n                <br />\n                <Localized id=\"read-terms-q\">\n                  <LocaleLink to={URLS.TERMS} className=\"terms\" blank />\n                </Localized>\n              </div>\n            </div>\n          </div>\n        </Section>\n      )}\n\n      <Section title={getString('contribution-experience')} className=\"box\">\n        <div>\n          <Localized id=\"skip-submission-feedback\">\n            <h3 className=\"feedback-toggle-title\" />\n          </Localized>\n          <Toggle\n            offText=\"off\"\n            onText=\"on\"\n            defaultChecked={account.skip_submission_feedback}\n            onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n              saveAccount({\n                skip_submission_feedback: event.target.checked,\n              })\n            }\n          />\n          <Localized id=\"skip-submission-description\">\n            <p className=\"skip-submission-description\" />\n          </Localized>\n          {/*<Localized id=\"skip-submission-note\">*/}\n          {/*  <p className=\"skip-submission-note\" />*/}\n          {/*</Localized>*/}\n        </div>\n\n        <div className=\"images\">\n          <img\n            src={require('./settings-image.svg')}\n            alt=\"Submission Success Screenshot\"\n          />\n        </div>\n      </Section>\n    </div>\n  );\n}\n\nexport default connect<PropsFromState, PropsFromDispatch>(\n  ({ locale, user }: StateTree) => ({\n    account: user.account,\n    locale,\n  }),\n  {\n    addNotification: Notifications.actions.addPill,\n    saveAccount: User.actions.saveAccount,\n  }\n)(withLocalization(Settings));\n","import { Localized } from '@fluent/react';\nimport * as React from 'react';\nimport { connect } from 'react-redux';\nimport { Redirect, Route, Switch } from 'react-router';\nimport { NavLink } from 'react-router-dom';\nimport { User } from '../../../stores/user';\nimport StateTree from '../../../stores/tree';\nimport URLS from '../../../urls';\nimport { localeConnector, LocalePropsFromState } from '../../locale-helpers';\nimport {\n  UserIcon,\n  UserPlusIcon,\n} from '../../ui/icons';\nimport AvatarSetup from './avatar-setup/avatar-setup';\nimport InfoPage from './info/info';\nimport Settings from './settings/settings';\n\nimport './layout.css';\n\ninterface PropsFromState {\n  user: User.State;\n}\n\ninterface Props extends LocalePropsFromState, PropsFromState {}\n\nconst Layout = ({ toLocaleRoute, user }: Props) => {\n  const [infoRoute, avatarRoute, prefRoute] = [\n    URLS.PROFILE_INFO\n  ].map(r => toLocaleRoute(r));\n  return (\n    <div className=\"profile-layout\">\n      <div className=\"profile-nav\">\n        <div className=\"links\">\n          {[\n            {\n              route: infoRoute,\n              ...(user.account\n                ? { icon: <UserIcon />, id: 'profile' }\n                : { icon: <UserPlusIcon />, id: 'build-profile' }),\n            }\n          ]\n            .slice(0, user.account ? Infinity : 1)\n            .map(({ route, icon, id }) => (\n              <NavLink key={route} to={route}>\n                {icon}\n                <Localized id={id}>\n                  <span className=\"text\" />\n                </Localized>\n              </NavLink>\n            ))}\n        </div>\n      </div>\n      <div className=\"content\">\n        <Switch>\n          <Route exact path={infoRoute} component={InfoPage} />\n          {[\n            { route: avatarRoute, Component: AvatarSetup },\n            { route: prefRoute, Component: Settings },\n            // { route: deleteRoute, Component: DeleteProfile },\n          ].map(({ route, Component }) => (\n            <Route\n              key={route}\n              exact\n              path={route}\n              render={_props =>\n                // @ts-ignore\n                user.account ? <Component /> : <Redirect to={infoRoute} />\n              }\n            />\n          ))}\n          <Route\n            render={() => <Redirect to={toLocaleRoute(URLS.PROFILE_INFO)} />}\n          />\n        </Switch>\n      </div>\n    </div>\n  );\n};\n\nexport default connect<PropsFromState>(({ user }: StateTree) => ({ user }))(\n  localeConnector(Layout)\n);\n"],"sourceRoot":""}