electron#screen TypeScript Examples

The following examples show how to use electron#screen. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: window-state.ts    From WowUp with GNU General Public License v3.0 6 votes vote down vote up
// Lifted from Discord to check where to display the window
function isVisibleOnScreen(windowState: WindowState) {
  let isVisibleOnAnyScreen = false;

  log.info(windowState);

  const displays = screen.getAllDisplays();
  for (const display of displays) {
    const displayBound = display.workArea;
    displayBound.x += MIN_VISIBLE_ON_SCREEN;
    displayBound.y += MIN_VISIBLE_ON_SCREEN;
    displayBound.width -= 2 * MIN_VISIBLE_ON_SCREEN;
    displayBound.height -= 2 * MIN_VISIBLE_ON_SCREEN;
    isVisibleOnAnyScreen = doRectanglesOverlap(windowState, displayBound);

    log.info("isVisibleOnAnyScreen", displayBound, isVisibleOnAnyScreen);
    if (isVisibleOnAnyScreen) {
      break;
    }
  }

  return isVisibleOnAnyScreen;
}
Example #2
Source File: main.ts    From tuxedo-control-center with GNU General Public License v3.0 6 votes vote down vote up
function createTccWindow(langId: string) {
    let windowWidth = 1040;
    let windowHeight = 750;
    if (windowWidth > screen.getPrimaryDisplay().workAreaSize.width) {
        windowWidth = screen.getPrimaryDisplay().workAreaSize.width;
    }
    if (windowHeight > screen.getPrimaryDisplay().workAreaSize.height) {
        windowHeight = screen.getPrimaryDisplay().workAreaSize.height;
    }

    tccWindow = new BrowserWindow({
        title: 'TUXEDO Control Center',
        width: windowWidth,
        height: windowHeight,
        frame: true,
        resizable: true,
        minWidth: windowWidth,
        minHeight: windowHeight,
        icon: path.join(__dirname, '../../data/dist-data/tuxedo-control-center_256.png'),
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
            enableRemoteModule: true,
        }
    });

    // Hide menu bar
    tccWindow.setMenuBarVisibility(false);
    // Workaround to menu bar appearing after full screen state
    tccWindow.on('leave-full-screen', () => { tccWindow.setMenuBarVisibility(false); });

    tccWindow.on('closed', () => {
        tccWindow = null;
    });

    const indexPath = path.join(__dirname, '..', '..', 'ng-app', langId, 'index.html');
    tccWindow.loadFile(indexPath);
}
Example #3
Source File: index.ts    From Protoman with MIT License 6 votes vote down vote up
async function createWindow(): Promise<void> {
  const screenWidth = screen.getPrimaryDisplay().workAreaSize.width;
  const bounds = config.get('winBounds') as Rectangle;
  //default value
  let width = screenWidth * WIDTH_RATIO;
  let height = screenWidth * WIDTH_RATIO * ASPECT_RATIO;
  //if some value
  if (bounds != undefined) {
    width = bounds.width;
    height = bounds.height;
  }
  console.log('saved bounds ', bounds);
  window = new BrowserWindow({
    width: width,
    height: height,
    webPreferences: {
      nodeIntegration: true,
    },
  });
  initializeEvents();
  Menu.setApplicationMenu(makeMenu());
  window.loadFile(path.join(__dirname, 'index.html'));

  window.on('close', () => {
    console.log('closing the window');
    console.log('save window bounds');
    config.set('winBounds', window.getBounds());
  });
  checkUpdateAndNotify(window);
}
Example #4
Source File: index.ts    From shadowsocks-electron with GNU General Public License v3.0 6 votes vote down vote up
getBestWindowPosition = (win: BrowserWindow, tray: Tray) => {
  const winBounds = win.getBounds();
  const trayBounds = tray.getBounds();

  const trayScreen = screen.getDisplayNearestPoint({
    x: trayBounds.x,
    y: trayBounds.y
  });

  const workArea = trayScreen.workArea;
  const screenBounds = trayScreen.bounds;

  if (workArea.x > 0) {
    return {
      x: workArea.x,
      y: workArea.height - winBounds.height
    };
  }

  if (workArea.y > 0) {
    return {
      x: Math.round(trayBounds.x + trayBounds.width / 2 - winBounds.width / 2),
      y: workArea.y
    };
  }

  if (workArea.width < screenBounds.width) {
    return {
      x: workArea.width - winBounds.width,
      y: screenBounds.height - winBounds.height
    };
  }

  return {
    x: Math.round(trayBounds.x + trayBounds.width / 2 - winBounds.width / 2),
    y: workArea.height - winBounds.height
  };
}
Example #5
Source File: window.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export function createWindow (environment: string): Promise<unknown> {
  const { height, width } = screen.getPrimaryDisplay().workAreaSize;

  const win = new BrowserWindow({
    height,
    icon: path.join(__dirname, 'icon.png'),
    webPreferences: {
      contextIsolation: true,
      enableRemoteModule: false,
      nodeIntegration: false,
      preload: path.join(__dirname, 'preload.js')
    },
    width
  });

  if (environment === 'development') {
    win.webContents.openDevTools();

    return win.loadURL('http://127.0.0.1:3000/');
  }

  const mainFilePath = path.resolve(__dirname, 'index.html');

  return win.loadFile(mainFilePath);
}
Example #6
Source File: price-check.ts    From awakened-poe-trade with MIT License 6 votes vote down vote up
export function showWidget (opts: {
  clipboard: string
  pressPosition: Point
  eventName: string
}) {
  checkPressPosition = (process.platform === 'win32')
    ? screen.dipToScreenPoint(opts.pressPosition)
    : opts.pressPosition
  const isLokedMode = (opts.eventName === 'price-check-locked')

  overlaySendEvent({
    name: 'MAIN->OVERLAY::price-check',
    payload: { clipboard: opts.clipboard, position: opts.pressPosition, lockedMode: isLokedMode }
  })

  const poeBounds = PoeWindow.bounds
  activeAreaRect = {
    x: getOffsetX(checkPressPosition, poeBounds),
    y: poeBounds.y,
    width: Math.floor(WIDTH_96DPI * DPR * config.get('fontSize')),
    height: poeBounds.height
  }

  isPriceCheckShown = true
  isClickedAfterLock = false
  isMouseInside = false

  if (isLokedMode) {
    lockWindow(true)
  }
}
Example #7
Source File: main.ts    From DittoPlusPlus with MIT License 6 votes vote down vote up
function showWindow() {
  if (mainWindow) {
    const {x, y} = screen.getCursorScreenPoint();
    mainWindow.setPosition(x, y);

    // workaround to show the application on current desktop when using multiple desktops
    mainWindow.setVisibleOnAllWorkspaces(true, {visibleOnFullScreen: true}); // put the window on all screens
    mainWindow.focus(); // focus the window up front on the active screen
    mainWindow.setVisibleOnAllWorkspaces(false, {visibleOnFullScreen: true}); // disable all screen behavior

    mainWindow.show();
    isWindowShowing = true;
    mainWindow.webContents.send(GlobalEvents.ShowWindow);
  }
}
Example #8
Source File: main.ts    From SpaceEye with MIT License 6 votes vote down vote up
/**
 * Get the position of the Windows taskbar based on the tray bounds.
 *
 * @param trayBounds - Current bounds of menubar tray
 * @returns Position of taskbar
 */
