Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ jobs:
include:
- os: ubuntu-latest
artifact_name: sixgrid-linux-amd64.tar.gz
asset_name: "sixgrid-${{ github.sha }}-linux-amd64.tar.gz"
asset_name: "sixgrid-linux-amd64.tar.gz"
- os: ubuntu-latest
artifact_name: sixgrid-linux-amd64.zip
asset_name: "sixgrid-${{ github.sha }}-linux-amd64.zip"
asset_name: "sixgrid-linux-amd64.zip"
- os: ubuntu-latest
artifact_name: "sixgrid-linux-amd64.AppImage"
asset_name: "sixgrid-${{ github.sha }}-linux-amd64.AppImage"
asset_name: "sixgrid-linux-amd64.AppImage"
- os: windows-latest
artifact_name: sixgrid-windows-amd64-setup.msi
asset_name: "sixgrid-${{ github.sha }}-win-amd64-setup.msi"
asset_name: "sixgrid-win-amd64-setup.msi"
- os: windows-latest
artifact_name: sixgrid-windows-amd64.zip
asset_name: "sixgrid-${{ github.sha }}-win-amd64.zip"
asset_name: "sixgrid-win-amd64.zip"

steps:
- name: Check out Git Repo
Expand Down
186 changes: 186 additions & 0 deletions src/main/config/configManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { BrowserWindow, ipcMain } from 'electron'
import * as helpers from '../helpers'
import * as sharedHelper from '../../shared/sharedHelper'
import { ConfigFileMap, ConfigKeys, ConfigTypeMap, PostDataSetConfig } from '../../shared/config'
import { DefaultData as DefaultConfigData } from '../../shared/configDefault'
import path from 'path'
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'

export class ConfigManager {
static get instance() {
if (global.configManager == undefined)
{
global.configManager = new ConfigManager()
}
return global.configManager
}

static get baseDirectory() {
return helpers.steamCloudConfigDirectory()
}

/**
* @description
* Config Manager.
*
* Note: This class is a singleton and only one instance can be created.
* @throws
* Will throw the error `global.electronMainWindow is undefined!!!` when `global.electronMainWindow` hasn't been created yet.
*
* It will also throw an error when `global.configManager` is defined already. This is because ConfigManager is a singleton and only one instance can be created.
*/
constructor() {
if (global.electronMainWindow == undefined)
throw new Error('global.electronMainWindow is undefined!!!')
if (global.configManager != undefined)
throw new Error('Instance of global.configManager exists already!')

global.configManager = this

this.window = global.electronMainWindow
this.cache = sharedHelper.deepClone({}, DefaultConfigData) as ConfigTypeMap

this.loadData()

this.initIPC()

this.saveLoop = setInterval(() => {
this.saveAll(true)
}, 5000)
}

saveLoop: NodeJS.Timer
window: BrowserWindow
cache: ConfigTypeMap
/**
* @description
* Stores when a config was last modified via `ConfigManager.set()`
*/
lastModify: {[key in ConfigKeys]: number} = {
'Authentication': 0,
'User': 0,
'Statistics': 0,
'Keybind': 0
}
/**
* @description
* Stores when a config was last saved via `ConfigManager.save()`
*/
lastSave: {[key in ConfigKeys]: number} = {
'Authentication': 0,
'User': 0,
'Statistics': 0,
'Keybind': 0
}
pendingSave: {[key in ConfigKeys]: boolean} = {
'Authentication': false,
'User': false,
'Statistics': false,
'Keybind': false
}

private loadData()
{
if (!existsSync(ConfigManager.baseDirectory))
mkdirSync(ConfigManager.baseDirectory)
let entries = Object.entries(ConfigFileMap) as [ConfigKeys, string][]
for (let pair of entries)
{
let location = path.join(ConfigManager.baseDirectory, pair[1])
if (!existsSync(location))
{
writeFileSync(location, JSON.stringify(this.cache[pair[0]], null, ' '))
}

let data = readFileSync(location).toString()
let parsed = JSON.parse(data)
this.cache[pair[0]] = parsed
}
}

private initIPC()
{
ipcMain.handle('config.get', (event, key: String) =>
{
if (this.cache[key as ConfigKeys] == undefined)
throw new Error(`Key provided '${key}' does not exist`)
return this.cache[key as ConfigKeys]
})
ipcMain.handle('config.getKeys', (event) =>
{
return Object.entries(this.cache).map(v => v[0])
})
ipcMain.handle('config.set', (event, data: PostDataSetConfig) =>
{
return this.set(data.key, data.data)
})

ipcMain.handle('config.saveAll', (event) => {
return this.saveAll()
})
ipcMain.handle('config.save', (event, key: ConfigKeys) => {
return this.save(key)
})
ipcMain.handle('config.getValue', (event, configKey: ConfigKeys, dataKey: any) => {
return this.getValue(configKey, dataKey)
})
}
/**
* @description
* Save all cached configs.
* @param onlyPending Only save item if `pendingSave[key]` is true
*/
saveAll(onlyPending: boolean = false) {
for (let pair of Object.entries(this.cache)) {
if (onlyPending) {
if (!this.pendingSave[pair[0] as ConfigKeys])
continue;
}
this.save(pair[0] as ConfigKeys)
}
}

save(key: ConfigKeys) {
if (!existsSync(ConfigManager.baseDirectory))
mkdirSync(ConfigManager.baseDirectory)

let targetPath = path.join(
ConfigManager.baseDirectory,
ConfigFileMap[key])

let data = JSON.stringify(this.cache[key], null, ' ')
writeFileSync(targetPath, data)

this.pendingSave[key] = false
this.lastSave[key] = Date.now()
}

set(key: ConfigKeys, value: any): void
{
this.cache[key] = value
this.lastModify[key] = Date.now()
this.pendingSave[key] = true
}
get(key: ConfigKeys): void
{
if (this.cache[key] == undefined)
throw new Error(`Key '${key}' does not exist in cache`)
return sharedHelper.clone(this.cache[key])
}
getValue(configKey: ConfigKeys, dataKey: any): any {
if (this.cache[configKey] == undefined)
throw new Error(`Key '${configKey}' does not exist in cache`)
let d = this.cache[configKey] as any
return d[dataKey]
}

update(key: ConfigKeys): void
{
let data: any = this.get(key)
data = {
...DefaultConfigData[key],
...data
}
this.set(key, data)
}
}
34 changes: 34 additions & 0 deletions src/main/flags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { app } from 'electron'
import * as os from 'os'

