WIP transform map-check into item-info

This commit is contained in:
Alexander Drozdov
2021-03-09 23:51:41 +02:00
parent f852823b85
commit 3ef73f1874
15 changed files with 313 additions and 208 deletions
+2 -2
View File
@@ -30,8 +30,8 @@ export interface IpcPriceCheck {
position: { x: number, y: number }
}
export const MAP_CHECK = 'MAIN->OVERLAY::map-check'
export interface IpcMapCheck {
export const ITEM_CHECK = 'MAIN->OVERLAY::item-check'
export interface IpcItemCheck {
clipboard: string
position: { x: number, y: number }
}
+2 -2
View File
@@ -16,8 +16,8 @@ class MainProcessBinding extends EventTarget {
this.selfEmitPriceCheck(data)
})
electron.ipcRenderer.on(ipcEvent.MAP_CHECK, (e, data) => {
this.dispatchEvent(new CustomEvent(ipcEvent.MAP_CHECK, {
electron.ipcRenderer.on(ipcEvent.ITEM_CHECK, (e, data) => {
this.dispatchEvent(new CustomEvent(ipcEvent.ITEM_CHECK, {
detail: data
}))
})
+45 -43
View File
@@ -1,4 +1,4 @@
import { MapCheckWidget, PriceCheckWidget } from '@/web/overlay/interfaces'
import { ItemCheckWidget, PriceCheckWidget } from '@/web/overlay/interfaces'
export interface League {
id: string
@@ -18,7 +18,7 @@ export interface Config {
overlayBackgroundExclusive: boolean
overlayBackgroundClose: boolean
priceCheckShowCursor: boolean
mapCheckKey: string | null
itemCheckKey: string | null
delveGridKey: string | null
restoreClipboard: boolean
commands: Array<{
@@ -62,7 +62,7 @@ type WidgetWellKnownFlag =
'hide-on-focus'
export const defaultConfig: Config = {
configVersion: 6,
configVersion: 7,
priceCheckKey: 'D',
priceCheckKeyHold: 'Ctrl',
priceCheckLocked: 'Ctrl + Alt + D',
@@ -73,7 +73,7 @@ export const defaultConfig: Config = {
overlayBackgroundExclusive: true,
overlayBackgroundClose: true,
priceCheckShowCursor: true,
mapCheckKey: null,
itemCheckKey: null,
delveGridKey: null,
restoreClipboard: true,
commands: [{
@@ -142,49 +142,51 @@ export const defaultConfig: Config = {
} as PriceCheckWidget,
{
wmId: 3,
wmType: 'map-check',
wmType: 'item-check',
wmTitle: '',
wmWants: 'hide',
wmZorder: 'exclusive',
wmFlags: ['hide-on-blur', 'skip-menu'],
selectedStats: [
{
matcher: 'Slaying Enemies close together has a #% chance to attract monsters from Beyond',
invert: false,
valueWarning: '',
valueDanger: '',
valueDesirable: '+'
},
{
matcher: '#% maximum Player Resistances',
invert: true,
valueWarning: '-10',
valueDanger: '',
valueDesirable: ''
},
{
matcher: 'Monsters reflect #% of Physical Damage',
invert: false,
valueWarning: '',
valueDanger: '+',
valueDesirable: ''
},
{
matcher: 'Monsters reflect #% of Elemental Damage',
invert: false,
valueWarning: '',
valueDanger: '+',
valueDesirable: ''
},
{
matcher: 'Area contains two Unique Bosses',
invert: false,
valueWarning: '',
valueDanger: '',
valueDesirable: '+'
}
]
} as MapCheckWidget,
maps: {
selectedStats: [
{
matcher: 'Slaying Enemies close together has a #% chance to attract monsters from Beyond',
invert: false,
valueWarning: '',
valueDanger: '',
valueDesirable: '+'
},
{
matcher: '#% maximum Player Resistances',
invert: true,
valueWarning: '-10',
valueDanger: '',
valueDesirable: ''
},
{
matcher: 'Monsters reflect #% of Physical Damage',
invert: false,
valueWarning: '',
valueDanger: '+',
valueDesirable: ''
},
{
matcher: 'Monsters reflect #% of Elemental Damage',
invert: false,
valueWarning: '',
valueDanger: '+',
valueDesirable: ''
},
{
matcher: 'Area contains two Unique Bosses',
invert: false,
valueWarning: '',
valueDanger: '',
valueDesirable: '+'
}
]
}
} as ItemCheckWidget,
{
wmId: 4,
wmType: 'delve-grid',
+14 -1
View File
@@ -7,6 +7,7 @@ import { GET_CONFIG, PUSH_CONFIG, CLOSE_SETTINGS_WINDOW } from '@/ipc/ipc-event'
import { overlayWindow } from './overlay-window'
import { logger } from './logger'
import { LogWatcher } from './LogWatcher'
import { ItemCheckWidget } from '@/web/overlay/interfaces'
export function setupConfigEvents () {
ipcMain.on(GET_CONFIG, (e) => {
@@ -33,7 +34,7 @@ export const config = (() => {
if (forbidden.includes(config.priceCheckLocked as string)) { config.priceCheckLocked = null }
if (forbidden.includes(config.wikiKey as string)) { config.wikiKey = null }
if (forbidden.includes(config.craftOfExileKey as string)) { config.craftOfExileKey = null }
if (forbidden.includes(config.mapCheckKey as string)) { config.mapCheckKey = null }
if (forbidden.includes(config.itemCheckKey as string)) { config.itemCheckKey = null }
if (config.priceCheckKeyHold === 'Ctrl' && forbiddenCtrl.includes(config.priceCheckKey as string)) {
config.priceCheckKey = null
}
@@ -117,6 +118,18 @@ export const config = (() => {
config.configVersion = 6
}
if (config.configVersion < 7) {
const mapCheck = config.widgets.find(w => w.wmType === 'map-check')!
mapCheck.wmType = 'item-check'
;(mapCheck as ItemCheckWidget).maps = { selectedStats: mapCheck.selectedStats }
mapCheck.selectedStats = undefined
config.itemCheckKey = (config as any).mapCheckKey || null
;(config as any).mapCheckKey = undefined
config.configVersion = 7
}
store.store = config
return store
})()
+7 -7
View File
@@ -39,12 +39,12 @@ function priceCheck (lockedMode: boolean) {
}
}
function mapCheck () {
logger.info('Map check', { source: 'shortcuts' })
function itemCheck () {
logger.info('Item check', { source: 'shortcuts' })
pollClipboard()
.then(clipboard => {
overlayWindow!.webContents.send(ipc.MAP_CHECK, { clipboard, position: hotkeyPressPosition! } as ipc.IpcMapCheck)
overlayWindow!.webContents.send(ipc.ITEM_CHECK, { clipboard, position: hotkeyPressPosition! } as ipc.IpcItemCheck)
assertOverlayActive()
})
.catch(() => {})
@@ -83,8 +83,8 @@ function registerGlobal () {
}
),
shortcutCallback(
config.get('mapCheckKey'),
mapCheck
config.get('itemCheckKey'),
itemCheck
),
shortcutCallback(
config.get('delveGridKey'),
@@ -166,8 +166,8 @@ export function setupShortcuts () {
pollClipboard().then(openCraftOfExile).catch(() => {})
robotjs.keyTap('C', ['Ctrl'])
}).cb()
} else if (pressed === config.get('mapCheckKey')) {
shortcutCallback(pressed, mapCheck).cb()
} else if (pressed === config.get('itemCheckKey')) {
shortcutCallback(pressed, itemCheck).cb()
} else if (pressed === config.get('delveGridKey')) {
shortcutCallback(pressed, toggleDelveGrid, { doNotResetModKey: true }).cb()
} else {
+48
View File
@@ -0,0 +1,48 @@
<template>
<div class="bg-gray-800 text-gray-200 border-gray-900 border-4" style="min-width: 20rem;" :style="{ 'max-width': `min(${wm.width - wm.poeUiWidth}px, 30rem)` }">
<div class="bg-gray-900 py-1 px-4 text-center">{{ itemName }}</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, computed, inject } from 'vue'
import { useI18n } from 'vue-i18n'
import { ItemRarity, ParsedItem } from '@/parser'
import { TRANSLATED_ITEM_NAME_BY_REF } from '@/assets/data'
import { WidgetManager } from '../overlay/interfaces'
export default defineComponent({
props: {
item: {
type: Object as PropType<ParsedItem>,
required: true
}
},
setup (props) {
const wm = inject<WidgetManager>('wm')!
const { t } = useI18n()
const itemName = computed(() => {
const { item } = props
if (item.rarity === ItemRarity.Unique) {
return TRANSLATED_ITEM_NAME_BY_REF.get(item.name || item.baseType)
} else {
return TRANSLATED_ITEM_NAME_BY_REF.get(item.baseType || item.name)
}
})
return {
t,
wm,
itemName
}
}
})
</script>
<i18n>
{
"ru": {
}
}
</i18n>
+94
View File
@@ -0,0 +1,94 @@
<template>
<widget :config="{ ...config, anchor }" move-handles="none" readonly :removable="false">
<map-check v-if="isMapLike"
:item="item" />
<item-info v-else-if="item"
:item="item" />
</widget>
</template>
<script lang="ts">
import { defineComponent, PropType, computed, inject, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Widget from '../overlay/Widget.vue'
import MapCheck from '../map-check/MapCheck.vue'
import ItemInfo from './ItemInfo.vue'
import { MainProcess } from '@/ipc/main-process-bindings'
import { ITEM_CHECK } from '@/ipc/ipc-event'
import { ItemCategory, parseClipboard, ParsedItem } from '@/parser'
import { ItemCheckWidget, WidgetManager } from '../overlay/interfaces'
import * as ipc from '@/ipc/ipc-event'
export default defineComponent({
components: {
Widget,
MapCheck,
ItemInfo
},
props: {
config: {
type: Object as PropType<ItemCheckWidget>,
required: true
}
},
setup (props) {
const wm = inject<WidgetManager>('wm')!
const { t } = useI18n()
const checkPosition = ref({ x: 1, y: 1 })
const item = ref<ParsedItem | null>(null)
MainProcess.addEventListener(ITEM_CHECK, (e) => {
const _e = (e as CustomEvent<ipc.IpcItemCheck>).detail
checkPosition.value = {
x: _e.position.x - window.screenX,
y: _e.position.y - window.screenY
}
item.value = parseClipboard(_e.clipboard)
if (item.value) {
wm.show(props.config.wmId)
}
})
props.config.wmWants = 'hide'
const anchor = computed(() => {
const side = checkPosition.value.x > (wm.width / 2)
? 'inventory'
: 'stash'
return {
pos: side === 'stash' ? 'cl' : 'cr',
y: 50,
x: side === 'stash'
? (wm.poeUiWidth / wm.width) * 100
: ((wm.width - wm.poeUiWidth) / wm.width) * 100
}
})
const isMapLike = computed(() => {
if (!item.value) return false
const { category } = item.value
return (
category === ItemCategory.Map ||
category === ItemCategory.HeistContract ||
category === ItemCategory.HeistBlueprint ||
category === ItemCategory.MavenInvitation)
})
return {
t,
anchor,
item,
isMapLike
}
}
})
</script>
<i18n>
{
"ru": {
}
}
</i18n>
+71
View File
@@ -0,0 +1,71 @@
<template>
<div class="bg-gray-800 text-gray-200 border-gray-900 border-4" style="min-width: 20rem;" :style="{ 'max-width': `min(${wm.width - wm.poeUiWidth}px, 30rem)` }">
<div class="bg-gray-900 py-1 px-4 text-center">{{ mapName }}</div>
<fullscreen-image v-if="image" :src="image" />
<div v-if="!mapStats.length" class="px-8 py-2">
{{ t('Item has no modifiers.') }}
</div>
<div v-else class="py-2 flex flex-col">
<map-stat-button v-for="stat in mapStats" :key="stat.text"
:stat="stat" />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, computed, inject } from 'vue'
import { useI18n } from 'vue-i18n'
import { ItemRarity, ParsedItem } from '@/parser'
import MapStatButton from './MapStatButton.vue'
import { prepareMapStats } from './prepare-map-stats'
import { TRANSLATED_ITEM_NAME_BY_REF, MAP_IMGS } from '@/assets/data'
import { WidgetManager } from '../overlay/interfaces'
export default defineComponent({
components: {
MapStatButton
},
props: {
item: {
type: Object as PropType<ParsedItem>,
required: true
}
},
setup (props) {
const wm = inject<WidgetManager>('wm')!
const { t } = useI18n()
const mapName = computed(() => {
const { item } = props
if (item.rarity === ItemRarity.Unique) {
return TRANSLATED_ITEM_NAME_BY_REF.get(item.name || item.baseType)
} else {
return TRANSLATED_ITEM_NAME_BY_REF.get(item.baseType || item.name)
}
})
const mapStats = computed(() => {
return prepareMapStats(props.item)
})
const image = computed(() => {
const entry = mapName.value && MAP_IMGS.get(mapName.value)
return entry && entry.img
})
return {
t,
wm,
mapName,
image,
mapStats
}
}
})
</script>
<i18n>
{
"ru": {
"Item has no modifiers.": "На предмете нету модов."
}
}
</i18n>
+5 -5
View File
@@ -28,7 +28,7 @@ import { defineComponent, PropType, computed } from 'vue'
import ItemModifierText from '../ui/ItemModifierText.vue'
import { Config } from '@/web/Config'
import { PreparedStat } from './prepare-map-stats'
import { MapCheckWidget } from '../overlay/interfaces'
import { ItemCheckWidget } from '../overlay/interfaces'
export default defineComponent({
components: { ItemModifierText },
@@ -40,11 +40,11 @@ export default defineComponent({
},
setup (props) {
const config = computed(() => {
return Config.store.widgets.find(widget => widget.wmType === 'map-check') as MapCheckWidget
return Config.store.widgets.find(widget => widget.wmType === 'item-check') as ItemCheckWidget
})
const entryInSelected = computed(() => {
return config.value.selectedStats.find(_ => _.matcher === props.stat.matcher)
return config.value.maps.selectedStats.find(_ => _.matcher === props.stat.matcher)
})
const state = computed(() => {
@@ -105,7 +105,7 @@ export default defineComponent({
state,
handleClick () {
if (!entryInSelected.value) {
config.value.selectedStats.push({
config.value.maps.selectedStats.push({
matcher: props.stat.matcher,
invert: false,
valueDanger: '+',
@@ -124,7 +124,7 @@ export default defineComponent({
entryInSelected.value.valueWarning = ''
entryInSelected.value.valueDesirable = '+'
} else if (entryInSelected.value.valueDesirable === '+') {
config.value.selectedStats = config.value.selectedStats.filter(selected => selected !== entryInSelected.value)
config.value.maps.selectedStats = config.value.maps.selectedStats.filter(selected => selected !== entryInSelected.value)
}
}
}
-125
View File
@@ -1,125 +0,0 @@
<template>
<widget :config="{ ...config, anchor }" move-handles="none" readonly :removable="false">
<div class="bg-gray-800 text-gray-200 border-gray-900 border-4" style="min-width: 20rem;" :style="{ 'max-width': `min(${wm.width - wm.poeUiWidth}px, 30rem)` }">
<div class="bg-gray-900 py-1 px-4 text-center">{{ mapName }}</div>
<fullscreen-image v-if="image" :src="image" />
<div v-if="!item" class="px-8 py-2">
{{ t('Item under cursor is not a craftable map-like item.') }}
</div>
<div v-else-if="!mapStats.length" class="px-8 py-2">
{{ t('Item has no modifiers.') }}
</div>
<div v-else class="py-2 flex flex-col">
<map-stat-button v-for="stat in mapStats" :key="stat.text"
:stat="stat" />
</div>
</div>
</widget>
</template>
<script lang="ts">
import { defineComponent, PropType, computed, inject, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Widget from '../overlay/Widget.vue'
import { MainProcess } from '@/ipc/main-process-bindings'
import { MAP_CHECK } from '@/ipc/ipc-event'
import { parseClipboard, ItemCategory, ItemRarity, ParsedItem } from '@/parser'
import MapStatButton from './MapStatButton.vue'
import { prepareMapStats } from './prepare-map-stats'
import { TRANSLATED_ITEM_NAME_BY_REF, MAP_IMGS } from '@/assets/data'
import { MapCheckWidget, WidgetManager } from '../overlay/interfaces'
import * as ipc from '@/ipc/ipc-event'
export default defineComponent({
components: {
Widget,
MapStatButton
},
props: {
config: {
type: Object as PropType<MapCheckWidget>,
required: true
}
},
setup (props) {
const wm = inject<WidgetManager>('wm')!
const { t } = useI18n()
const checkPosition = ref({ x: 1, y: 1 })
const item = ref<ParsedItem | null>(null)
MainProcess.addEventListener(MAP_CHECK, (e) => {
const _e = (e as CustomEvent<ipc.IpcMapCheck>).detail
wm.show(props.config.wmId)
checkPosition.value = {
x: _e.position.x - window.screenX,
y: _e.position.y - window.screenY
}
item.value = null
const item_ = parseClipboard(_e.clipboard)
if (item_?.category === ItemCategory.Map ||
item_?.category === ItemCategory.HeistContract ||
item_?.category === ItemCategory.HeistBlueprint ||
item_?.category === ItemCategory.MavenInvitation) {
item.value = item_
}
})
props.config.wmWants = 'hide'
const anchor = computed(() => {
const side = checkPosition.value.x > (wm.width / 2)
? 'inventory'
: 'stash'
return {
pos: side === 'stash' ? 'cl' : 'cr',
y: 50,
x: side === 'stash'
? (wm.poeUiWidth / wm.width) * 100
: ((wm.width - wm.poeUiWidth) / wm.width) * 100
}
})
const mapName = computed(() => {
if (!item.value) {
return t('Invalid item')
}
if (item.value.rarity === ItemRarity.Unique) {
return TRANSLATED_ITEM_NAME_BY_REF.get(item.value.name || item.value.baseType)
} else {
return TRANSLATED_ITEM_NAME_BY_REF.get(item.value.baseType || item.value.name)
}
})
const mapStats = computed(() => {
return prepareMapStats(item.value!)
})
const image = computed(() => {
if (!item.value) return undefined
const entry = mapName.value && MAP_IMGS.get(mapName.value)
return entry && entry.img
})
return {
t,
anchor,
wm,
mapName,
image,
item,
mapStats
}
}
})
</script>
<i18n>
{
"ru": {
"Item under cursor is not a craftable map-like item.": "Предмет под курсором не является крафтовым предметом, таким как карта.",
"Invalid item": "Неверный предмет",
"Item has no modifiers.": "На предмете нету модов."
}
}
</i18n>
+2 -2
View File
@@ -26,7 +26,7 @@ import WidgetStashSearch from './WidgetStashSearch'
import WidgetMenu from './WidgetMenu'
import PriceCheckWindow from '@/web/price-check/PriceCheckWindow'
import WidgetDebug from './WidgetDebug'
import WidgetMapCheck from '@/web/map-check/WidgetMapCheck'
import WidgetItemCheck from '@/web/item-check/WidgetItemCheck'
import WidgetImageStrip from './WidgetImageStrip'
import WidgetDelveGrid from './WidgetDelveGrid'
import { registerOtherServices } from '../other-services'
@@ -45,7 +45,7 @@ export default {
WidgetMenu,
WidgetPriceCheck: PriceCheckWindow,
WidgetDebug,
WidgetMapCheck,
WidgetItemCheck,
WidgetImageStrip,
WidgetDelveGrid,
LoadingAnimation
+10 -8
View File
@@ -51,14 +51,16 @@ export interface PriceCheckWidget extends Widget {
apiLatencySeconds: number
}
export interface MapCheckWidget extends Widget {
selectedStats: Array<{
matcher: string
invert: boolean
valueWarning: string
valueDanger: string
valueDesirable: string
}>
export interface ItemCheckWidget extends Widget {
maps: {
selectedStats: Array<{
matcher: string
invert: boolean
valueWarning: string
valueDanger: string
valueDesirable: string
}>
}
}
export interface StopwatchWidget extends Widget {
+7 -7
View File
@@ -19,7 +19,7 @@
import { defineComponent, computed, nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
import { Config } from '@/web/Config'
import { MapCheckWidget } from '../overlay/interfaces'
import { ItemCheckWidget } from '../overlay/interfaces'
export default defineComponent({
emits: [],
@@ -35,10 +35,10 @@ export default defineComponent({
},
setup (props) {
const config = computed(() => {
return Config.store.widgets.find(widget => widget.wmType === 'map-check') as MapCheckWidget
return Config.store.widgets.find(widget => widget.wmType === 'item-check') as ItemCheckWidget
})
const entryInSelected = computed(() => {
return config.value.selectedStats.find(_ => _.matcher === props.matcher)
return config.value.maps.selectedStats.find(_ => _.matcher === props.matcher)
})
const invert = computed<boolean>({
@@ -58,9 +58,9 @@ export default defineComponent({
set (value) { setProp('valueDesirable', value) }
})
function setProp<T extends keyof MapCheckWidget['selectedStats'][number]> (
function setProp<T extends keyof ItemCheckWidget['maps']['selectedStats'][number]> (
key: T,
value: MapCheckWidget['selectedStats'][number][T]
value: ItemCheckWidget['maps']['selectedStats'][number][T]
) {
if (entryInSelected.value) {
entryInSelected.value[key] = value
@@ -68,7 +68,7 @@ export default defineComponent({
removeIfNotUsed()
}
} else {
config.value.selectedStats.push({
config.value.maps.selectedStats.push({
matcher: props.matcher,
invert: false,
valueWarning: '',
@@ -94,7 +94,7 @@ export default defineComponent({
function remove () {
if (!entryInSelected.value) return
config.value.selectedStats = config.value.selectedStats
config.value.maps.selectedStats = config.value.maps.selectedStats
.filter(selected => selected !== entryInSelected.value)
}
+3 -3
View File
@@ -32,8 +32,8 @@
</div>
<div class="mb-4">
<div class="flex">
<div class="flex-1">{{ t('Map check') }}</div>
<hotkey-input v-model="config.mapCheckKey" class="w-48" />
<div class="flex-1">{{ t('Item info') }}</div>
<hotkey-input v-model="config.itemCheckKey" class="w-48" />
</div>
</div>
<div v-if="config.language === 'en'" class="mb-4">
@@ -88,7 +88,7 @@ export default defineComponent({
"Open without auto-hide": "Открыть без авто-скрытия",
"Overlay": "Оверлей",
"Open item on wiki": "Открыть предмет в вики",
"Map check": "Проверка карты",
"Item info": "Проверка предмета",
"Stash tab scrolling": "Прокрутка вкладок тайника",
"Delve grid": "Сетка \"Спуска\""
}
+3 -3
View File
@@ -48,7 +48,7 @@ import { useI18n } from 'vue-i18n'
import { Config } from '@/web/Config'
import { STATS } from '@/assets/data'
import MapsStatEntry from './MapsStatEntry.vue'
import { MapCheckWidget } from '../overlay/interfaces'
import { ItemCheckWidget } from '../overlay/interfaces'
import VirtualScroll from '../ui/VirtualScroll.vue'
const statList = computed(() => {
@@ -67,7 +67,7 @@ export default defineComponent({
const onlySelected = ref(true)
const config = computed(() => {
return Config.store.widgets.find(widget => widget.wmType === 'map-check') as MapCheckWidget
return Config.store.widgets.find(widget => widget.wmType === 'item-check') as ItemCheckWidget
})
const { t } = useI18n()
@@ -82,7 +82,7 @@ export default defineComponent({
return statList.value.filter(stat =>
q.every(part => stat.searchStr.includes(part)) &&
(onlySelected.value
? (config.value.selectedStats.some(selected => selected.matcher === stat.matchStr))
? (config.value.maps.selectedStats.some(selected => selected.matcher === stat.matchStr))
: true)
)
}),