function getWindowsTaskbarLocation(trayBounds: Rectangle): WindowsTaskbarPosition {
    if (trayBounds.y === 0) {
        return WindowsTaskbarPosition.Top
    }
    if (trayBounds.x < 50) {
        return WindowsTaskbarPosition.Left
    }
    const currentScreen = screen.getDisplayMatching(trayBounds)
    if (trayBounds.y + trayBounds.height === currentScreen.bounds.height) {
        return WindowsTaskbarPosition.Bottom
    }
    return WindowsTaskbarPosition.Right
}
Example #9
Source File: wallpaper_manager.ts    From SpaceEye with MIT License 6 votes vote down vote up
/**
     * Get all non-internal monitors.
     *
     * @returns All non-internal monitors
     */
    private static getMonitors(): Display[] {
        const allMonitors = screen.getAllDisplays().filter(monitor => !monitor.internal)
        log.debug(
            'All monitors:',
            allMonitors.map(monitor => monitor.id)
        )
        return allMonitors
    }
Example #10
Source File: window.ts    From SideQuest with MIT License 6 votes vote down vote up
serializeWindowState(): WindowState {
        if (!this._window) {
            return defaultWindowState();
        }

        const display = screen.getDisplayMatching(this.getBounds());
        const mode: WindowMode = this._window.isMaximized() ? 'maximized' : 'normal';
        const bounds = mode === 'normal' ? this.getBounds() : this._window.getNormalBounds();
        const state: WindowState = {
            mode,
            x: bounds.x,
            y: bounds.y,
            width: bounds.width,
            height: bounds.height,
            display: display ? display.id : undefined,
        };
        return state;
    }
