<commit_before>import {
  ipcMain,
  globalShortcut,
  app,
  Tray,
  BrowserWindow,
  dialog,
  shell,
  remote,
  screen
} from 'electron'
import * as url from 'url'
const osascript = require('node-osascript')
import * as path from 'path'
const assetsDirectory = path.join(__dirname, '../assets')

const onMac = /^darwin/.test(process.platform)
const onWindows = /^win/.test(process.platform)
import { Ipc, ElmIpc } from './ipc'

export class DisplayManager {
  private mainWindow: Electron.BrowserWindow
  private secondaryWindows: Electron.BrowserWindow[]
  private scriptsWindow: Electron.BrowserWindow | null

  constructor(
    private transparencyDisabled: boolean,
    private bugsnag: any,
    private closeTimerFunction: (() => void),
    private ipcHandler: ((ipc: ElmIpc) => void)
  ) {
    this.createMainWindow()
  }

  showMain() {
    if (!this.mainWindow.isVisible()) {
      this.showMainWindow()
      this.createSecondaryWindows()
    }
  }

  getMainWindow() {
    return this.mainWindow
  }

  hideMain() {
    this.hideMainWindow()
    this.closeSecondaryWindows()
    returnFocus()
  }

  hideMainKeepFocus() {
    this.hideMainWindow()
    this.closeSecondaryWindows()
  }

  toggleMain() {
    if (this.mainWindow.isVisible()) {
      this.hideMain()
    } else {
      this.showMain()
    }
  }

  newTransparentOnTopWindow(
    additionalOptions: Electron.BrowserWindowConstructorOptions
  ) {
    const transparentWindowDefaultOptions: Electron.BrowserWindowConstructorOptions = {
      transparent: !this.transparencyDisabled,
      frame: false,
      alwaysOnTop: true
    }
    return new BrowserWindow({
      ...transparentWindowDefaultOptions,
      ...additionalOptions
    })
  }

  private hideMainWindow() {
    this.mainWindow.hide()
  }

  private showMainWindow() {
    // TODO: workaround - remove once
    // https://github.com/electron/electron/issues/2867#issuecomment-264312493 has been resolved
    if (onWindows) {
      this.mainWindow.minimize()
    }
    this.mainWindow.show()
    this.mainWindow.focus()
  }

  private createSecondaryWindows() {
    let displays: Electron.Display[] = screen
      .getAllDisplays()
      .filter(display => display.id !== screen.getPrimaryDisplay().id)
    this.secondaryWindows = displays.map(display =>
      this.createSecondaryWindow(display)
    )
  }

  private closeSecondaryWindows() {
    this.secondaryWindows.forEach(secondaryWindow => secondaryWindow.close())
    this.secondaryWindows = []
  }

  createSecondaryWindow(display: Electron.Display) {
    let secondaryWindow: Electron.BrowserWindow = this.newTransparentOnTopWindow(
      {
        frame: false,
        alwaysOnTop: true,
        focusable: false,
        show: false,
        ...display.bounds
      }
    )
    secondaryWindow.loadURL(
      url.format({
        pathname: path.join(__dirname, '../blocker.html'),
        protocol: 'file:',
        slashes: true
      })
    )
    secondaryWindow.once('ready-to-show', () => {
      if (secondaryWindow) {
        secondaryWindow.show()
      }
    })

    return secondaryWindow
  }

  showScripts() {
    this.scriptsWindow = new BrowserWindow({
      width: 1000,
      height: 800,
      frame: true,
      icon: `${assetsDirectory}/icon.ico`,
      show: false
    })
    this.scriptsWindow.loadURL(
      url.format({
        pathname: path.join(__dirname, '../script-install-instructions.html'),
        protocol: 'file:',
        slashes: true
      })
    )
    this.scriptsWindow.once('ready-to-show', () => {
      if (this.scriptsWindow) {
        this.hideMainKeepFocus()
        this.scriptsWindow.show()
      }
    })

    this.scriptsWindow.on('closed', () => {
      this.scriptsWindow = null
      this.showMain()
    })
  }

