Added MacOS support (#403)

This commit is contained in:
Harry Yu
2023-12-06 23:23:25 -08:00
committed by GitHub
parent 18d079b811
commit 588b801a26
10 changed files with 109 additions and 19 deletions

43
DEVELOPING.md Normal file
View File

@@ -0,0 +1,43 @@
# How this works
There are 2 main parts of the app:
1. renderer: this is the HTML/Javascript-based UI rendered within the Electron container. This runs Vue.js, a React-like Javascript framework for rendering front-end.
2. main: includes the main app (written in Electron). Handles keyboard shortcuts, brings up the UI and overlays.
Note that these 2 both depend on each other, and one cannot run without the other.
# How to develop
The most up-to-date instructions can always be derived from CI:
[.github/workflows/main.yml](https://github.com/SnosMe/awakened-poe-trade/blob/master/.github/workflows/main.yml)
Here's what that looks like as of 2023-12-03.
```shell
cd renderer
yarn install
yarn make-index-files
yarn dev
# In a second shell
cd main
yarn install
yarn dev
```
# How to build
```shell
cd renderer
yarn install
yarn make-index-files
yarn build
cd ../main
yarn build
# We want to sign with a distribution certificate to ensure other users can
# install without errors
CSC_NAME="Certificate name in Keychain" yarn package
```

View File

@@ -15,7 +15,7 @@
### Development
Follow instructions similar to CI [.github/workflows/main.yml](https://github.com/SnosMe/awakened-poe-trade/blob/master/.github/workflows/main.yml)
See [DEVELOPING.md](./DEVELOPING.md)
### Acknowledgments

View File

@@ -217,7 +217,9 @@ export const KeyToElectron = {
Backslash: '\\',
BracketRight: ']',
Quote: "'",
Ctrl: 'CmdOrCtrl',
// Do not change Ctrl to CmdOrCtrl. It causes registered shortcuts to
// often not work on Mac for unknown reasons.
Ctrl: 'Ctrl',
Alt: 'Alt',
Shift: 'Shift'
}

View File

@@ -21,6 +21,13 @@ win:
linux:
target:
- "AppImage"
mac:
target:
- target: default
arch:
- universal
# MacOS apps can only be run on other systems if signed
forceCodeSigning: true
appImage:
executableArgs:
- "--sandbox"

View File

@@ -8,9 +8,21 @@ export class AppTray {
serverPort = 0
constructor (server: ServerEvents) {
this.tray = new Tray(
nativeImage.createFromPath(path.join(__dirname, process.env.STATIC!, process.platform === 'win32' ? 'icon.ico' : 'icon.png'))
let trayImage = nativeImage.createFromPath(
path.join(
__dirname,
process.env.STATIC!,
process.platform === "win32" ? "icon.ico" : "icon.png"
)
)
if (process.platform === 'darwin') {
// Mac image size needs to be smaller, or else it looks huge. Size
// guideline is from https://iconhandbook.co.uk/reference/chart/osx/
trayImage = trayImage.resize({ width: 22, height: 22 })
}
this.tray = new Tray(trayImage)
this.tray.setToolTip(`Awakened PoE Trade v${app.getVersion()}`)
this.rebuildMenu()

View File

@@ -2,6 +2,7 @@ import fs from 'fs/promises'
import path from 'path'
import ini from 'ini'
import { app } from 'electron'
import process from 'process';
import { hotkeyToString, CodeToKey } from '../../../ipc/KeyToCode'
import type { Logger } from '../RemoteLogger'
import type { ServerEvents } from '../server'
@@ -21,7 +22,12 @@ export class GameConfig {
if (this.filePath === filePath) return
if (!filePath) {
filePath = path.join(app.getPath('documents'), 'My Games', 'Path of Exile', 'production_Config.ini')
if (process.platform === 'darwin') {
filePath = path.join(app.getPath('appData'), 'Path of Exile', 'Preferences', 'production_Config.ini')
} else {
filePath = path.join(app.getPath('documents'), 'My Games', 'Path of Exile', 'production_Config.ini')
}
try {
await fs.access(filePath)
// this.server.sendEventTo('any', {

View File

@@ -1,12 +1,8 @@
import { promises as fs, watchFile, unwatchFile } from 'fs'
import { app } from 'electron';
import { ServerEvents } from '../server'
import { Logger } from '../RemoteLogger'
const COMMON_PATH = [
'C:\\Program Files (x86)\\Grinding Gear Games\\Path of Exile\\logs\\Client.txt',
'C:\\Program Files (x86)\\Steam\\steamapps\\common\\Path of Exile\\logs\\Client.txt'
]
export class GameLogWatcher {
private offset = 0
private filePath?: string
@@ -22,8 +18,20 @@ export class GameLogWatcher {
async restart (logFile: string | null) {
if (this.filePath === logFile) return
if (!logFile && process.platform === 'win32') {
for (const filePath of COMMON_PATH) {
if (!logFile) {
let possiblePaths: string[] = []
if (process.platform === 'win32') {
possiblePaths = [
'C:\\Program Files (x86)\\Grinding Gear Games\\Path of Exile\\logs\\Client.txt',
'C:\\Program Files (x86)\\Steam\\steamapps\\common\\Path of Exile\\logs\\Client.txt'
]
} else if (process.platform === 'darwin') {
possiblePaths = [
`${app.getPath('home')}/Library/Caches/com.GGG.PathOfExile/Logs/Client.txt`
]
}
for (const filePath of possiblePaths) {
try {
await fs.access(filePath)
// this.server.sendEventTo('any', {

View File

@@ -224,7 +224,16 @@ export class Shortcuts {
function pressKeysToCopyItemText (pressedModKeys: string[] = [], showModsKey: string) {
let keys = mergeTwoHotkeys('Ctrl + C', showModsKey).split(' + ')
keys = keys.filter(key => key !== 'C' && !pressedModKeys.includes(key))
keys = keys.filter(key => key !== 'C')
if (process.platform !== 'darwin') {
// On non-Mac platforms, don't toggle keys that are already being pressed.
//
// For unknown reasons, we need to toggle pressed keys on Mac for advanced
// mod descriptions to be copied. You can test this by setting the shortcut
// to "Alt + any letter". They'll work with this line, but not if it's
// commented out.
keys = keys.filter(key => !pressedModKeys.includes(key))
}
for (const key of keys) {
uIOhook.keyToggle(UiohookKey[key as UiohookKeyT], 'down')

View File

@@ -1,4 +1,5 @@
import { uIOhook, UiohookKey as Key } from 'uiohook-napi'
import process from 'process';
import type { HostClipboard } from './HostClipboard'
import type { OverlayWindow } from '../windowing/OverlayWindow'
@@ -14,14 +15,16 @@ const AUTO_CLEAR = [
export function typeInChat (text: string, send: boolean, clipboard: HostClipboard) {
clipboard.restoreShortly((clipboard) => {
const modifiers = process.platform === 'darwin' ? [Key.Meta] : [Key.Ctrl]
if (text.startsWith(PLACEHOLDER_LAST)) {
text = text.slice(`${PLACEHOLDER_LAST} `.length)
clipboard.writeText(text)
uIOhook.keyTap(Key.Enter, [Key.Ctrl])
uIOhook.keyTap(Key.Enter, modifiers)
} else if (text.endsWith(PLACEHOLDER_LAST)) {
text = text.slice(0, -PLACEHOLDER_LAST.length)
clipboard.writeText(text)
uIOhook.keyTap(Key.Enter, [Key.Ctrl])
uIOhook.keyTap(Key.Enter, modifiers)
uIOhook.keyTap(Key.Home)
// press twice to focus input when using controller
uIOhook.keyTap(Key.Home)
@@ -30,11 +33,11 @@ export function typeInChat (text: string, send: boolean, clipboard: HostClipboar
clipboard.writeText(text)
uIOhook.keyTap(Key.Enter)
if (!AUTO_CLEAR.includes(text[0])) {
uIOhook.keyTap(Key.A, [Key.Ctrl])
uIOhook.keyTap(Key.A, modifiers)
}
}
uIOhook.keyTap(Key.V, [Key.Ctrl])
uIOhook.keyTap(Key.V, modifiers)
if (send) {
uIOhook.keyTap(Key.Enter)
@@ -56,7 +59,7 @@ export function stashSearch (
overlay.assertGameActive()
clipboard.writeText(text)
uIOhook.keyTap(Key.F, [Key.Ctrl])
uIOhook.keyTap(Key.V, [Key.Ctrl])
uIOhook.keyTap(Key.V, [process.platform === 'darwin' ? Key.Meta : Key.Ctrl])
uIOhook.keyTap(Key.Enter)
})
}

View File

@@ -34,7 +34,7 @@ export class GameWindow extends EventEmitter {
if (!this._isTracking) {
OverlayController.events.on('focus', () => { this.isActive = true })
OverlayController.events.on('blur', () => { this.isActive = false })
OverlayController.attachByTitle(window, title)
OverlayController.attachByTitle(window, title, { hasTitleBarOnMac: true })
this._isTracking = true
}
}