Example #11
Source File: main.ts    From VIR with MIT License 5 votes vote down vote up
function createWindow(): BrowserWindow {

  const electronScreen = screen;
  const size = electronScreen.getPrimaryDisplay().workAreaSize;

  // Create the browser window.
  win = new BrowserWindow({
    x: 0,
    y: 0,
    width: size.width,
    height: size.height,
    webPreferences: {
      nodeIntegration: true,
      allowRunningInsecureContent: (serve) ? true : false,
      contextIsolation: false,  // false if you want to run 2e2 test with Spectron
      enableRemoteModule : true // true if you want to run 2e2 test  with Spectron or use remote module in renderer context (ie. Angular)
    },
  });

  if (serve) {

    win.webContents.openDevTools();

    require('electron-reload')(__dirname, {
      electron: require(`${__dirname}/node_modules/electron`)
    });
    win.loadURL('http://localhost:4200');

  } else {
    win.loadURL(url.format({
      pathname: path.join(__dirname, 'dist/index.html'),
      protocol: 'file:',
      slashes: true
    }));
  }

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store window
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null;
  });

  return win;
}
Example #12
Source File: index.ts    From multi-downloader-nx with MIT License 5 votes vote down vote up
createWindow = async () => {
  (await import('../../../modules/module.cfg-loader')).ensureConfig();
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: screen.getPrimaryDisplay().bounds.width,
    height: screen.getPrimaryDisplay().bounds.height,
    title: `AniDL GUI v${json.version}`,
    webPreferences: {
      nodeIntegration: false,
      preload: path.join(__dirname, 'preload.js')
    },
    icon,
  });

  mainWindow.webContents.on('crashed', (e) => console.log(e));

  (await import('./messageHandler')).default(mainWindow);
  
  if (!process.env.USE_BROWSER) {
    const app = express();

    // Path.sep seems to return / on windows with electron 
    // \\ in Filename on Linux is possible but I don't see another way rn
    const sep = isWindows ? '\\' : '/';

    const p = __dirname.split(sep);
    p.pop();
    p.push('build');

    console.log(p.join(sep));

    app.use(express.static(p.join(sep)));

    await new Promise((resolve) => {
      app.listen(3000, () => {
        console.log('Express started');
        resolve(undefined);
      });
    });

  }
  
  mainWindow.loadURL('http://localhost:3000');
  if (process.env.TEST)
    mainWindow.webContents.openDevTools();
}
Example #13
Source File: shortcuts.ts    From awakened-poe-trade with MIT License 5 votes vote down vote up
function registerGlobal () {
  const toRegister = shortcutsFromConfig()
  for (const entry of toRegister) {
    const isOk = globalShortcut.register(shortcutToElectron(entry.shortcut), () => {
      if (entry.keepModKeys) {
        const nonModKey = entry.shortcut.split(' + ').filter(key => !isModKey(key))[0]
        robotjs.keyToggle(nonModKey, 'up')
      } else {
        entry.shortcut.split(' + ').reverse().forEach(key => { robotjs.keyToggle(key, 'up') })
      }

      if (entry.action.type === 'toggle-overlay') {
        toggleOverlayState()
      } else if (entry.action.type === 'paste-in-chat') {
        typeInChat(entry.action.text, entry.action.send)
      } else if (entry.action.type === 'trigger-event') {
        overlaySendEvent({ name: entry.action.eventName, payload: entry.action.payload } as ipc.IpcEvent)
      } else if (entry.action.type === 'stash-search') {
        stashSearch(entry.action.text)
      } else if (entry.action.type === 'copy-item') {
        const { action } = entry

        const pressPosition = screen.getCursorScreenPoint()

        pollClipboard()
          .then(clipboard => {
            if (action.eventName === 'price-check-quick' || action.eventName === 'price-check-locked') {
              showPriceCheck({ clipboard, pressPosition, eventName: action.eventName })
            } else {
              overlaySendEvent({
                name: action.eventName,
                payload: { clipboard, position: pressPosition }
              })
              if (action.focusOverlay) {
                assertOverlayActive()
              }
            }
          }).catch(() => {})

        if (!entry.keepModKeys) {
          pressKeysToCopyItemText()
        } else {
          pressKeysToCopyItemText(entry.shortcut.split(' + ').filter(key => isModKey(key)))
        }
      }
    })

    if (!isOk) {
      logger.error('Failed to register a shortcut. It is already registered by another application.', { source: 'shortcuts', shortcut: entry.shortcut })
    }

    if (entry.action.type === 'test-only') {
      globalShortcut.unregister(shortcutToElectron(entry.shortcut))
    }
  }

  logger.verbose('Registered Global', { source: 'shortcuts', total: toRegister.length })
}
Example #14
Source File: window.ts    From SideQuest with MIT License 5 votes vote down vote up
private validateWindowState(state: WindowState, displays: Display[]): WindowState {
        if (
            typeof state.x !== 'number' ||
            typeof state.y !== 'number' ||
            typeof state.width !== 'number' ||
            typeof state.height !== 'number'
        ) {
            return undefined;
        }

        if (state.width <= 0 || state.height <= 0) {
            return undefined;
        }

        if (displays.length === 1) {
            const displayWorkingArea = this.getWorkingArea(displays[0]);
            if (displayWorkingArea) {
                const ensureStateInDisplayWorkingArea = () => {
                    const isTooFarLeft = state.x < displayWorkingArea.x;
                    if (isTooFarLeft) {
                        state.x = displayWorkingArea.x;
                    }
                    const isTooFarUp = state.y < displayWorkingArea.y;
                    if (isTooFarUp) {
                        state.y = displayWorkingArea.y;
                    }
                };
                ensureStateInDisplayWorkingArea();
                const isTooWide = state.width > displayWorkingArea.width;
                if (isTooWide) {
                    state.width = displayWorkingArea.width;
                }
                const isTooTall = state.height > displayWorkingArea.height;
                if (isTooTall) {
                    state.height = displayWorkingArea.height;
                }
                const isTooFarRight = state.x > displayWorkingArea.x + displayWorkingArea.width - 128;
                if (isTooFarRight) {
                    state.x = displayWorkingArea.x + displayWorkingArea.width - 128;
                }
                const isTooFarDown = state.y > displayWorkingArea.y + displayWorkingArea.height - 128;
                if (isTooFarDown) {
                    state.y = displayWorkingArea.y + displayWorkingArea.height - 128;
                }
                ensureStateInDisplayWorkingArea();
            }
            return state;
        } else {
            const display = screen.getDisplayMatching({ x: state.x, y: state.y, width: state.width, height: state.height });
            const displayWorkingArea = this.getWorkingArea(display);
            if (
                display &&
                displayWorkingArea &&
                state.x + state.width > displayWorkingArea.x &&
                state.y + state.height > displayWorkingArea.y &&
                state.x < displayWorkingArea.x + displayWorkingArea.width &&
                state.y < displayWorkingArea.y + displayWorkingArea.height
            ) {
                return state;
            } else {
                return undefined;
            }
        }
    }
Example #15
Source File: TransparentWindow.ts    From shadowsocks-electron with GNU General Public License v3.0 5 votes vote down vote up
constructor() {
    const screenSize = screen.getPrimaryDisplay().workAreaSize;
    this.icon = path.resolve(__dirname, "../../assets/logo.png");
    this.url = `file://${path.resolve(app.getAppPath(), "assets/twin.html")}`;
    this.win = null;
    this.width = screenSize.width;
    this.height = screenSize.height;
  }
Example #16
Source File: main.ts    From SpaceEye with MIT License 5 votes vote down vote up
// mb.on('ready', () => {})