export default {
customUrlEnable: app.commandLine.hasSwitch('url'),
customUrl: app.commandLine.getSwitchValue('url'),

winUrl_dev: 'http://localhost:9080',
get winUrl() {
if (this.debugMode && this.customUrlEnable)
{
return this.customUrlEnable ? this.customUrl : this.winUrl_dev
}
else
{
return process.env.NODE_ENV === 'development' ? this.winUrl_dev : `file://${__dirname}/index.html`
}
},

get debugMode() {
return app.commandLine.hasSwitch('developer')
|| app.commandLine.hasSwitch('dev')
|| process.env.NODE_ENV == 'development'
},


get steamworks() {
return app.commandLine.hasSwitch('steam')
},

get isSteamDeck() {
return os.release().toString().includes('valve') || app.commandLine.hasSwitch('deck')
}
}
5 changes: 4 additions & 1 deletion src/main/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { IProductInformation } from '../shared'
import type { BrowserWindow } from 'electron'
import type { GlobalShortcutData } from './globalShortcuts'
import type { GlobalShortcutData } from '../shared/config'
import type { ConfigManager } from './config/configManager'

declare global
{
var electronMainWindow: BrowserWindow|undefined
Expand All @@ -9,5 +11,6 @@ declare global
var __static: string
var debugMode: boolean
var globalShortcut_data: GlobalShortcutData
var configManager: ConfigManager
}

8 changes: 2 additions & 6 deletions src/main/globalShortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ import * as fs from 'fs'
import * as helpers from './helpers'
import { globalShortcut, app, ipcMain } from 'electron'

export interface GlobalShortcutData
{
relaunch: Electron.Accelerator|null
debugOutline: Electron.Accelerator|null
safeReload: Electron.Accelerator|null
}
import { GlobalShortcutData } from '../shared/config'

interface GlobalShortcutActions
{
relaunch(): void
Expand Down
51 changes: 5 additions & 46 deletions src/main/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { app, dialog } from 'electron'
import * as path from 'path'
import flags from './flags'
const _ProductInformation = __PRODUCT_EXTENDED_INFORMATION
export function isDevelopmentMode () {
if (app.commandLine.hasSwitch('dev'))
return true
return process.env.NODE_ENV === 'development'
}

export function fetchTitle () {
let value = `SixGrid v${__SIXGRID_PRODUCT_BUILD_VERSION} (${_ProductInformation.commitHashShort})`
if (electronMainWindow != undefined)
Expand All @@ -14,14 +11,8 @@ export function fetchTitle () {
}
export function safeReload () {
if (electronMainWindow != undefined)
electronMainWindow.loadURL(winURL)
electronMainWindow.loadURL(flags.winUrl)
}
export const winURL = (() => {
var value = isDevelopmentMode()
? `http://localhost:9080`
: `file://${process.platform == 'win32' ? '/' : ''}${__dirname.replaceAll('\\', '/')}/index.html`
return value
})()
export function relaunch () {
app.relaunch()
app.quit()
Expand All @@ -36,48 +27,16 @@ export function relaunchConfirm () {
`Relaunch`
]
})

if (btn == 1) {
relaunch()
}
}
export function stringArrayCharacterLength (input: string[]) {
let length = 0
for (let thing of input) {
length += thing.length
}
return length
}
export function paragraphSplit (input: string, maximumLineWidth: number) {
let resultList = [] /* string[][] */
let inputSplitted = input.split(' ')
let buffer = [] /* input[] */
for (let i = 0; i < inputSplitted.length; i++) {
let bufferCharLen = stringArrayCharacterLength(buffer) + buffer.length
if (bufferCharLen + inputSplitted[i].length + 1 > maximumLineWidth) {
resultList.push(buffer)
buffer = []
}
buffer.push(inputSplitted[i])
}

resultList.push(buffer)

let resultArray = []
for (let i = 0; i < resultList.length; i++) {
let tmp = [] /* string[] */
for (let x = 0; x < resultList[i].length; x++) {
tmp.push(resultList[i][x])
}
let tmpString = tmp.join(' ')
resultArray.push(tmpString)
}
return resultArray.join('\n')
}

export function steamCloudConfigDirectory() {
let target = path.join(path.dirname(process.execPath), 'AppConfig')
if (path.basename(process.execPath).startsWith('electron')) {
target = path.join(process.cwd(), 'AppConfig')
}
return target
}
}
5 changes: 5 additions & 0 deletions src/main/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { IProductInformation } from '../shared'
import type { BrowserWindow } from 'electron'
import type { GlobalShortcutData } from '../shared/config'
import type { ConfigManager } from './config/configManager'

declare global {
namespace NodeJS {
interface Global {
Expand All @@ -8,6 +11,8 @@ declare global {
__PRODUCT_EXTENDED_INFORMATION: IProductInformation
__static: string
debugMode: boolean
globalShortcut_data: GlobalShortcutData
configManager: ConfigManager
}
}
}
Expand Down
Loading