  private createMainWindow() {
    this.mainWindow = this.newTransparentOnTopWindow({
      icon: `${assetsDirectory}/icon.ico`,
      show: false
    })

    this.mainWindow.once('ready-to-show', () => {
      this.mainWindow && this.mainWindow.show()
      this.createSecondaryWindows()
    })

    this.mainWindow.webContents.on('crashed', () => {
      this.bugsnag.notify('crashed', 'mainWindow crashed')
    })
    this.mainWindow.on('unresponsive', () => {
      this.bugsnag.notify('unresponsive', 'mainWindow unresponsive')
    })
    setTimeout(() => {
      this.mainWindow.setAlwaysOnTop(true) // delay to workaround https://github.com/electron/electron/issues/8287
    }, 1000)
    this.mainWindow.maximize()
<commit_msg>Only show mainWindow when all blocker windows are ready.<commit_after>import {
  ipcMain,
  globalShortcut,
  app,
  Tray,
  BrowserWindow,
  dialog,
  shell,
  remote,
  screen
} from 'electron'
import * as url from 'url'
const osascript = require('node-osascript')
import * as path from 'path'
const assetsDirectory = path.join(__dirname, '../assets')

const onMac = /^darwin/.test(process.platform)
const onWindows = /^win/.test(process.platform)
import { Ipc, ElmIpc } from './ipc'

export class DisplayManager {
  private mainWindow: Electron.BrowserWindow
  private secondaryWindows: Electron.BrowserWindow[]
  private scriptsWindow: Electron.BrowserWindow | null

  constructor(
    private transparencyDisabled: boolean,
    private bugsnag: any,
    private closeTimerFunction: (() => void),
    private ipcHandler: ((ipc: ElmIpc) => void)
  ) {
    this.createMainWindow()
  }

  showMain() {
    if (!this.mainWindow.isVisible()) {
      // this.showMainWindow()
      this.createSecondaryWindows()
    }
  }

  getMainWindow() {
    return this.mainWindow
  }

  hideMain() {
    this.hideMainWindow()
    this.closeSecondaryWindows()
    returnFocus()
  }

  hideMainKeepFocus() {
    this.hideMainWindow()
    this.closeSecondaryWindows()
  }

  toggleMain() {
    if (this.mainWindow.isVisible()) {
      this.hideMain()
    } else {
      this.showMain()
    }
  }

  newTransparentOnTopWindow(
    additionalOptions: Electron.BrowserWindowConstructorOptions
  ) {
    const transparentWindowDefaultOptions: Electron.BrowserWindowConstructorOptions = {
      transparent: !this.transparencyDisabled,
      frame: false,
      alwaysOnTop: true
    }
    return new BrowserWindow({
      ...transparentWindowDefaultOptions,
      ...additionalOptions
    })
  }

  private hideMainWindow() {
    this.mainWindow.hide()
  }

  private createSecondaryWindows() {
    let displays: Electron.Display[] = screen
      .getAllDisplays()
      .filter(display => display.id !== screen.getPrimaryDisplay().id)
    this.secondaryWindows = displays.map(display =>
      this.createSecondaryWindow(display)
    )

    this.showAllWhenReady(this.mainWindow, this.secondaryWindows)
  }

  private showAllWhenReady(
    mainWindow: Electron.BrowserWindow,
    windows: Electron.BrowserWindow[]
  ): void {
    let readyToDisplay = windows.map(window => {
      return { id: window.id, ready: false }
    })
    windows.forEach(window => {
      window.once('ready-to-show', () => {
        if (window) {
          let entry = readyToDisplay.find(({ id }) => id === window.id)
          entry && (entry.ready = true)
          if (readyToDisplay.every(({ ready }) => ready)) {
            mainWindow.show()
            windows.forEach(window => window.show())
          }
        }
      })
    })
  }

  private showAll() {
    this.mainWindow.show()
    this.secondaryWindows.forEach(window => window.show())
  }

  private closeSecondaryWindows() {
    this.secondaryWindows.forEach(secondaryWindow => secondaryWindow.close())
    this.secondaryWindows = []
  }

  createSecondaryWindow(display: Electron.Display) {
    let secondaryWindow: Electron.BrowserWindow = this.newTransparentOnTopWindow(
      {
        frame: false,
        alwaysOnTop: true,
        focusable: false,
        show: false,
        ...display.bounds
      }
    )
    secondaryWindow.loadURL(
      url.format({
        pathname: path.join(__dirname, '../blocker.html'),
        protocol: 'file:',
        slashes: true
      })
    )

    return secondaryWindow
  }

  showScripts() {
    this.scriptsWindow = new BrowserWindow({
      width: 1000,
      height: 800,
      frame: true,
      icon: `${assetsDirectory}/icon.ico`,
      show: false
    })
    this.scriptsWindow.loadURL(
      url.format({
        pathname: path.join(__dirname, '../script-install-instructions.html'),
        protocol: 'file:',
        slashes: true
      })
    )
    this.scriptsWindow.once('ready-to-show', () => {
      if (this.scriptsWindow) {
        this.hideMainKeepFocus()
        this.scriptsWindow.show()
      }
    })

    this.scriptsWindow.on('closed', () => {
      this.scriptsWindow = null
      this.showMain()
    })
  }

  private createMainWindow() {
    this.mainWindow = this.newTransparentOnTopWindow({
      icon: `${assetsDirectory}/icon.ico`,
      show: false
    })

    this.mainWindow.once('ready-to-show', () => {
      // this.mainWindow && this.mainWindow.show()
      this.createSecondaryWindows()
    })

    this.mainWindow.webContents.on('crashed', () => {
      this.bugsnag.notify('crashed', 'mainWindow crashed')
    })
    this.mainWindow.on('unresponsive', () => {
      this.bugsnag.notify('unresponsive', 'mainWindow unresponsive')
    })
    setTimeout(() => {
      this.mainWindow.setAlwaysOnTop(true) // delay to workaround https://github.com/electron/electron/issues/8287
    }, 1000)
    this.mainWindow.maximize()

{'fraction_non_alphanumeric': 0.1295314818740725, 'fraction_numerical': 0.004557981768072927, 'mean_word_length': 2.7983091787439616, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, 'https://': 3, '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': '5261010', 'n_tokens_mistral': 2888, 'n_tokens_neox': 2764, 'n_words': 497}