mb.on('ready', () => {
    log.info('Menubar ready')
    // createWindow()
    heartbeatHandle = setInterval(heartbeat, HEARTBEAT_INTERVAL)

    // Check if toolbar icon should be updated (Windows only)
    updateToolbarIcon()

    // Display config change triggers update
    screen.on('display-added', async () => {
        log.debug('Display added')
        await WallpaperManager.update(Initiator.displayChangeWatcher)
    })

    screen.on('display-removed', async () => {
        log.debug('Display removed')
        await WallpaperManager.update(Initiator.displayChangeWatcher)
    })

    screen.on('display-metrics-changed', async () => {
        log.debug('Display metrics changed')
        await WallpaperManager.update(Initiator.displayChangeWatcher)
    })

    // Update when machine is unlocked/resumed
    // TODO: Need a new initiator
    if (process.platform === 'darwin' || process.platform === 'win32') {
        powerMonitor.on('unlock-screen', async () => {
            log.debug('Screen unlocked')
            await WallpaperManager.update(Initiator.displayChangeWatcher)
        })
    }

    if (process.platform === 'linux' || process.platform === 'win32') {
        powerMonitor.on('resume', async () => {
            log.debug('System resumed')
            await WallpaperManager.update(Initiator.displayChangeWatcher)
        })
    }

    // If first run, show user the window
    if (AppConfigStore.firstRun) {
        mb.showWindow()
        // If macOS, no onboarding, so first run must be reset here
        if (process.platform === 'darwin') {
            AppConfigStore.firstRun = false
        }
    }

    // Run an update on start
    WallpaperManager.update(Initiator.user)
})
Example #17
Source File: main.ts    From StraxUI with MIT License 5 votes vote down vote up
function createWindow(): void {
  // Create the browser window.
  const height = screen.getPrimaryDisplay().bounds.height - 100;
  const width = Math.round(height * 1.1);

  console.log(height);
  console.log(width);
  mainWindow = new BrowserWindow({
    width: width,
    height: height,
    frame: true,
    minWidth: 900,
    minHeight: 800,
    title: applicationName,
    webPreferences: {
      nodeIntegration: true,
      allowRunningInsecureContent: (serve) ? true : false,
      contextIsolation: false,  // false if you want to run 2e2 test with Spectron
      enableRemoteModule: true // true if you want to run 2e2 test  with Spectron or use remote module in renderer context (ie. Angular)
    },
  });

  if (serve) {
    require('electron-reload')(__dirname, {
      electron: require(`${__dirname}/node_modules/electron`)
    });
    mainWindow.loadURL('http://localhost:4200');
  } else {
    mainWindow.loadURL(url.format({
      pathname: path.join(__dirname, 'dist/index.html'),
      protocol: 'file:',
      slashes: true
    }));
  }

  if (serve || devtools) {
    mainWindow.webContents.openDevTools();
  }

  // Emitted when the window is closed.
  mainWindow.on('closed', () => {
    // Dereference the window object, usually you would store window
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });

  // Remove menu, new from Electron 5
  mainWindow.removeMenu();
}
Example #18
Source File: window.ts    From SideQuest with MIT License 5 votes vote down vote up
private restoreWindowState(state?: WindowState): [WindowState, boolean] {
        const displays = screen.getAllDisplays();
        const hasMultipleDisplays = displays.length > 1;
        if (state) {
            state = this.validateWindowState(state, displays);
        }
        return [state || defaultWindowState(), hasMultipleDisplays];
    }
Example #19
Source File: main.ts    From Creators.TF-Community-Launcher with MIT License 4 votes vote down vote up
public static createWindow() {
        const { width, height } = screen.getPrimaryDisplay().workAreaSize;
        this.screenWidth = width;
        this.screenHeight = height;
        this.minWindowWidth = 960;
        this.minWindowHeight = 540;
        this.icon = path.join(__dirname, "..", "images/installer/256x256.png");
        try {
            Main.mainWindow = new BrowserWindow({
                minWidth: this.minWindowWidth,
                minHeight: this.minWindowHeight,
                width: this.screenWidth-200,
                height: this.screenHeight-150,
                webPreferences: {
                    preload: path.join(__dirname, "preload.js"),
                    nodeIntegration: false,
                    contextIsolation: false
                },
                center: true,
                maximizable: true,
                resizable: true,
                autoHideMenuBar: true,
                darkTheme: true,
                backgroundColor: "#2B2826",
                icon: this.icon
            });
            //@ts-ignore
            global.mainWindow = Main.mainWindow;
            Main.app = app;
            if (!isDev) {
                Main.mainWindow.removeMenu();
            }

            //Lets load the config file.
            Config.GetConfig().then((c) => {
                //Make sure the config is loaded in.
                // and load the index.html of the app.
                //Also setup the mod manager.
                this.config = c;
                try {
                    mod_manager.Setup().then(() => {
                        Main.mainWindow.loadFile(path.join(__dirname, "..", "index.html"));
                        delete require("electron").nativeImage.createThumbnailFromPath;
                    });
                }
                catch (e) {
                    log.error(e.toString());
                    dialog.showMessageBox({
                        type: "error",
                        title: "Startup Error - Main Window Load",
                        message: e.toString() + majorErrorMessageEnd,
                        buttons: ["OK"]
                    }).then(() => {
                        app.quit();
                    });
                }
            })
                .catch((e) => {
                    log.error(e.toString());
                    dialog.showMessageBox({
                        type: "error",
                        title: "Startup Error - Config Load",
                        message: e.toString() + majorErrorMessageEnd,
                        buttons: ["OK"]
                    }).then(() => {
                        app.quit();
                    });
                });
        }
        catch (majorE) {
            log.error(majorE.toString());
            dialog.showMessageBox({
                type: "error",
                title: "Startup Error - Major Initial Error",
                message: majorE.toString() + majorErrorMessageEnd,
                buttons: ["OK"]
            }).then(() => {
                app.quit();
            });
        }
    }
