<commit_before>import {ipcRenderer, remote, shell} from 'electron';
import _ from 'lodash';
import $j from 'jquery/dist/jquery.slim';

// Note: `./` == `/app/dist/renderer/views`, not `js`
import {handleTrafficLightsClicks, $, disposeObservers} from '../js/utils';

const {app, dialog, getCurrentWindow} = remote;

const aperture = require('aperture');

const plugins = remote.require('../main/plugins').default;

const settingsValues = app.kap.settings.getAll();

// Observers that should be disposed when the window unloads
const observersToDispose = [];

document.addEventListener('DOMContentLoaded', async () => {
  // Element definitions
  const allowAnalyticsCheckbox = $('#allow-analytics');
  const audioInputDeviceSelector = $('.js-audio-input-device-selector');
  const chooseSaveDirectoryBtn = $('.js-choose-save');
  const fpsLabel = $('.fps-slider .js-middle-label');
  const fpsSlider = $('.fps-slider input');
  const header = $('header');
  const highlightClicksCheckbox = $('#highlight-clicks');
  const openOnStartupCheckbox = $('#open-on-startup');
  const saveToDescription = $('.js-save-to-description');
  const showCursorCheckbox = $('#show-cursor');
  const openPluginsFolder = $('.js-open-plugins');

  const electronWindow = getCurrentWindow();

  electronWindow.setSheetOffset(header.offsetHeight);
  handleTrafficLightsClicks();

  // Init the shown settings
  saveToDescription.dataset.fullPath = settingsValues.kapturesDir;
  saveToDescription.setAttribute('title', settingsValues.kapturesDir);
  saveToDescription.innerText = `.../${settingsValues.kapturesDir.split('/').pop()}`;
  openOnStartupCheckbox.checked = settingsValues.openOnStartup;
  allowAnalyticsCheckbox.checked = settingsValues.allowAnalytics;
  showCursorCheckbox.checked = settingsValues.showCursor;
  if (settingsValues.showCursor === false) {
    highlightClicksCheckbox.disabled = true;
  } else {
    highlightClicksCheckbox.checked = settingsValues.highlightClicks;
  }
  fpsSlider.value = settingsValues.fps;
  fpsLabel.innerText = `${settingsValues.fps} FPS`;

  for (const device of await aperture.audioDevices()) {
    const option = document.createElement('option');
    option.value = device.id;
    option.text = device.name;
    audioInputDeviceSelector.add(option);
  }

  audioInputDeviceSelector.value = settingsValues.audioInputDeviceId;

  const tabs = $j('.prefs-nav > a');
  tabs.on('click', function (event) {
    event.preventDefault();
    tabs.removeClass('is-active');
    $j(this).addClass('is-active');

    const panes = $j('.prefs-sections > section');
    const paneName = $j(this).data('pane');
    panes.addClass('hidden');
    panes.filter(`[data-pane="${paneName}"]`).removeClass('hidden');
  });

  const pluginListTemplate = _.template(`
    <% _.forEach(plugins, plugin => { %>
      <div class="preference container">
        <div class="preference-part">
          <div class="preference-content">
            <div class="preference__title">
              <a class="preference__url o-link" href data-url="<%- plugin.homepage || plugin.links.homepage %>"><%- plugin.prettyName %></a>
              <span class="preference__note"><%- plugin.version %></span>
            </div>
            <p class="preference__description"><%- plugin.description %></p>
          </div>
          <div class="preference-input">
            <div class="c-toggle">
              <input type="checkbox" class="c-toggle__input install-toggle" id="plugin-toggle-<%- plugin.name %>" data-name="<%- plugin.name %>" <%- installed ? 'checked' : '' %>>
              <label class="c-toggle__label" for="plugin-toggle-<%- plugin.name %>"></label>
            </div>
          </div>
        </div>
      </div>
    <% }); %>
  `);

  function loadInstalledPlugins(installedPlugins) {
    const html = pluginListTemplate({
      plugins: installedPlugins,
      installed: true
    });

    $j('#plugins-installed').html(html);
  }

  function loadAvailablePlugins(availablePlugins) {
    const html = pluginListTemplate({
      plugins: availablePlugins,
      installed: false
    });

    $j('#plugins-available').html(html);
  }

  $j('.plugins-list').on('change', '.install-toggle', function (e) {
    const el = e.target;
    const name = el.dataset.name;

    el.disabled = true;

    if (el.checked) {
      el.classList.add('loading');
      ipcRenderer.send('install-plugin', name);
      $j(this).parents('li').remove(); // We don't want to wait on `loadAvailablePlugins`
    } else {
      ipcRenderer.send('uninstall-plugin', name);
    }
  });

  ipcRenderer.on('load-plugins', (event, {available, installed}) => {
    loadAvailablePlugins(available);
    loadInstalledPlugins(installed);
  });

  // Open plugin homepage
  $j('.plugins-prefs').on('click', '.preference__url', function (event) {
    event.preventDefault();
    const url = $j(this).data('url');<commit_msg>Allow only one plugin to be installing/uninstalling at the time (#361)<commit_after>import {ipcRenderer, remote, shell} from 'electron';
import _ from 'lodash';
import $j from 'jquery/dist/jquery.slim';

// Note: `./` == `/app/dist/renderer/views`, not `js`
import {handleTrafficLightsClicks, $, disposeObservers} from '../js/utils';

const {app, dialog, getCurrentWindow} = remote;

const aperture = require('aperture');

const plugins = remote.require('../main/plugins').default;

const settingsValues = app.kap.settings.getAll();

// Observers that should be disposed when the window unloads
const observersToDispose = [];

document.addEventListener('DOMContentLoaded', async () => {
  // Element definitions
  const allowAnalyticsCheckbox = $('#allow-analytics');
  const audioInputDeviceSelector = $('.js-audio-input-device-selector');
  const chooseSaveDirectoryBtn = $('.js-choose-save');
  const fpsLabel = $('.fps-slider .js-middle-label');
  const fpsSlider = $('.fps-slider input');
  const header = $('header');
  const highlightClicksCheckbox = $('#highlight-clicks');
  const openOnStartupCheckbox = $('#open-on-startup');
  const saveToDescription = $('.js-save-to-description');
  const showCursorCheckbox = $('#show-cursor');
  const openPluginsFolder = $('.js-open-plugins');

  const electronWindow = getCurrentWindow();

  electronWindow.setSheetOffset(header.offsetHeight);
  handleTrafficLightsClicks();

  // Init the shown settings
  saveToDescription.dataset.fullPath = settingsValues.kapturesDir;
  saveToDescription.setAttribute('title', settingsValues.kapturesDir);
  saveToDescription.innerText = `.../${settingsValues.kapturesDir.split('/').pop()}`;
  openOnStartupCheckbox.checked = settingsValues.openOnStartup;
  allowAnalyticsCheckbox.checked = settingsValues.allowAnalytics;
  showCursorCheckbox.checked = settingsValues.showCursor;
  if (settingsValues.showCursor === false) {
    highlightClicksCheckbox.disabled = true;
  } else {
    highlightClicksCheckbox.checked = settingsValues.highlightClicks;
  }
  fpsSlider.value = settingsValues.fps;
  fpsLabel.innerText = `${settingsValues.fps} FPS`;

  for (const device of await aperture.audioDevices()) {
    const option = document.createElement('option');
    option.value = device.id;
    option.text = device.name;
    audioInputDeviceSelector.add(option);
  }

  audioInputDeviceSelector.value = settingsValues.audioInputDeviceId;

  const tabs = $j('.prefs-nav > a');
  tabs.on('click', function (event) {
    event.preventDefault();
    tabs.removeClass('is-active');
    $j(this).addClass('is-active');

    const panes = $j('.prefs-sections > section');
    const paneName = $j(this).data('pane');
    panes.addClass('hidden');
    panes.filter(`[data-pane="${paneName}"]`).removeClass('hidden');
  });

  const pluginListTemplate = _.template(`
    <% _.forEach(plugins, plugin => { %>
      <div class="preference container">
        <div class="preference-part">
          <div class="preference-content">
            <div class="preference__title">
              <a class="preference__url o-link" href data-url="<%- plugin.homepage || plugin.links.homepage %>"><%- plugin.prettyName %></a>
              <span class="preference__note"><%- plugin.version %></span>
            </div>
            <p class="preference__description"><%- plugin.description %></p>
          </div>
          <div class="preference-input">
            <div class="c-toggle">
              <input type="checkbox" class="c-toggle__input install-toggle" id="plugin-toggle-<%- plugin.name %>" data-name="<%- plugin.name %>" <%- installed ? 'checked' : '' %>>
              <label class="c-toggle__label" for="plugin-toggle-<%- plugin.name %>"></label>
            </div>
          </div>
        </div>
      </div>
    <% }); %>
  `);

  function loadInstalledPlugins(installedPlugins) {
    const html = pluginListTemplate({
      plugins: installedPlugins,
      installed: true
    });

    $j('#plugins-installed').html(html);
  }

  function loadAvailablePlugins(availablePlugins) {
    const html = pluginListTemplate({
      plugins: availablePlugins,
      installed: false
    });

    $j('#plugins-available').html(html);
  }

  $j('.plugins-list').on('change', '.install-toggle', function (e) {
    const el = e.target;
    const name = el.dataset.name;

    $j('.plugins-list .install-toggle').prop('disabled', true);

    if (el.checked) {
      el.classList.add('loading');
      ipcRenderer.send('install-plugin', name);
      $j(this).parents('li').remove(); // We don't want to wait on `loadAvailablePlugins`
    } else {
      ipcRenderer.send('uninstall-plugin', name);
    }
  });

  ipcRenderer.on('load-plugins', (event, {available, installed}) => {
    loadAvailablePlugins(available);
    loadInstalledPlugins(installed);
  });

  // Open plugin homepage
  $j('.plugins-prefs').on('click', '.preference__url', function (event) {
    event.preventDefault();
    const url = $j(this).data('url');
{'fraction_non_alphanumeric': 0.16311052684801294, 'fraction_numerical': 0.0003033673778946304, 'mean_word_length': 3.7548076923076925, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7537838', 'n_tokens_mistral': 3014, 'n_tokens_neox': 2918, 'n_words': 562}