price check refactor

This commit is contained in:
Alexander Drozdov
2020-06-20 01:10:17 +03:00
parent c59ab22368
commit afde91b2c8
8 changed files with 107 additions and 136 deletions
+6 -1
View File
@@ -4,11 +4,12 @@ import { app, protocol, ipcMain, screen } from 'electron'
import { installVueDevtools } from 'vue-cli-plugin-electron-builder/lib'
import { setupShortcuts } from './main/shortcuts'
import { createTray } from './main/tray'
import { setupShowHide } from './main/positioning'
import { setupShowHide } from './main/price-check'
import { setupConfigEvents, config } from './main/config'
import { CLOSE_SETTINGS_WINDOW } from '@/ipc/ipc-event'
import { closeWindow as closeSettings } from './main/SettingsWindow'
import { logger } from './main/logger'
import { checkForUpdates } from './main/updates'
import os from 'os'
import { createOverlayWindow } from './main/overlay-window'
import { setupAltVisibility } from './main/alt-visibility'
@@ -64,6 +65,10 @@ app.on('ready', async () => {
process.platform === 'linux' ? 1000 : 0
)
if (!isDevelopment) {
checkForUpdates()
}
ipcMain.on(CLOSE_SETTINGS_WINDOW, closeSettings)
})
+7
View File
@@ -15,6 +15,13 @@ export const FOCUS_CHANGE = 'OVERLAY::focus-change'
export const DPR_CHANGE = 'OVERLAY->MAIN::devicePixelRatio-change'
export const PRICE_CHECK = 'MAIN->OVERLAY::price-check'
export const PRICE_CHECK_CANCELED = 'MAIN->OVERLAY::price-check-canceled'
export interface IpcPriceCheck {
clipboard: string
position: { x: number, y: number }
}
export const SHOW_BROWSER = 'OVERLAY->MAIN::show-browser'
export interface IpcShowBrowser {
+3 -3
View File
@@ -48,9 +48,9 @@ class MainProcessBinding extends EventTarget {
}
}
selfEmitPriceCheck (data: { clipboard: string, position: string }) {
this.dispatchEvent(new CustomEvent('price-check', {
detail: data
selfEmitPriceCheck (e: ipcEvent.IpcPriceCheck) {
this.dispatchEvent(new CustomEvent(ipcEvent.PRICE_CHECK, {
detail: e
}))
}
-8
View File
@@ -33,14 +33,6 @@ class PoeWindowClass extends EventEmitter {
return Math.round(this.bounds!.height * ratio)
}
getPoeUiPosition (mousePos: Point) {
if (mousePos.x > (this.bounds!.x + this.bounds!.width / 2)) {
return 'inventory'
} else {
return 'stash' // or chat/vendor/center of screen
}
}
attach (window: BrowserWindow) {
OW.on('focus', () => { this.isActive = true })
OW.on('blur', () => { this.isActive = false })
+39 -39
View File
@@ -2,20 +2,25 @@ import path from 'path'
import { BrowserWindow, ipcMain, dialog } from 'electron'
import { PoeWindow } from './PoeWindow'
import { logger } from './logger'
import { OVERLAY_READY, FOCUS_CHANGE } from '@/ipc/ipc-event'
import * as ipc from '@/ipc/ipc-event'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import { checkForUpdates } from './updates'
import { overlayWindow as OW } from 'electron-overlay-window'
export let overlayWindow: BrowserWindow | undefined
export let isInteractable = false
export let DPR = 1
let _resolveOverlayReady: Function
let _resolveOverlayReady: () => void
export const overlayReady = new Promise<void>((resolve) => {
_resolveOverlayReady = resolve
})
export async function createOverlayWindow () {
ipcMain.once(ipc.OVERLAY_READY, _resolveOverlayReady)
ipcMain.on(ipc.DPR_CHANGE, (_: any, dpr: number) => handleDprChange(dpr))
PoeWindow.on('active-change', handlePoeWindowActiveChange)
PoeWindow.onceAttached(handleOverlayAttached)
overlayWindow = new BrowserWindow({
icon: path.join(__static, 'icon.png'),
...OW.WINDOW_OPTS,
@@ -28,49 +33,18 @@ export async function createOverlayWindow () {
}
})
overlayWindow.setIgnoreMouseEvents(true)
if (process.env.WEBPACK_DEV_SERVER_URL) {
overlayWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#overlay')
overlayWindow.webContents.openDevTools({ mode: 'detach', activate: false })
} else {
createProtocol('app')
overlayWindow.loadURL('app://./index.html#overlay')
checkForUpdates()
}
overlayWindow.setIgnoreMouseEvents(true)
ipcMain.once(OVERLAY_READY, () => {
_resolveOverlayReady()
})
PoeWindow.on('active-change', (isActive) => {
if (!overlayWindow) {
logger.error('Window is not ready')
return
}
if (isActive && isInteractable) {
isInteractable = false
overlayWindow.setIgnoreMouseEvents(true)
}
overlayWindow.webContents.send(FOCUS_CHANGE, { game: isActive, overlay: isInteractable })
})
PoeWindow.onceAttached((hasAccess) => {
if (hasAccess === false) {
dialog.showErrorBox(
'PoE window - No access',
// ----------------------
'Path of Exile is running with administrator rights.\n' +
'\n' +
'You need to restart Awakened PoE Trade with administrator rights.'
)
}
})
const electronReadyToShow = new Promise<void>((resolve) => {
overlayWindow!.once('ready-to-show', resolve)
})
const electronReadyToShow = new Promise<void>(resolve =>
overlayWindow!.once('ready-to-show', resolve))
await electronReadyToShow
await overlayReady
PoeWindow.attach(overlayWindow)
@@ -86,7 +60,15 @@ export function toggleOverlayState () {
} else {
focusOverlay()
}
overlayWindow.webContents.send(FOCUS_CHANGE, { game: PoeWindow.isActive, overlay: isInteractable })
overlayWindow.webContents.send(ipc.FOCUS_CHANGE, { game: PoeWindow.isActive, overlay: isInteractable })
}
function handlePoeWindowActiveChange (isActive: boolean) {
if (isActive && isInteractable) {
isInteractable = false
overlayWindow!.setIgnoreMouseEvents(true)
}
overlayWindow!.webContents.send(ipc.FOCUS_CHANGE, { game: isActive, overlay: isInteractable })
}
export function assertOverlayActive () {
@@ -118,3 +100,21 @@ function focusPoE () {
OW.focusTarget()
PoeWindow.isActive = true
}
function handleOverlayAttached (hasAccess?: boolean) {
if (hasAccess === false) {
dialog.showErrorBox(
'PoE window - No access',
// ----------------------
'Path of Exile is running with administrator rights.\n' +
'\n' +
'You need to restart Awakened PoE Trade with administrator rights.'
)
}
}
function handleDprChange (devicePixelRatio: number) {
if (process.platform === 'win32') {
DPR = devicePixelRatio
}
}
@@ -1,25 +1,31 @@
import { ipcMain, screen, Rectangle, BrowserView, Point, shell } from 'electron'
import { ipcMain, Rectangle, Point } from 'electron'
import { uIOhook } from 'uiohook-napi'
import { checkPressPosition, isPollingClipboard } from './shortcuts'
import { isPollingClipboard } from './shortcuts'
import { PoeWindow } from './PoeWindow'
import { PRICE_CHECK_HIDE, PRICE_CHECK_MOUSE, OPEN_LINK, OPEN_LINK_EXTERNAL, PRICE_CHECK_CANCELED, DPR_CHANGE } from '@/ipc/ipc-event'
import * as ipc from '@/ipc/ipc-event'
import { config } from './config'
import { logger } from './logger'
import { overlayWindow, isInteractable, assertOverlayActive, assertPoEActive } from './overlay-window'
import { overlayWindow, isInteractable, assertOverlayActive, assertPoEActive, DPR } from './overlay-window'
const WIDTH_96DPI = 460
const CLOSE_THRESHOLD_96DPI = 40
let DPR = 1
let isPriceCheckShown = false
let isClickedAfterLock = false
let checkPressPosition: Point | undefined
let activeAreaRect: Rectangle | undefined
let isMouseInside = false
let browserViewExternal: BrowserView | undefined
export function showWidget (opts: {
clipboard: string
hotkeyPressPosition: Point
lockedMode: boolean
}) {
checkPressPosition = opts.hotkeyPressPosition
overlayWindow!.webContents.send(ipc.PRICE_CHECK, { clipboard: opts.clipboard, position: checkPressPosition } as ipc.IpcPriceCheck)
export function showWindow () {
const poeBounds = PoeWindow.bounds!
activeAreaRect = {
x: getOffsetX(checkPressPosition!, poeBounds),
@@ -31,21 +37,9 @@ export function showWindow () {
isPriceCheckShown = true
isClickedAfterLock = false
isMouseInside = false
}
function hideWindow () {
isPriceCheckShown = false
isMouseInside = false
activeAreaRect = undefined
if (isInteractable) {
if (browserViewExternal) {
overlayWindow!.removeBrowserView(browserViewExternal)
// uncomment to trade performance for less memory usage (1 process & 13 MB)
// browserViewExternal.destroy()
// browserViewExternal = undefined
browserViewExternal.webContents.loadURL('about:blank')
}
if (opts.lockedMode) {
lockWindow(true)
}
}
@@ -56,7 +50,7 @@ export function lockWindow (syntheticClick = false) {
}
export function setupShowHide () {
ipcMain.on(PRICE_CHECK_HIDE, () => {
ipcMain.on(ipc.PRICE_CHECK_HIDE, () => {
logger.debug('Closing', { source: 'price-check', reason: 'Close button or hotkey' })
isPriceCheckShown = false
assertPoEActive()
@@ -69,13 +63,7 @@ export function setupShowHide () {
}
})
ipcMain.on(DPR_CHANGE, (_: any, devicePixelRatio: number) => {
if (process.platform === 'win32') {
DPR = devicePixelRatio
}
})
ipcMain.on(PRICE_CHECK_MOUSE, (e, name: string, modifier?: string) => {
ipcMain.on(ipc.PRICE_CHECK_MOUSE, (e, name: string, modifier?: string) => {
if (name === 'click') {
isClickedAfterLock = true
logger.debug('Clicked inside window after lock', { source: 'price-check' })
@@ -100,30 +88,6 @@ export function setupShowHide () {
}
})
ipcMain.on(OPEN_LINK, (e, link) => {
if (!browserViewExternal) {
browserViewExternal = new BrowserView()
}
overlayWindow!.setBrowserView(browserViewExternal)
let browserBounds = {
x: 0,
y: 0,
width: PoeWindow.bounds!.width - Math.floor(WIDTH_96DPI * DPR),
height: PoeWindow.bounds!.height
}
if (process.platform === 'win32') {
browserBounds = screen.screenToDipRect(overlayWindow!, browserBounds)
}
browserViewExternal.setBounds(browserBounds)
browserViewExternal.webContents.loadURL(link)
})
ipcMain.on(OPEN_LINK_EXTERNAL, (e, link) => {
hideWindow()
shell.openExternal(link)
})
uIOhook.on('mousemove', (e) => {
if (!isPriceCheckShown) return
@@ -134,7 +98,7 @@ export function setupShowHide () {
if (distance > (CLOSE_THRESHOLD_96DPI * DPR)) {
logger.debug('Closing', { source: 'price-check', reason: 'Auto-hide on mouse move', distance, threshold: CLOSE_THRESHOLD_96DPI })
overlayWindow!.webContents.send(PRICE_CHECK_CANCELED)
overlayWindow!.webContents.send(ipc.PRICE_CHECK_CANCELED)
isPriceCheckShown = false
}
} else if (!isMouseInside) {
@@ -146,7 +110,7 @@ export function setupShowHide () {
mousePos.y > activeAreaRect!.y &&
mousePos.y < activeAreaRect!.y + activeAreaRect!.height
) {
ipcMain.emit(PRICE_CHECK_MOUSE, undefined, 'enter', modifier)
ipcMain.emit(ipc.PRICE_CHECK_MOUSE, undefined, 'enter', modifier)
}
}
})
+10 -15
View File
@@ -2,17 +2,16 @@ import { screen, Point, clipboard, globalShortcut, Notification } from 'electron
import robotjs from 'robotjs'
import { uIOhook, UiohookKey } from 'uiohook-napi'
import { pollClipboard } from './PollClipboard'
import { showWindow, lockWindow } from './positioning'
import { showWidget as showPriceCheck } from './price-check'
import { KeyToElectron } from '@/ipc/KeyToCode'
import { PRICE_CHECK } from '@/ipc/ipc-event'
import { config } from './config'
import { PoeWindow } from './PoeWindow'
import { openWiki } from './wiki'
import { logger } from './logger'
import { toggleOverlayState, overlayWindow } from './overlay-window'
import { toggleOverlayState } from './overlay-window'
export let isPollingClipboard = false
export let checkPressPosition: Point | undefined
export let hotkeyPressPosition: Point | undefined
export const UiohookToName = Object.fromEntries(Object.entries(UiohookKey).map(([k, v]) => ([v, k])))
@@ -22,20 +21,16 @@ function priceCheck (lockedMode: boolean) {
if (!isPollingClipboard) {
isPollingClipboard = true
pollClipboard(32, 500)
.then(async (clipboard) => {
overlayWindow!.webContents.send(PRICE_CHECK, { clipboard, position: PoeWindow.getPoeUiPosition(checkPressPosition!) })
showWindow()
if (lockedMode) {
lockWindow(true)
}
})
.then(clipboard =>
showPriceCheck({ clipboard, hotkeyPressPosition: hotkeyPressPosition!, lockedMode })
)
.catch(() => { /* nothing bad */ })
.finally(() => { isPollingClipboard = false })
}
checkPressPosition = screen.getCursorScreenPoint()
if (process.platform === 'win32') {
checkPressPosition = screen.dipToScreenPoint(checkPressPosition)
}
hotkeyPressPosition = screen.getCursorScreenPoint()
// if (process.platform === 'win32') {
// hotkeyPressPosition = screen.dipToScreenPoint(hotkeyPressPosition)
// }
if (!lockedMode) {
if (config.get('priceCheckKeyHold') === 'Ctrl') {
+23 -15
View File
@@ -71,7 +71,7 @@ import BrowserMode from './BrowserMode'
import CheckedItem from './CheckedItem'
import AppBootstrap from './AppBootstrap'
import { MainProcess } from '@/ipc/main-process-bindings'
import { PRICE_CHECK_CANCELED } from '@/ipc/ipc-event'
import { PRICE_CHECK, PRICE_CHECK_CANCELED } from '@/ipc/ipc-event'
import { Prices, displayRounding } from './Prices'
import { Leagues } from './Leagues'
import { parseClipboard } from '@/parser'
@@ -100,34 +100,29 @@ export default {
}
},
created () {
MainProcess.addEventListener('price-check', ({ detail: { position, clipboard } }) => {
this.clickPosition = position
this.isBrowserShown = false
MainProcess.addEventListener(PRICE_CHECK, ({ detail: e }) => {
this.wm.closeBrowser(this.config.wmId)
this.wm.show(this.config.wmId)
this.item = parseClipboard(clipboard)
this.checkPosition = {
x: e.position.x - window.screenX,
y: e.position.y - window.screenY
}
this.item = parseClipboard(e.clipboard)
})
MainProcess.addEventListener(PRICE_CHECK_CANCELED, () => {
this.wm.hide(this.config.wmId)
})
MainProcess.addEventListener('open-link', () => {
this.clickPosition = 'inventory'
this.isBrowserShown = true
})
window.addEventListener('resize', this.updatePoeUiWidth)
this.updatePoeUiWidth()
},
data () {
return {
poeUiWidth: '0px',
clickPosition: 'stash',
isBrowserShown: false,
poeUiWidth: '1px',
checkPosition: { x: 1, y: 1 },
item: null
}
},
computed: {
browserMode () {
return !MainProcess.isElectron
},
title () {
if (!Leagues.isLoaded) {
return 'Awakened PoE Trade'
@@ -140,6 +135,19 @@ export default {
if (!Prices.isLoaded) return null
return Math.round(Prices.exaToChaos(1))
},
isBrowserShown () {
return this.config.wmFlags.includes('has-browser')
},
clickPosition () {
if (this.isBrowserShown) {
return 'inventory'
} else {
return this.checkPosition.x > (window.innerWidth / 2)
? 'inventory'
: 'stash'
// or {chat, vendor, center of screen}
}
}
},
methods: {