Example #20
Source File: RewindElectronApp.ts    From rewind with MIT License 4 votes vote down vote up
createMainWindow() {
    const workAreaSize = screen.getPrimaryDisplay().workAreaSize;
    const width = Math.min(DEFAULT_WIDTH, workAreaSize.width || DEFAULT_WIDTH);
    const height = Math.min(DEFAULT_HEIGHT, workAreaSize.height || DEFAULT_HEIGHT);
    const minWidth = Math.min(MIN_WIDTH, workAreaSize.width || MIN_WIDTH);
    const minHeight = Math.min(MIN_HEIGHT, workAreaSize.height || MIN_HEIGHT);

    this.mainWindow = new BrowserWindow({
      width,
      height,
      minWidth,
      minHeight,
      show: false,
      webPreferences: {
        contextIsolation: true,
        backgroundThrottling: true, // This MUST be true in order for PageVisibility API to work.
        preload: desktopFrontendPreloadPath,
      },
    });
    this.mainWindow.center();

    // It still takes a while to load, so maybe a splash screen in the future could be shown while it is "not ready to
    // show".
    this.mainWindow.on("ready-to-show", () => {
      console.log("ReadyToShow");
      this.mainWindow?.show();
    });

    const osuFolder = this.settings.osuPath;
    const osuFolderKnown = !!osuFolder as boolean;
    this.mainWindow.setMenu(
      Menu.buildFromTemplate([
        {
          label: "File",
          submenu: [
            {
              label: "Open Replay",
              accelerator: "CommandOrControl+O",
              enabled: osuFolderKnown,
              click: async () => {
                const { canceled, filePaths } = await dialog.showOpenDialog({
                  defaultPath: join(osuFolder, "Replays"),
                  properties: ["openFile"],
                  filters: [
                    { name: "osu! Replay", extensions: ["osr"] },
                    { name: "All Files", extensions: ["*"] },
                  ],
                });
                if (!canceled && filePaths.length > 0) {
                  const file = filePaths[0];
                  this.mainWindow?.webContents.send("onManualReplayOpen", file);
                }
              },
            },
            { type: "separator" },
            {
              label: "Open Installation Folder",
              click: async () => {
                await shell.showItemInFolder(this.application.getPath("exe"));
              },
            },
            {
              label: "Open User Config Folder",
              click: async () => {
                await shell.openPath(this.application.getPath("userData"));
              },
            },
            {
              label: "Open Logs Folder",
              click: async () => {
                await shell.openPath(this.application.getPath("logs"));
              },
            },
            { type: "separator" },
            {
              label: "Open osu! Folder",
              click: async () => {
                await shell.openPath(osuFolder);
              },
              enabled: osuFolderKnown,
            },
            { type: "separator" },
            { role: "close" },
          ],
        },
        {
          label: "View",
          submenu: [
            { role: "reload" },
            { role: "forceReload" },
            { type: "separator" },
            { role: "toggleDevTools" },
            { label: "Open Backend", click: () => this.apiWindow?.show() },
          ],
        },
        {
          label: "Help",
          submenu: [
            {
              label: "Documentation",
              click: async () => {
                await shell.openExternal("https://github.com/abstrakt8/rewind/wiki");
              },
            },
            {
              label: "Discord",
              click: async () => {
                await shell.openExternal("https://discord.gg/QubdHdnBVg");
              },
            },
            { type: "separator" },
            {
              label: "About",
              click: async () => {
                const aboutMessage = `Rewind ${this.application.getVersion()}\nDeveloped by abstrakt\nPartnered with osu! University`;
                await dialog.showMessageBox({
                  title: "About Rewind",
                  type: "info",
                  message: aboutMessage,
                  // TODO: icon: NativeImage (RewindIcon)
                });
              },
            },
          ],
        },
      ]),
    );
    // this.mainWindow.setMenuBarVisibility(false);

    this.mainWindow.on("closed", () => {
      this.mainWindow = undefined;
      this.application.quit();
      // Otherwise we won't trigger all windows closed
      this.apiWindow?.close();
    });

    // Open external links such as socials in the default browser.
    this.mainWindow.webContents.setWindowOpenHandler((details) => {
      shell.openExternal(details.url);
      return { action: "deny" };
    });
  }
Example #21
Source File: main.ts    From EXOS-Core with MIT License 4 votes vote down vote up
function createWindow() {
    // Create the browser window.
    let iconpath;
    if (serve) {
        iconpath = nativeImage.createFromPath('./src/assets/exos-core/logo-tray.png');
    } else {
        iconpath = nativeImage.createFromPath(path.resolve(__dirname, '..//..//resources//dist//assets//exos-core//logo-tray.png'));
    }

    const { width, height } = screen.getPrimaryDisplay().workAreaSize;

    mainWindow = new BrowserWindow({
        width: 1366,
        minWidth: 1100,
        icon: iconpath,
        height: 768,
        frame: true,
        center: true,
        resizable: true,

        title: 'EXOS Core',
        webPreferences: { webSecurity: false, nodeIntegration: true, contextIsolation: false }
    });

    contents = mainWindow.webContents;

    mainWindow.setMenu(null);

    // Make sure links that open new window, e.g. target="_blank" launches in external window (browser).
    mainWindow.webContents.on('new-window', function (event, linkUrl) {
        event.preventDefault();
        shell.openExternal(linkUrl);
    });

    if (serve) {
        require('electron-reload')(__dirname, {
            electron: require(`${__dirname}/node_modules/electron`)
        });

        writeLog('Creating Window and loading: http://localhost:4200?coin=' + coin.identity);
        mainWindow.loadURL('http://localhost:4200?coin=' + coin.identity);
    } else {
        writeLog('Creating Window and loading: ' + path.join(__dirname, 'dist/index.html'));
        mainWindow.loadURL(url.format({
            pathname: path.join(__dirname, 'dist/index.html'),
            protocol: 'file:',
            slashes: true
        }));
    }

    if (serve) {
        mainWindow.webContents.openDevTools();
    }

    autoUpdater.checkForUpdatesAndNotify();

    // Emitted when the window is going to close.
    mainWindow.on('close', (event) => {
        writeLog(`close event on mainWindow was triggered. Calling shutdown method. Daemon state is: ${daemonState}.`);

        // If daemon stopping has not been triggered, it means it likely never started and user clicked Exit on the error dialog. Exit immediately.
        // Additionally if it was never started, it is already stopped.
        if (daemonState === DaemonState.Stopping || daemonState === DaemonState.Stopped) {
            writeLog('Daemon was in stopping mode, so exiting immediately without showing status any longer.');
            return true;
        } else {
            // If shutdown not initated yet, perform it.
            if (daemonState === DaemonState.Started) {
                writeLog('Daemon shutdown initiated... preventing window close, and informing UI that shutdown is in progress.');

                daemonState = DaemonState.Stopping;

                event.preventDefault();

                contents.send('daemon-exiting');

                // Call the shutdown while we show progress window.
                shutdown(() => { });

                return true;
            } else { // Else, allow window to be closed. This allows users to click X twice to immediately close the window.
                writeLog('ELSE in the CLOSE event. Should only happen on double-click on exit button.');
            }
        }
    });

    mainWindow.on('minimize', (event) => {
        if (!settings.showInTaskbar) {
            event.preventDefault();
            // mainWindow.hide();
        }
    });

    // Emitted when the window is closed.
    mainWindow.on('closed', () => {
        // Dereference the window object, usually you would store window
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        mainWindow = null;
    });
}
Example #22
Source File: main.ts    From desktop with MIT License 4 votes vote down vote up
async function start(): Promise<void> {
  log.transports.file.level = `info`
  autoUpdater.logger = log
  log.info(`App starting...`)
  fixPath()
  /**
   * Start a static server to serve the app's resources.
   * Gatsby doesn't like being served from a file URL
   */
  const port = await detectPort(9099)

  express()
    .use(serveStatic(path.resolve(dir, `public`)))
    .listen(port)

  const makeUrl = (path: string = ``): string =>
    process.env.GATSBY_DEVELOP_URL
      ? `${process.env.GATSBY_DEVELOP_URL}/${path}`
      : `http://localhost:${port}/${path}`

  let mainWindow: BrowserWindow | undefined

  let siteList: Array<{ site: ISiteMetadata; status?: ISiteStatus }> = []

  const siteLaunchers = new Map<string, SiteLauncher>()

  function openMainWindow(): void {
    if (!mainWindow || mainWindow.isDestroyed()) {
      mainWindow = makeWindow()
      mainWindow.loadURL(makeUrl())
    } else {
      if (!mainWindow.webContents.getURL()) {
        mainWindow.loadURL(makeUrl())
      }
    }
    mainWindow.show()
    trackEvent(`WINDOW_OPEN`)
  }

  // Start setting up listeners

  // The `payload` can be a site id, which means the window will be opened with that site's admin page
  ipcMain.on(`open-main`, async (event, payload?: string) => {
    if (!mainWindow || mainWindow.isDestroyed()) {
      mainWindow = makeWindow()
    }
    const url = makeUrl(payload ? `sites/${payload}` : ``)
    if (mainWindow.webContents.getURL() !== url) {
      mainWindow.loadURL(url)
    }
    mainWindow.show()
  })

  ipcMain.on(
    `launch-site`,
    async (event, { root, hash, clean }): Promise<number | undefined> => {
      if (!root || !hash) {
        console.error(`Invalid launch params`, { root, hash })
        return undefined
      }
      let launcher = siteLaunchers.get(hash)
      if (!launcher) {
        launcher = new SiteLauncher(root, hash)
        launcher.setListener((message: Message) => {
          if (mainWindow && !mainWindow.isDestroyed()) {
            mainWindow.webContents?.send(`site-message`, hash, message)
          }
        })
        siteLaunchers.set(hash, launcher)
      }
      return launcher.start(clean)
    }
  )

  ipcMain.on(
    `stop-site`,
    async (event, { hash, pid }): Promise<void> => {
      if (!hash) {
        console.error(`Missing site hash`)
        return
      }
      const launcher = siteLaunchers.get(hash)
      if (launcher) {
        launcher.stop()
        return
      }
      if (pid) {
        process.kill(pid)
      } else {
        console.error(`Site not found`)
      }
    }
  )

  app.on(`before-quit`, async (event) => {
    const { response } = await dialog.showMessageBox({
      message: `Quit Gatsby Desktop?`,
      detail: `This will stop all running sites`,
      buttons: [`Cancel`, `Quit`],
      defaultId: 1,
      type: `question`,
    })

    if (response !== 1) {
      event.preventDefault()
      return
    }
    trackEvent(`GATSBY_DESKTOP_QUIT`)
    siteLaunchers.forEach((site) => site.stop())
    stopWatching()
  })

  app.on(`activate`, (event, hasVisibleWindows) => {
    if (!hasVisibleWindows) {
      openMainWindow()
    }
  })

  app.on(`browser-window-focus`, () => {
    trackEvent(`WINDOW_FOCUS`)
  })

  app.on(`browser-window-blur`, () => {
    trackEvent(`WINDOW_BLUR`)
  })

  ipcMain.on(`quit-app`, () => {
    app.quit()
  })

  ipcMain.handle(`get-sites`, async () => siteList)

  // This request comes from the renderer
  ipcMain.handle(`browse-for-site`, async () => {
    console.log(`Browsing for site`)
    const { canceled, filePaths } = await dialog.showOpenDialog({
      properties: [`openDirectory`],
    })
    if (canceled || !filePaths?.length) {
      return undefined
    }

    const path = filePaths[0]
    try {
      const packageJson = await loadPackageJson(path)
      // i.e. actually installed in node_modules
      if (await hasGatsbyInstalled(path)) {
        return { packageJson, path }
      }
      // Has a dependency but it hasn't been installed
      if (hasGatsbyDependency(packageJson)) {
        return {
          packageJson,
          path,
          warning: `The site ${packageJson.name} is a Gatsby site, but needs dependencies to be installed before it can be started`,
        }
      }
    } catch (e) {
      console.log(e)
    }
    return {
      error: SiteError.NoGatsbyRepo,
      message: `The selected folder is not a Gatsby site. Please try another`,
    }
  })

  // Wait til the app is ready

  await app.whenReady()

  autoUpdater.checkForUpdatesAndNotify()
  // Check if the user has opted-in to telemetry
  initializeTelemetry()

  const displays = screen.getAllDisplays()

  trackEvent(`DISPLAY_METADATA`, {
    name: JSON.stringify(displays.map(({ size }) => size)),
  })

  mainWindow = makeWindow()

  tray = new Tray(path.resolve(dir, `assets`, `IconTemplate.png`))
  const contextMenu = Menu.buildFromTemplate([
    {
      label: `Show Gatsby Desktop`,
      click: openMainWindow,
    },
    {
      label: `Quit...`,
      click: async (): Promise<void> => {
        openMainWindow()
        app.quit()
      },
    },
  ])
  tray.setContextMenu(contextMenu)

  watchSites((sites) => {
    siteList = sites.map((site) => {
      const launcher = site.hash && siteLaunchers.get(site.hash)
      if (!launcher) {
        return {
          site,
        }
      }
      const { logs, rawLogs, status } = launcher
      return {
        site,
        status: { startedInDesktop: true, logs, rawLogs, status },
      }
    })
    if (mainWindow && !mainWindow.isDestroyed()) {
      mainWindow.webContents?.send(`sites-updated`, siteList)
    }
  })

  // If we're not running develop we can preload the start page

  if (!process.env.GATSBY_DEVELOP_URL) {
    mainWindow.loadURL(makeUrl())
    mainWindow.show()
  }
}
Example #23
Source File: ipcMainHandlers.ts    From deskreen with GNU Affero General Public License v3.0 4 votes vote down vote up
export default function initIpcMainHandlers(mainWindow: BrowserWindow) {
  ipcMain.on('client-changed-language', async (_, newLangCode) => {
    i18n.changeLanguage(newLangCode);
    if (store.has(ElectronStoreKeys.AppLanguage)) {
      if (store.get(ElectronStoreKeys.AppLanguage) === newLangCode) {
        return;
      }
      store.delete(ElectronStoreKeys.AppLanguage);
    }
    store.set(ElectronStoreKeys.AppLanguage, newLangCode);
  });

  ipcMain.handle('get-signaling-server-port', () => {
    if (mainWindow === null) return;
    mainWindow.webContents.send('sending-port-from-main', signalingServer.port);
  });

  ipcMain.handle('get-all-displays', () => {
    return screen.getAllDisplays();
  });

  ipcMain.handle('get-display-size-by-display-id', (_, displayID: string) => {
    const display = screen.getAllDisplays().find((d: Display) => {
      return `${d.id}` === displayID;
    });

    if (display) {
      return display.size;
    }
    return undefined;
  });

  ipcMain.handle('main-window-onbeforeunload', () => {
    const deskreenGlobal = getDeskreenGlobal();
    deskreenGlobal.connectedDevicesService = new ConnectedDevicesService();
    deskreenGlobal.roomIDService = new RoomIDService();
    deskreenGlobal.sharingSessionService.sharingSessions.forEach(
      (sharingSession: SharingSession) => {
        sharingSession.denyConnectionForPartner();
        sharingSession.destroy();
      }
    );

    deskreenGlobal.rendererWebrtcHelpersService.helpers.forEach(
      (helperWindow) => {
        helperWindow.close();
      }
    );

    deskreenGlobal.sharingSessionService.waitingForConnectionSharingSession = null;
    deskreenGlobal.rendererWebrtcHelpersService.helpers.clear();
    deskreenGlobal.sharingSessionService.sharingSessions.clear();
  });

  ipcMain.handle('get-latest-version', () => {
    return getDeskreenGlobal().latestAppVersion;
  });

  ipcMain.handle('get-current-version', () => {
    return getDeskreenGlobal().currentAppVersion;
  });

  ipcMain.handle('get-local-lan-ip', async () => {
    if (
      process.env.RUN_MODE === 'dev' ||
      process.env.NODE_ENV === 'production'
    ) {
      const ip = await v4IPGetter();
      return ip;
    }
    return '255.255.255.255';
  });

  ipcMain.handle(IpcEvents.GetAppPath, () => {
    const deskreenGlobal = getDeskreenGlobal();
    return deskreenGlobal.appPath;
  });

  ipcMain.handle(IpcEvents.UnmarkRoomIDAsTaken, (_, roomID) => {
    const deskreenGlobal = getDeskreenGlobal();
    deskreenGlobal.roomIDService.unmarkRoomIDAsTaken(roomID);
  });

  function onDeviceConnectedCallback(device: Device): void {
    getDeskreenGlobal().connectedDevicesService.setPendingConnectionDevice(
      device
    );
    mainWindow.webContents.send(IpcEvents.SetPendingConnectionDevice, device);
  }

  ipcMain.handle(IpcEvents.CreateWaitingForConnectionSharingSession, () => {
    getDeskreenGlobal()
      .sharingSessionService.createWaitingForConnectionSharingSession()
      // eslint-disable-next-line promise/always-return
      .then((waitingForConnectionSharingSession) => {
        waitingForConnectionSharingSession.setOnDeviceConnectedCallback(
          onDeviceConnectedCallback
        );
      })
      .catch((e) => log.error(e));
  });

  ipcMain.handle(IpcEvents.ResetWaitingForConnectionSharingSession, () => {
    const sharingSession = getDeskreenGlobal().sharingSessionService
      .waitingForConnectionSharingSession;
    sharingSession?.disconnectByHostMachineUser();
    sharingSession?.destroy();
    sharingSession?.setStatus(SharingSessionStatusEnum.NOT_CONNECTED);
    getDeskreenGlobal().sharingSessionService.sharingSessions.delete(
      sharingSession?.id as string
    );
    getDeskreenGlobal().sharingSessionService.waitingForConnectionSharingSession = null;
  });

  ipcMain.handle(IpcEvents.SetDeviceConnectedStatus, () => {
    if (
      getDeskreenGlobal().sharingSessionService
        .waitingForConnectionSharingSession !== null
    ) {
      const sharingSession = getDeskreenGlobal().sharingSessionService
        .waitingForConnectionSharingSession;
      sharingSession?.setStatus(SharingSessionStatusEnum.CONNECTED);
    }
  });

  ipcMain.handle(
    IpcEvents.GetSourceDisplayIDByDesktopCapturerSourceID,
    (_, sourceId) => {
      return getDeskreenGlobal().desktopCapturerSourcesService.getSourceDisplayIDByDisplayCapturerSourceID(
        sourceId
      );
    }
  );

  ipcMain.handle(
    IpcEvents.DisconnectPeerAndDestroySharingSessionBySessionID,
    (_, sessionId) => {
      const sharingSession = getDeskreenGlobal().sharingSessionService.sharingSessions.get(
        sessionId
      );
      if (sharingSession) {
        getDeskreenGlobal().connectedDevicesService.disconnectDeviceByID(
          sharingSession.deviceID
        );
      }
      sharingSession?.disconnectByHostMachineUser();
      sharingSession?.destroy();
      getDeskreenGlobal().sharingSessionService.sharingSessions.delete(
        sessionId
      );
    }
  );

  ipcMain.handle(
    IpcEvents.GetDesktopCapturerSourceIdBySharingSessionId,
    (_, sessionId) => {
      return getDeskreenGlobal().sharingSessionService.sharingSessions.get(
        sessionId
      )?.desktopCapturerSourceID;
    }
  );

  ipcMain.handle(IpcEvents.GetConnectedDevices, () => {
    return getDeskreenGlobal().connectedDevicesService.getDevices();
  });

  ipcMain.handle(IpcEvents.DisconnectDeviceById, (_, id) => {
    getDeskreenGlobal().connectedDevicesService.disconnectDeviceByID(id);
  });

  ipcMain.handle(IpcEvents.DisconnectAllDevices, () => {
    getDeskreenGlobal().connectedDevicesService.disconnectAllDevices();
  });

  ipcMain.handle(IpcEvents.AppLanguageChanged, (_, newLang) => {
    if (store.has(ElectronStoreKeys.AppLanguage)) {
      store.delete(ElectronStoreKeys.AppLanguage);
    }
    store.set(ElectronStoreKeys.AppLanguage, newLang);
    getDeskreenGlobal().sharingSessionService.sharingSessions.forEach(
      (sharingSession) => {
        sharingSession?.appLanguageChanged();
      }
    );
  });

  ipcMain.handle(IpcEvents.GetDesktopCapturerServiceSourcesMap, () => {
    const map = getDeskreenGlobal().desktopCapturerSourcesService.getSourcesMap();
    const res = {};
    // eslint-disable-next-line guard-for-in
    for (const key of map.keys()) {
      const source = map.get(key);
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      res[key] = {
        source: {
          thumbnail: source?.source.thumbnail?.toDataURL(),
          appIcon: source?.source.appIcon?.toDataURL(),
          name: source?.source.name,
        },
      };
    }
    return res;
  });

  ipcMain.handle(
    IpcEvents.GetWaitingForConnectionSharingSessionSourceId,
    () => {
      return getDeskreenGlobal().sharingSessionService
        .waitingForConnectionSharingSession?.desktopCapturerSourceID;
    }
  );

  ipcMain.handle(
    IpcEvents.StartSharingOnWaitingForConnectionSharingSession,
    () => {
      const sharingSession = getDeskreenGlobal().sharingSessionService
        .waitingForConnectionSharingSession;
      if (sharingSession !== null) {
        sharingSession.callPeer();
        sharingSession.status = SharingSessionStatusEnum.SHARING;
      }
      getDeskreenGlobal().connectedDevicesService.addDevice(
        getDeskreenGlobal().connectedDevicesService.pendingConnectionDevice
      );
      getDeskreenGlobal().connectedDevicesService.resetPendingConnectionDevice();
    }
  );

  ipcMain.handle(IpcEvents.GetPendingConnectionDevice, () => {
    return getDeskreenGlobal().connectedDevicesService.pendingConnectionDevice;
  });

  ipcMain.handle(IpcEvents.GetWaitingForConnectionSharingSessionRoomId, () => {
    if (
      getDeskreenGlobal().sharingSessionService
        .waitingForConnectionSharingSession === null
    ) {
      return undefined;
    }
    return getDeskreenGlobal().sharingSessionService
      .waitingForConnectionSharingSession?.roomID;
  });

  ipcMain.handle(
    IpcEvents.GetDesktopSharingSourceIds,
    (_, { isEntireScreenToShareChosen }) => {
      if (isEntireScreenToShareChosen === true) {
        return getDeskreenGlobal()
          .desktopCapturerSourcesService.getScreenSources()
          .map((source) => source.id);
      }
      return getDeskreenGlobal()
        .desktopCapturerSourcesService.getAppWindowSources()
        .map((source) => source.id);
    }
  );

  ipcMain.handle(IpcEvents.SetDesktopCapturerSourceId, (_, id) => {
    getDeskreenGlobal().sharingSessionService.waitingForConnectionSharingSession?.setDesktopCapturerSourceID(
      id
    );
  });

  ipcMain.handle(IpcEvents.NotifyAllSessionsWithAppThemeChanged, () => {
    getDeskreenGlobal().sharingSessionService.sharingSessions.forEach(
      (sharingSession) => {
        sharingSession?.appThemeChanged();
      }
    );
  });

  ipcMain.handle(IpcEvents.GetIsFirstTimeAppStart, () => {
    if (store.has(ElectronStoreKeys.IsNotFirstTimeAppStart)) {
      return false;
    }
    return true;
  });

  ipcMain.handle(IpcEvents.SetAppStartedOnce, () => {
    if (store.has(ElectronStoreKeys.IsNotFirstTimeAppStart)) {
      store.delete(ElectronStoreKeys.IsNotFirstTimeAppStart);
    }
    store.set(ElectronStoreKeys.IsNotFirstTimeAppStart, true);
  });

  ipcMain.handle(IpcEvents.GetIsAppDarkTheme, () => {
    if (store.has(ElectronStoreKeys.IsAppDarkTheme)) {
      return store.get(ElectronStoreKeys.IsAppDarkTheme);
    }
    return false;
  });

  ipcMain.handle(IpcEvents.SetIsAppDarkTheme, (_, isDarkTheme) => {
    if (store.has(ElectronStoreKeys.IsAppDarkTheme)) {
      store.delete(ElectronStoreKeys.IsAppDarkTheme);
    }
    store.set(ElectronStoreKeys.IsAppDarkTheme, isDarkTheme);
  });

  ipcMain.handle(IpcEvents.GetAppLanguage, () => {
    if (store.has(ElectronStoreKeys.AppLanguage)) {
      return store.get(ElectronStoreKeys.AppLanguage);
    }
    return 'en';
  });

  ipcMain.handle(IpcEvents.DestroySharingSessionById, (_, id) => {
    const sharingSession = getDeskreenGlobal().sharingSessionService.sharingSessions.get(
      id
    );
    sharingSession?.setStatus(SharingSessionStatusEnum.DESTROYED);
    sharingSession?.destroy();
    getDeskreenGlobal().sharingSessionService.sharingSessions.delete(id);
  });
}