diff --git a/package.json b/package.json index 3134a798..4689ecf0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vitrine", - "version": "0.9.3", + "version": "0.9.4", "description": "Centralize all of your games within a simple interface.", "main": "public/server.js", "productName": "Vitrine", @@ -29,7 +29,6 @@ "discord-rich-presence": "^0.0.6", "download-file": "^0.1.5", "electron-updater": "^2.21.3", - "foreach-end": "1.1.0", "fs-extra": "6.0.0", "gamepad-listener": "0.4.0", "glob": "^7.1.2", @@ -48,6 +47,7 @@ "rimraf": "^2.6.2", "semantic-ui-react": "0.80.0", "steam-web": "0.7.0", + "steam-web-promise": "^0.8.0", "uuid": "^3.2.1", "winreg": "^1.2.4" }, @@ -102,7 +102,7 @@ "node-windows": "^0.1.14" }, "scripts": { - "start": "electron .", + "start": "cross-env ELECTRON_ENV=dev electron .", "build:app": "parallel-webpack --progress --config=webpack/base.config.js", "build:prod": "cross-env NODE_ENV=prod parallel-webpack --progress --config=webpack/base.config.js", "build:server": "parallel-webpack --progress --config=webpack/server.config.js", diff --git a/scripts/build_modules.js b/scripts/build_modules.js index 176748ef..59db8fa6 100644 --- a/scripts/build_modules.js +++ b/scripts/build_modules.js @@ -5,19 +5,19 @@ const { cd, exec, grep, mkdir, mv, rm } = require('shelljs'); const electronUrl = 'https://atom.io/download/electron'; const electronVersion = grep('"electron":', 'package.json') - .sed(/[ ]+"electron": "[\^]?(.*)"[,]?/, '$1') - .replace(/\n/, ''); + .sed(/[ ]+"electron": "[\^]?(.*)"[,]?/, '$1') + .replace(/\n/, ''); mkdir('-p', 'modules'); cd('sources/modules'); readdir(resolve()).then((modules) => { - for (const module of modules.filter((module) => statSync(module).isDirectory())) { - cd(module); - exec(`${resolve('../../../node_modules/.bin/node-gyp')} rebuild --target=${electronVersion} --arch=x64 --dist-url=${electronUrl}`); - mv(`build/Release/${module}.node`, '../../../modules'); - rm('-r', 'build'); - cd('-'); - console.log(`${module} build completed.`); - } + for (const module of modules.filter((module) => statSync(module).isDirectory())) { + cd(module); + exec(`${resolve('../../../node_modules/.bin/node-gyp')} rebuild --target=${electronVersion} --arch=x64 --dist-url=${electronUrl}`); + mv(`build/Release/${module}.node`, '../../../modules'); + rm('-r', 'build'); + cd('-'); + console.log(`${module} build completed.`); + } }); diff --git a/sources/client/app/AppState.ts b/sources/client/app/AppState.ts index 01ec9563..c1d7f94d 100644 --- a/sources/client/app/AppState.ts +++ b/sources/client/app/AppState.ts @@ -5,113 +5,113 @@ import { PlayableGame, SortParameter } from '../../models/PlayableGame'; import { PotentialGame } from '../../models/PotentialGame'; import { reduxLog } from './helpers'; import { - gamesSortParameter, - gameToEdit, - launchedGame, - playableGames, - potentialGames, - potentialGameToAdd, - refreshingGames, - selectedGame + gamesSortParameter, + gameToEdit, + launchedGame, + playableGames, + potentialGames, + potentialGameToAdd, + refreshingGames, + selectedGame } from './reducers/games'; import { - gameAddModalVisible, - igdbResearchModalVisible, - potentialGamesAddModalVisible, - settingsModalVisible, - timePlayedEditionModalVisible + gameAddModalVisible, + igdbResearchModalVisible, + potentialGamesAddModalVisible, + settingsModalVisible, + timePlayedEditionModalVisible } from './reducers/modals'; import { internetConnection, modulesConfig, settings } from './reducers/settings'; export interface AppState { - settings: any; - modulesConfig: any; - internetConnection: boolean; - potentialGames: GamesCollection; - playableGames: GamesCollection; - selectedGame: PlayableGame; - launchedGame: PlayableGame; - refreshingGames: boolean; - potentialGameToAdd: PotentialGame; - gameToEdit: PlayableGame; - gamesSortParameter: SortParameter; - gameAddModalVisible: boolean; - igdbResearchModalVisible: boolean; - timePlayedEditionModalVisible: boolean; - potentialGamesAddModalVisible: boolean; - settingsModalVisible: boolean; + settings: any; + modulesConfig: any; + internetConnection: boolean; + potentialGames: GamesCollection; + playableGames: GamesCollection; + selectedGame: PlayableGame; + launchedGame: PlayableGame; + refreshingGames: boolean; + potentialGameToAdd: PotentialGame; + gameToEdit: PlayableGame; + gamesSortParameter: SortParameter; + gameAddModalVisible: boolean; + igdbResearchModalVisible: boolean; + timePlayedEditionModalVisible: boolean; + potentialGamesAddModalVisible: boolean; + settingsModalVisible: boolean; } export const vitrineStore: Store = createStore(combineReducers({ - settings, - modulesConfig, - internetConnection, - potentialGames, - playableGames, - selectedGame, - launchedGame, - refreshingGames, - potentialGameToAdd, - gameToEdit, - gamesSortParameter, - gameAddModalVisible, - igdbResearchModalVisible, - timePlayedEditionModalVisible, - potentialGamesAddModalVisible, - settingsModalVisible + settings, + modulesConfig, + internetConnection, + potentialGames, + playableGames, + selectedGame, + launchedGame, + refreshingGames, + potentialGameToAdd, + gameToEdit, + gamesSortParameter, + gameAddModalVisible, + igdbResearchModalVisible, + timePlayedEditionModalVisible, + potentialGamesAddModalVisible, + settingsModalVisible }), { - settings: null, - modulesConfig: null, - internetConnection: true, - potentialGames: new GamesCollection(), - playableGames: new GamesCollection(), - selectedGame: null, - launchedGame: null, - refreshingGames: false, - potentialGameToAdd: null, - gameToEdit: null, - gamesSortParameter: SortParameter.NAME, - gameAddModalVisible: false, - igdbResearchModalVisible: false, - timePlayedEditionModalVisible: false, - potentialGamesAddModalVisible: false, - settingsModalVisible: false + settings: null, + modulesConfig: null, + internetConnection: true, + potentialGames: new GamesCollection(), + playableGames: new GamesCollection(), + selectedGame: null, + launchedGame: null, + refreshingGames: false, + potentialGameToAdd: null, + gameToEdit: null, + gamesSortParameter: SortParameter.NAME, + gameAddModalVisible: false, + igdbResearchModalVisible: false, + timePlayedEditionModalVisible: false, + potentialGamesAddModalVisible: false, + settingsModalVisible: false }, applyMiddleware(reduxLog)); export function getSortedGamesFromStore(dispatchedData: any): PlayableGame[] { - const { playableGames, editedGame, gamesSortParameter }: any = dispatchedData; - const sortedGames: GamesCollection = new GamesCollection(); + const { playableGames, editedGame, gamesSortParameter }: any = dispatchedData; + const sortedGames: GamesCollection = new GamesCollection(); - if (playableGames && playableGames.length > 1) - sortedGames.addGames(playableGames); - else - sortedGames.addGames(vitrineStore.getState().playableGames.getGames()); + if (playableGames && playableGames.length > 1) + sortedGames.addGames(playableGames); + else + sortedGames.addGames(vitrineStore.getState().playableGames.getGames()); - if (playableGames && playableGames.length === 1) - sortedGames.addGame(playableGames[0]); - if (editedGame) - sortedGames.editGame(editedGame); + if (playableGames && playableGames.length === 1) + sortedGames.addGame(playableGames[0]); + if (editedGame) + sortedGames.editGame(editedGame); - const sortParameter = gamesSortParameter || vitrineStore.getState().gamesSortParameter; - switch (sortParameter) { - case (SortParameter.NAME): { - return sortedGames.getGames().sort((gameA: PlayableGame, gameB: PlayableGame): number => { - return (gameA.name > gameB.name) ? (1) : (-1); - }); - } - case (SortParameter.TIME_PLAYED): { - return sortedGames.getGames().sort((gameA: PlayableGame, gameB: PlayableGame): number => { - return (gameA.timePlayed < gameB.timePlayed) ? (1) : (-1); - }); - } - default: - return sortedGames.getGames().sort((gameA: PlayableGame, gameB: PlayableGame): number => { - if (!gameA.details[sortParameter]) - return 1; - if (!gameB.details[sortParameter]) - return -1; - const result: number = (sortParameter !== SortParameter.RATING && sortParameter !== SortParameter.RELEASE_DATE) ? (1) : (-1); - return (gameA.details[sortParameter] > gameB.details[sortParameter]) ? (result) : (-result); - }); - } + const sortParameter = gamesSortParameter || vitrineStore.getState().gamesSortParameter; + switch (sortParameter) { + case (SortParameter.NAME): { + return sortedGames.getGames().sort((gameA: PlayableGame, gameB: PlayableGame): number => { + return (gameA.name > gameB.name) ? (1) : (-1); + }); + } + case (SortParameter.TIME_PLAYED): { + return sortedGames.getGames().sort((gameA: PlayableGame, gameB: PlayableGame): number => { + return (gameA.timePlayed < gameB.timePlayed) ? (1) : (-1); + }); + } + default: + return sortedGames.getGames().sort((gameA: PlayableGame, gameB: PlayableGame): number => { + if (!gameA.details[sortParameter]) + return 1; + if (!gameB.details[sortParameter]) + return -1; + const result: number = (sortParameter !== SortParameter.RATING && sortParameter !== SortParameter.RELEASE_DATE) ? (1) : (-1); + return (gameA.details[sortParameter] > gameB.details[sortParameter]) ? (result) : (-result); + }); + } } diff --git a/sources/client/app/ControlsHandler.ts b/sources/client/app/ControlsHandler.ts index 4fad3a66..67a307dc 100644 --- a/sources/client/app/ControlsHandler.ts +++ b/sources/client/app/ControlsHandler.ts @@ -2,81 +2,81 @@ import { BrowserWindow, remote } from 'electron'; import { GamepadListener, ListenerEvent } from 'gamepad-listener'; interface ActionCallbacks { - [key: string]: () => void; + [key: string]: () => void; } class ControlsHandler { - private currentWindow: BrowserWindow; - private actionCallbacks: ActionCallbacks; - private gamepadListener: GamepadListener; + private currentWindow: BrowserWindow; + private actionCallbacks: ActionCallbacks; + private gamepadListener: GamepadListener; - public constructor() { - this.currentWindow = remote.getCurrentWindow(); - this.gamepadListener = new GamepadListener(); - this.actionCallbacks = {}; - window.addEventListener('keydown', this.registerKeyboardActions.bind(this)); - this.registerGamepadActions(); - this.gamepadListener.start(); - } + public constructor() { + this.currentWindow = remote.getCurrentWindow(); + this.gamepadListener = new GamepadListener(); + this.actionCallbacks = {}; + window.addEventListener('keydown', this.registerKeyboardActions.bind(this)); + this.registerGamepadActions(); + this.gamepadListener.start(); + } - public unregister() { - window.removeEventListener('keydown', this.registerKeyboardActions.bind(this)); - this.gamepadListener.stop(); - } + public unregister() { + window.removeEventListener('keydown', this.registerKeyboardActions.bind(this)); + this.gamepadListener.stop(); + } - public registerDownAction(callback: () => void) { - this.actionCallbacks.down = callback; - } + public registerDownAction(callback: () => void) { + this.actionCallbacks.down = callback; + } - public registerUpAction(callback: () => void) { - this.actionCallbacks.up = callback; - } + public registerUpAction(callback: () => void) { + this.actionCallbacks.up = callback; + } - public registerEnterAction(callback: () => void) { - this.actionCallbacks.enter = callback; - } + public registerEnterAction(callback: () => void) { + this.actionCallbacks.enter = callback; + } - private registerKeyboardActions(event: KeyboardEvent) { - switch (event.code) { - case 'ArrowUp': { - event.preventDefault(); - if (this.actionCallbacks.up) - this.actionCallbacks.up(); - break; - } - case 'ArrowDown': { - event.preventDefault(); - if (this.actionCallbacks.down) - this.actionCallbacks.down(); - break; - } - case 'Enter': { - event.preventDefault(); - if (this.actionCallbacks.enter) - this.actionCallbacks.enter(); - break; - } - } - } + private registerKeyboardActions(event: KeyboardEvent) { + switch (event.code) { + case 'ArrowUp': { + event.preventDefault(); + if (this.actionCallbacks.up) + this.actionCallbacks.up(); + break; + } + case 'ArrowDown': { + event.preventDefault(); + if (this.actionCallbacks.down) + this.actionCallbacks.down(); + break; + } + case 'Enter': { + event.preventDefault(); + if (this.actionCallbacks.enter) + this.actionCallbacks.enter(); + break; + } + } + } - private registerGamepadActions() { - this.gamepadListener.on('gamepad:axis', (event: ListenerEvent) => { - if (!this.currentWindow.isFocused()) - return; - if (event.axis === 1) { - if (event.value < -0.98 && this.actionCallbacks.up) - this.actionCallbacks.up(); - if (event.value > 0.96 && this.actionCallbacks.down) - this.actionCallbacks.down(); - } - }); - this.gamepadListener.on('gamepad:button:0', (event: ListenerEvent) => { - if (!this.currentWindow.isFocused()) - return; - if (event.button.pressed && this.actionCallbacks.enter) - this.actionCallbacks.enter(); - }); - } + private registerGamepadActions() { + this.gamepadListener.on('gamepad:axis', (event: ListenerEvent) => { + if (!this.currentWindow.isFocused()) + return; + if (event.axis === 1) { + if (event.value < -0.98 && this.actionCallbacks.up) + this.actionCallbacks.up(); + if (event.value > 0.96 && this.actionCallbacks.down) + this.actionCallbacks.down(); + } + }); + this.gamepadListener.on('gamepad:button:0', (event: ListenerEvent) => { + if (!this.currentWindow.isFocused()) + return; + if (event.button.pressed && this.actionCallbacks.enter) + this.actionCallbacks.enter(); + }); + } } export const controlsHandler: ControlsHandler = new ControlsHandler(); diff --git a/sources/client/app/Localizer.ts b/sources/client/app/Localizer.ts index 2143d497..af46ad86 100644 --- a/sources/client/app/Localizer.ts +++ b/sources/client/app/Localizer.ts @@ -1,38 +1,38 @@ class Localizer { - private readonly languages: any[]; - private selectedLanguage: string; - - public constructor(languages?: any) { - this.languages = languages || {}; - this.selectedLanguage = 'en'; - } - - public getLanguages(): any[] { - return this.languages; - } - - public getSelectedLanguage(): string { - return this.selectedLanguage; - } - - public addLanguage(key: string, dict: any) { - this.languages[key] = dict; - } - - public setLanguage(language: string) { - this.selectedLanguage = language; - } - - public f(key: string, arg?: any): string { - if (!arg) - return this.languages[this.selectedLanguage][key]; - return this.languages[this.selectedLanguage][key].replace('%1', arg); - } - - public genre(key: string): string { - const genre: string = this.languages[this.selectedLanguage].genresNames[key]; - return genre || key; - } + private readonly languages: any[]; + private selectedLanguage: string; + + public constructor(languages?: any) { + this.languages = languages || {}; + this.selectedLanguage = 'en'; + } + + public getLanguages(): any[] { + return this.languages; + } + + public getSelectedLanguage(): string { + return this.selectedLanguage; + } + + public addLanguage(key: string, dict: any) { + this.languages[key] = dict; + } + + public setLanguage(language: string) { + this.selectedLanguage = language; + } + + public f(key: string, arg?: any): string { + if (!arg) + return this.languages[this.selectedLanguage][key]; + return this.languages[this.selectedLanguage][key].replace('%1', arg); + } + + public genre(key: string): string { + const genre: string = this.languages[this.selectedLanguage].genresNames[key]; + return genre || key; + } } export const localizer: Localizer = new Localizer(); diff --git a/sources/client/app/ServerListener.ts b/sources/client/app/ServerListener.ts index bd4a2002..4bc91cbb 100644 --- a/sources/client/app/ServerListener.ts +++ b/sources/client/app/ServerListener.ts @@ -1,23 +1,23 @@ import { ipcRenderer } from 'electron'; class ServerListener { - public constructor(private emitterName: string, private receiverName: string) {} + public constructor(private emitterName: string, private receiverName: string) {} - public send(channelName, ...args) { - const sentArgs: any[] = [ - `${this.emitterName}.${channelName}`, - ...args - ]; - ipcRenderer.send.apply(ipcRenderer, sentArgs); - } + public send(channelName, ...args) { + const sentArgs: any[] = [ + `${this.emitterName}.${channelName}`, + ...args + ]; + ipcRenderer.send.apply(ipcRenderer, sentArgs); + } - public listen(channelName: string, callbackFunction: (...args: any[]) => any): this { - ipcRenderer.on(`${this.receiverName}.${channelName}`, (...args) => { - args.shift(); - callbackFunction.apply(null, args); - }); - return this; - } + public listen(channelName: string, callbackFunction: (...args: any[]) => any): this { + ipcRenderer.on(`${this.receiverName}.${channelName}`, (...args) => { + args.shift(); + callbackFunction.apply(null, args); + }); + return this; + } } export let loaderServerListener: ServerListener = new ServerListener('loader', 'loaderServer'); diff --git a/sources/client/app/actions/actionsTypes.ts b/sources/client/app/actions/actionsTypes.ts index 8a42e4f6..e68a439a 100644 --- a/sources/client/app/actions/actionsTypes.ts +++ b/sources/client/app/actions/actionsTypes.ts @@ -1,33 +1,33 @@ export interface Action { - type: ActionType; - payload: any; + type: ActionType; + payload: any; } export enum ActionType { - UPDATE_SETTINGS = 'UPDATE_SETTINGS', - UPDATE_MODULES_CONFIG = 'UPDATE_MODULES_CONFIG', - SET_INTERNET_CONNECTION = 'INTERNET_CONNECTION', + UPDATE_SETTINGS = 'UPDATE_SETTINGS', + UPDATE_MODULES_CONFIG = 'UPDATE_MODULES_CONFIG', + SET_INTERNET_CONNECTION = 'INTERNET_CONNECTION', - REFRESH_GAMES = 'REFRESH_GAMES', - ADD_POTENTIAL_GAMES = 'ADD_POTENTIAL_GAMES', - ADD_PLAYABLE_GAMES = 'ADD_PLAYABLE_GAMES', - EDIT_PLAYABLE_GAME = 'EDIT_PLAYABLE_GAME', - REMOVE_PLAYABLE_GAME = 'REMOVE_PLAYABLE_GAME', - LAUNCH_GAME = 'LAUNCH_GAME', - STOP_GAME = 'STOP_GAME', - SELECT_GAME = 'SELECT_GAME', - SET_POTENTIAL_GAME_TO_ADD = 'SET_POTENTIAL_GAME_TO_ADD', - SET_GAME_TO_EDIT = 'SET_GAME_TO_EDIT', - SORT_GAMES = 'SORT_GAMES', + REFRESH_GAMES = 'REFRESH_GAMES', + ADD_POTENTIAL_GAMES = 'ADD_POTENTIAL_GAMES', + ADD_PLAYABLE_GAMES = 'ADD_PLAYABLE_GAMES', + EDIT_PLAYABLE_GAME = 'EDIT_PLAYABLE_GAME', + REMOVE_PLAYABLE_GAME = 'REMOVE_PLAYABLE_GAME', + LAUNCH_GAME = 'LAUNCH_GAME', + STOP_GAME = 'STOP_GAME', + SELECT_GAME = 'SELECT_GAME', + SET_POTENTIAL_GAME_TO_ADD = 'SET_POTENTIAL_GAME_TO_ADD', + SET_GAME_TO_EDIT = 'SET_GAME_TO_EDIT', + SORT_GAMES = 'SORT_GAMES', - OPEN_GAME_ADD_MODAL = 'OPEN_GAME_ADD_MODAL', - CLOSE_GAME_ADD_MODAL = 'CLOSE_GAME_ADD_MODAL', - OPEN_IGDB_RESEARCH_MODAL = 'OPEN_IGDB_RESEARCH_MODAL', - CLOSE_IGDB_RESEARCH_MODAL = 'CLOSE_IGDB_RESEARCH_MODAL', - OPEN_TIME_PLAYED_EDITION_MODAL = 'OPEN_TIME_PLAYED_EDITION_MODAL', - CLOSE_TIME_PLAYED_EDITION_MODAL = 'CLOSE_TIME_PLAYED_EDITION_MODAL', - OPEN_POTENTIAL_GAMES_ADD_MODAL = 'OPEN_POTENTIAL_GAMES_ADD_MODAL', - CLOSE_POTENTIAL_GAMES_ADD_MODAL = 'CLOSE_POTENTIAL_GAMES_ADD_MODAL', - OPEN_SETTINGS_MODAL = 'OPEN_SETTINGS_MODAL', - CLOSE_SETTINGS_MODAL = 'CLOSE_SETTINGS_MODAL' + OPEN_GAME_ADD_MODAL = 'OPEN_GAME_ADD_MODAL', + CLOSE_GAME_ADD_MODAL = 'CLOSE_GAME_ADD_MODAL', + OPEN_IGDB_RESEARCH_MODAL = 'OPEN_IGDB_RESEARCH_MODAL', + CLOSE_IGDB_RESEARCH_MODAL = 'CLOSE_IGDB_RESEARCH_MODAL', + OPEN_TIME_PLAYED_EDITION_MODAL = 'OPEN_TIME_PLAYED_EDITION_MODAL', + CLOSE_TIME_PLAYED_EDITION_MODAL = 'CLOSE_TIME_PLAYED_EDITION_MODAL', + OPEN_POTENTIAL_GAMES_ADD_MODAL = 'OPEN_POTENTIAL_GAMES_ADD_MODAL', + CLOSE_POTENTIAL_GAMES_ADD_MODAL = 'CLOSE_POTENTIAL_GAMES_ADD_MODAL', + OPEN_SETTINGS_MODAL = 'OPEN_SETTINGS_MODAL', + CLOSE_SETTINGS_MODAL = 'CLOSE_SETTINGS_MODAL' } diff --git a/sources/client/app/actions/games.ts b/sources/client/app/actions/games.ts index 02d9a039..aa5a2745 100644 --- a/sources/client/app/actions/games.ts +++ b/sources/client/app/actions/games.ts @@ -4,113 +4,113 @@ import { getSortedGamesFromStore } from '../AppState'; import { Action, ActionType } from './actionsTypes'; export function refreshGames(): Action { - return { - type: ActionType.REFRESH_GAMES, - payload: { - refreshingGames: true - } - }; + return { + type: ActionType.REFRESH_GAMES, + payload: { + refreshingGames: true + } + }; } export function addPotentialGames(potentialGames: PotentialGame[]): Action { - return { - type: ActionType.ADD_POTENTIAL_GAMES, - payload: { - potentialGames, - refreshingGames: false - } - }; + return { + type: ActionType.ADD_POTENTIAL_GAMES, + payload: { + potentialGames, + refreshingGames: false + } + }; } export function addPlayableGames(unsortedGames: PlayableGame[]): Action { - const playableGames: PlayableGame[] = getSortedGamesFromStore({ - playableGames: unsortedGames - }); - return { - type: ActionType.ADD_PLAYABLE_GAMES, - payload: { - playableGames, - selectedGame: (unsortedGames.length) ? ((unsortedGames.length > 1) ? (playableGames[0]) : (unsortedGames[0])) : (null), - potentialGameToAdd: null - } - }; + const playableGames: PlayableGame[] = getSortedGamesFromStore({ + playableGames: unsortedGames + }); + return { + type: ActionType.ADD_PLAYABLE_GAMES, + payload: { + playableGames, + selectedGame: (unsortedGames.length) ? ((unsortedGames.length > 1) ? (playableGames[0]) : (unsortedGames[0])) : (null), + potentialGameToAdd: null + } + }; } export function editPlayableGame(editedGame: PlayableGame): Action { - const playableGames: PlayableGame[] = getSortedGamesFromStore({ editedGame }); - return { - type: ActionType.EDIT_PLAYABLE_GAME, - payload: { - playableGames, - editedGame, - potentialGameToAdd: null, - gameToEdit: null - } - }; + const playableGames: PlayableGame[] = getSortedGamesFromStore({ editedGame }); + return { + type: ActionType.EDIT_PLAYABLE_GAME, + payload: { + playableGames, + editedGame, + potentialGameToAdd: null, + gameToEdit: null + } + }; } export function removePlayableGame(gameUuid: string): Action { - return { - type: ActionType.REMOVE_PLAYABLE_GAME, - payload: { - gameUuid - } - }; + return { + type: ActionType.REMOVE_PLAYABLE_GAME, + payload: { + gameUuid + } + }; } export function launchGame(launchedGame: PlayableGame): Action { - return { - type: ActionType.LAUNCH_GAME, - payload: { - launchedGame - } - }; + return { + type: ActionType.LAUNCH_GAME, + payload: { + launchedGame + } + }; } export function stopGame(playedGame: PlayableGame): Action { - return { - type: ActionType.STOP_GAME, - payload: { - playedGame, - launchedGame: null - } - }; + return { + type: ActionType.STOP_GAME, + payload: { + playedGame, + launchedGame: null + } + }; } export function selectGame(selectedGame: PlayableGame): Action { - return { - type: ActionType.SELECT_GAME, - payload: { - selectedGame - } - }; + return { + type: ActionType.SELECT_GAME, + payload: { + selectedGame + } + }; } export function setPotentialGameToAdd(potentialGameToAdd: PotentialGame): Action { - return { - type: ActionType.SET_POTENTIAL_GAME_TO_ADD, - payload: { - potentialGameToAdd - } - }; + return { + type: ActionType.SET_POTENTIAL_GAME_TO_ADD, + payload: { + potentialGameToAdd + } + }; } export function setGameToEdit(gameToEdit: PlayableGame): Action { - return { - type: ActionType.SET_GAME_TO_EDIT, - payload: { - gameToEdit - } - }; + return { + type: ActionType.SET_GAME_TO_EDIT, + payload: { + gameToEdit + } + }; } export function sortGames(gamesSortParameter: SortParameter): Action { - const playableGames: PlayableGame[] = getSortedGamesFromStore({ gamesSortParameter }); - return { - type: ActionType.SORT_GAMES, - payload: { - gamesSortParameter, - playableGames - } - }; + const playableGames: PlayableGame[] = getSortedGamesFromStore({ gamesSortParameter }); + return { + type: ActionType.SORT_GAMES, + payload: { + gamesSortParameter, + playableGames + } + }; } diff --git a/sources/client/app/actions/modals.ts b/sources/client/app/actions/modals.ts index 3e829610..53aa63d4 100644 --- a/sources/client/app/actions/modals.ts +++ b/sources/client/app/actions/modals.ts @@ -1,91 +1,91 @@ import { Action, ActionType } from './actionsTypes'; export function openGameAddModal(): Action { - return { - type: ActionType.OPEN_GAME_ADD_MODAL, - payload: { - GameAddModalVisible: true - } - }; + return { + type: ActionType.OPEN_GAME_ADD_MODAL, + payload: { + GameAddModalVisible: true + } + }; } export function closeGameAddModal(): Action { - return { - type: ActionType.CLOSE_GAME_ADD_MODAL, - payload: { - GameAddModalVisible: false - } - }; + return { + type: ActionType.CLOSE_GAME_ADD_MODAL, + payload: { + GameAddModalVisible: false + } + }; } export function openIgdbResearchModal(): Action { - return { - type: ActionType.OPEN_IGDB_RESEARCH_MODAL, - payload: { - igdbResearchModalVisible: true - } - }; + return { + type: ActionType.OPEN_IGDB_RESEARCH_MODAL, + payload: { + igdbResearchModalVisible: true + } + }; } export function closeIgdbResearchModal(): Action { - return { - type: ActionType.CLOSE_IGDB_RESEARCH_MODAL, - payload: { - igdbResearchModalVisible: false - } - }; + return { + type: ActionType.CLOSE_IGDB_RESEARCH_MODAL, + payload: { + igdbResearchModalVisible: false + } + }; } export function openTimePlayedEditionModal(): Action { - return { - type: ActionType.OPEN_TIME_PLAYED_EDITION_MODAL, - payload: { - timePlayedEditionModalVisible: true - } - }; + return { + type: ActionType.OPEN_TIME_PLAYED_EDITION_MODAL, + payload: { + timePlayedEditionModalVisible: true + } + }; } export function closeTimePlayedEditionModal(): Action { - return { - type: ActionType.CLOSE_TIME_PLAYED_EDITION_MODAL, - payload: { - timePlayedEditionModalVisible: false - } - }; + return { + type: ActionType.CLOSE_TIME_PLAYED_EDITION_MODAL, + payload: { + timePlayedEditionModalVisible: false + } + }; } export function openPotentialGamesAddModal(): Action { - return { - type: ActionType.OPEN_POTENTIAL_GAMES_ADD_MODAL, - payload: { - potentialGamesAddModalVisible: true - } - }; + return { + type: ActionType.OPEN_POTENTIAL_GAMES_ADD_MODAL, + payload: { + potentialGamesAddModalVisible: true + } + }; } export function closePotentialGamesAddModal(): Action { - return { - type: ActionType.CLOSE_POTENTIAL_GAMES_ADD_MODAL, - payload: { - potentialGamesAddModalVisible: false - } - }; + return { + type: ActionType.CLOSE_POTENTIAL_GAMES_ADD_MODAL, + payload: { + potentialGamesAddModalVisible: false + } + }; } export function openSettingsModal(): Action { - return { - type: ActionType.OPEN_SETTINGS_MODAL, - payload: { - settingsModalVisible: true - } - }; + return { + type: ActionType.OPEN_SETTINGS_MODAL, + payload: { + settingsModalVisible: true + } + }; } export function closeSettingsModal(): Action { - return { - type: ActionType.CLOSE_SETTINGS_MODAL, - payload: { - settingsModalVisible: false - } - }; + return { + type: ActionType.CLOSE_SETTINGS_MODAL, + payload: { + settingsModalVisible: false + } + }; } diff --git a/sources/client/app/actions/settings.ts b/sources/client/app/actions/settings.ts index c4a2347c..18e7bc39 100644 --- a/sources/client/app/actions/settings.ts +++ b/sources/client/app/actions/settings.ts @@ -1,28 +1,28 @@ import { Action, ActionType } from './actionsTypes'; export function updateSettings(settings: any): Action { - return { - type: ActionType.UPDATE_SETTINGS, - payload: { - settings - } - }; + return { + type: ActionType.UPDATE_SETTINGS, + payload: { + settings + } + }; } export function updateModulesConfig(modulesConfig: any): Action { - return { - type: ActionType.UPDATE_MODULES_CONFIG, - payload: { - modulesConfig - } - }; + return { + type: ActionType.UPDATE_MODULES_CONFIG, + payload: { + modulesConfig + } + }; } export function setInternetConnection(internetConnection: boolean): Action { - return { - type: ActionType.SET_INTERNET_CONNECTION, - payload: { - internetConnection - } - }; + return { + type: ActionType.SET_INTERNET_CONNECTION, + payload: { + internetConnection + } + }; } diff --git a/sources/client/app/components/ActionButton.tsx b/sources/client/app/components/ActionButton.tsx index 3e91c2c7..cd47a590 100644 --- a/sources/client/app/components/ActionButton.tsx +++ b/sources/client/app/components/ActionButton.tsx @@ -8,130 +8,130 @@ import { randomHashedString } from '../../../models/env'; import { VitrineComponent } from './VitrineComponent'; interface Props { - icon: FontAwesomeIcon.IconDefinition; - spin?: boolean; - tooltip?: string; - onClick?: React.MouseEventHandler; - className?: string; + icon: FontAwesomeIcon.IconDefinition; + spin?: boolean; + tooltip?: string; + onClick?: React.MouseEventHandler; + className?: string; } interface State { - buttonClassName: string; - iconClassName: string; + buttonClassName: string; + iconClassName: string; } export class ActionButton extends VitrineComponent { - private readonly id: string; + private readonly id: string; - public constructor() { - super(); + public constructor() { + super(); - this.state = { - buttonClassName: css(styles.buttonStandard), - iconClassName: css(styles.iconStandard) - }; - this.id = `tooltip_${randomHashedString(6)}`; + this.state = { + buttonClassName: css(styles.buttonStandard), + iconClassName: css(styles.iconStandard) + }; + this.id = `tooltip_${randomHashedString(6)}`; - this.mouseEnterHandler = this.mouseEnterHandler.bind(this); - this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this); - } + this.mouseEnterHandler = this.mouseEnterHandler.bind(this); + this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this); + } - private mouseEnterHandler() { - this.setState({ - buttonClassName: css(styles.buttonHover), - iconClassName: css(styles.iconHover) - }); - } + private mouseEnterHandler() { + this.setState({ + buttonClassName: css(styles.buttonHover), + iconClassName: css(styles.iconHover) + }); + } - private mouseLeaveHandler() { - this.setState({ - buttonClassName: css(styles.buttonStandard), - iconClassName: css(styles.iconStandard) - }); - } + private mouseLeaveHandler() { + this.setState({ + buttonClassName: css(styles.buttonStandard), + iconClassName: css(styles.iconStandard) + }); + } - public render(): JSX.Element { - const icon: JSX.Element = ( - - ); - const button: JSX.Element = ( -
- {icon} -
- ); + public render(): JSX.Element { + const icon: JSX.Element = ( + + ); + const button: JSX.Element = ( +
+ {icon} +
+ ); - return ( -
- {button} - {(this.props.tooltip) ? ( - - {this.props.tooltip} - - ) : ('')} -
- ); - } + return ( +
+ {button} + {(this.props.tooltip) ? ( + + {this.props.tooltip} + + ) : ('')} +
+ ); + } } const styles: React.CSSProperties & any = StyleSheet.create({ - buttonWrapper: { - display: 'inline-block', - width: 100..percents(), - height: 100..percents() - }, - button: { - display: 'inline-block', - width: 84..percents(), - height: 88..percents(), - margin: margin(4..percents(), 8..percents()), - padding: padding(8..percents(), 14..percents()), - // padding: padding(5, 8, 4, 8), - borderRadius: 3, - cursor: 'pointer', - transition: `${100}ms ease`, - '-webkitAppRegion': 'no-drag' - }, - buttonStandard: { - backgroundColor: rgba(0, 0, 0, 0), - }, - buttonHover: { - backgroundColor: rgba(0, 0, 0, 0.3), - }, - icon: { - width: 100..percents(), - margin: margin(0, 'auto'), - fontSize: 30, - textAlign: 'center', - transition: `${100}ms ease` - }, - iconStandard: { - color: '#635F5F', - }, - iconHover: { - color: '#908578' - }, - tooltip: { - color: '#D4D4D4', - backgroundColor: rgba(0, 0, 0, 0.85), - ':after': { - borderBottomColor: rgba(0, 0, 0, 0.85) - } - } + buttonWrapper: { + display: 'inline-block', + width: 100..percents(), + height: 100..percents() + }, + button: { + display: 'inline-block', + width: 84..percents(), + height: 88..percents(), + margin: margin(4..percents(), 8..percents()), + padding: padding(8..percents(), 14..percents()), + // padding: padding(5, 8, 4, 8), + borderRadius: 3, + cursor: 'pointer', + transition: `${100}ms ease`, + '-webkitAppRegion': 'no-drag' + }, + buttonStandard: { + backgroundColor: rgba(0, 0, 0, 0), + }, + buttonHover: { + backgroundColor: rgba(0, 0, 0, 0.3), + }, + icon: { + width: 100..percents(), + margin: margin(0, 'auto'), + fontSize: 30, + textAlign: 'center', + transition: `${100}ms ease` + }, + iconStandard: { + color: '#635F5F', + }, + iconHover: { + color: '#908578' + }, + tooltip: { + color: '#D4D4D4', + backgroundColor: rgba(0, 0, 0, 0.85), + ':after': { + borderBottomColor: rgba(0, 0, 0, 0.85) + } + } }); diff --git a/sources/client/app/components/App.tsx b/sources/client/app/components/App.tsx index e8bf6363..58ad5e44 100644 --- a/sources/client/app/components/App.tsx +++ b/sources/client/app/components/App.tsx @@ -1,6 +1,6 @@ import { remote } from 'electron'; import * as fs from 'fs-extra'; -import * as glob from 'glob'; +import { promise as glob } from 'glob-promise'; import * as path from 'path'; import * as React from 'react'; @@ -12,81 +12,81 @@ import { serverListener } from '../ServerListener'; import { ErrorsWrapper } from './ErrorsWrapper'; interface Props { - settings: any; - updateSettings: (settings: any) => void; - updateModulesConfig: (modulesConfig: any) => void; - setInternetConnection: (internetConnection: boolean) => void; + settings: any; + updateSettings: (settings: any) => void; + updateModulesConfig: (modulesConfig: any) => void; + setInternetConnection: (internetConnection: boolean) => void; } interface State { - settingsReceived: boolean; + settingsReceived: boolean; } export class App extends React.Component { - public constructor(props: Props) { - super(props); + public constructor(props: Props) { + super(props); - this.state = { - settingsReceived: false - }; + this.state = { + settingsReceived: false + }; + } - this.initLanguages(); - } + private async initLanguages() { + const langFilesFolder: string = getEnvFolder('config/lang'); + const configLang: string = (this.props.settings && this.props.settings.lang) ? (this.props.settings.lang) : (''); + const systemLang: string = remote.app.getLocale(); - private initLanguages() { - const langFilesFolder: string = getEnvFolder('config/lang'); - const configLang: string = (this.props.settings && this.props.settings.lang) ? (this.props.settings.lang) : (''); - const systemLang: string = remote.app.getLocale(); + const langFilesPaths = await glob(`${langFilesFolder}/*`); + const langNames: string[] = await Promise.all(langFilesPaths.map(async (langFilePath: string) => { + const langName: string = path.basename(langFilePath).slice(0, -5); + const langFile: any = await fs.readJson(langFilePath); + localizer.addLanguage(langName, langFile); + return langName; + })); + if (configLang) + localizer.setLanguage(configLang); + else if (langNames.indexOf(systemLang) !== -1) + localizer.setLanguage(systemLang); + else + localizer.setLanguage('en'); + } - const langFilesPaths: string[] = glob.sync(`${langFilesFolder}/*`); - langFilesPaths.forEachEnd((langFilePath: string, done: () => void) => { - const langName: string = path.basename(langFilePath).slice(0, -5); - const langFile: any = fs.readJsonSync(langFilePath); - localizer.addLanguage(langName, langFile); - if (!configLang && systemLang === langName) - localizer.setLanguage(langName); - done(); - }, () => { - if (configLang) - localizer.setLanguage(configLang); - }); - } + private handleInternetConnection() { + this.props.setInternetConnection(window.navigator.onLine); - private handleInternetConnection() { - this.props.setInternetConnection(window.navigator.onLine); + if (!window.navigator.onLine) { + notify(localizer.f('noInternet'), true, true); + } + } - if (!window.navigator.onLine) { - notify(localizer.f('noInternet'), true, true); - } - } + public async componentDidMount() { + await this.initLanguages(); + serverListener.listen('init-settings', (settings: any, modulesConfig: any) => { + this.props.updateSettings(settings); + this.props.updateModulesConfig(modulesConfig); + this.setState({ + settingsReceived: true + }, () => { + serverListener.send('ready'); + }); + }); + serverListener.listen('set-internet-connection', this.handleInternetConnection.bind(this)); + window.addEventListener('online', this.handleInternetConnection.bind(this)); + window.addEventListener('offline', this.handleInternetConnection.bind(this)); - public componentDidMount() { - serverListener.listen('init-settings', (settings: any, modulesConfig: any) => { - this.props.updateSettings(settings); - this.props.updateModulesConfig(modulesConfig); - this.setState({ - settingsReceived: true - }, () => { - serverListener.send('ready'); - }); - }); - serverListener.listen('set-internet-connection', this.handleInternetConnection.bind(this)); - window.addEventListener('online', this.handleInternetConnection.bind(this)); - window.addEventListener('offline', this.handleInternetConnection.bind(this)); + serverListener.send('settings-asked'); + } - serverListener.send('settings-asked'); - } + public componentWillUnmount() { + window.removeEventListener('online', this.handleInternetConnection.bind(this)); + window.removeEventListener('offline', this.handleInternetConnection.bind(this)); + } - public componentWillUnmount() { - window.removeEventListener('online', this.handleInternetConnection.bind(this)); - window.removeEventListener('offline', this.handleInternetConnection.bind(this)); - } - - public render(): JSX.Element { - return (this.state.settingsReceived) ? ( - - - - ) : (null); - } + public render(): JSX.Element { + return (this.state.settingsReceived) ? ( + + + + ) : (null); + } } diff --git a/sources/client/app/components/BlurPicture.tsx b/sources/client/app/components/BlurPicture.tsx index 1263d8aa..d6004181 100644 --- a/sources/client/app/components/BlurPicture.tsx +++ b/sources/client/app/components/BlurPicture.tsx @@ -8,148 +8,148 @@ import { urlify } from '../helpers'; import { VitrineComponent } from './VitrineComponent'; interface Props { - width?: number; - height?: number; - fontSize: number; - background: string; - faIcon: FontAwesomeIcon.IconDefinition; - clickHandler: () => void; + width?: number; + height?: number; + fontSize: number; + background: string; + faIcon: FontAwesomeIcon.IconDefinition; + clickHandler: () => void; } interface State { - iconVisible: boolean; - pulseVisible: boolean; - divStyle: React.CSSProperties; - imageStyle: React.CSSProperties; + iconVisible: boolean; + pulseVisible: boolean; + divStyle: React.CSSProperties; + imageStyle: React.CSSProperties; } export class BlurPicture extends VitrineComponent { - private readonly pulseDuration: number; - - public constructor(props: Props) { - super(props); - - const divWidth: number = this.props.width || 3.136; - const divHeight: number = this.props.height || 4.48; - this.pulseDuration = 165; - - this.state = { - iconVisible: false, - pulseVisible: true, - divStyle: { - width: divWidth.em(), - height: divHeight.em(), - fontSize: this.props.fontSize.px(), - animationDuration: `${this.pulseDuration}ms` - }, - imageStyle: { - backgroundImage: urlify(this.props.background) - } - }; - - this.mouseEnterHandler = this.mouseEnterHandler.bind(this); - this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this); - this.clickHandler = this.clickHandler.bind(this); - } - - private mouseEnterHandler() { - const imageStyle: any = this.state.imageStyle; - imageStyle.filter = `blur(${4..px()})`; - - this.setState({ - iconVisible: true, - imageStyle: { - backgroundImage: urlify(this.props.background), - filter: `blur(${4..px()})` - } - }); - } - - private mouseLeaveHandler() { - const imageStyle: any = this.state.imageStyle; - imageStyle.filter = ''; - - this.setState({ - iconVisible: false, - imageStyle: { - backgroundImage: urlify(this.props.background), - filter: '' - } - }); - } - - private clickHandler() { - this.setState({ - pulseVisible: !this.state.pulseVisible - }); - - this.props.clickHandler(); - } - - public static getDerivedStateFromProps(nextProps: Props): Partial { - return { - imageStyle: { - backgroundImage: urlify(nextProps.background), - filter: '' - } - }; - } - - public render(): JSX.Element { - return ( - -
-
- - - - {this.checkErrors()} -
- - ); - } + private readonly pulseDuration: number; + + public constructor(props: Props) { + super(props); + + const divWidth: number = this.props.width || 3.136; + const divHeight: number = this.props.height || 4.48; + this.pulseDuration = 165; + + this.state = { + iconVisible: false, + pulseVisible: true, + divStyle: { + width: divWidth.em(), + height: divHeight.em(), + fontSize: this.props.fontSize.px(), + animationDuration: `${this.pulseDuration}ms` + }, + imageStyle: { + backgroundImage: urlify(this.props.background) + } + }; + + this.mouseEnterHandler = this.mouseEnterHandler.bind(this); + this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this); + this.clickHandler = this.clickHandler.bind(this); + } + + private mouseEnterHandler() { + const imageStyle: any = this.state.imageStyle; + imageStyle.filter = `blur(${4..px()})`; + + this.setState({ + iconVisible: true, + imageStyle: { + backgroundImage: urlify(this.props.background), + filter: `blur(${4..px()})` + } + }); + } + + private mouseLeaveHandler() { + const imageStyle: any = this.state.imageStyle; + imageStyle.filter = ''; + + this.setState({ + iconVisible: false, + imageStyle: { + backgroundImage: urlify(this.props.background), + filter: '' + } + }); + } + + private clickHandler() { + this.setState({ + pulseVisible: !this.state.pulseVisible + }); + + this.props.clickHandler(); + } + + public static getDerivedStateFromProps(nextProps: Props): Partial { + return { + imageStyle: { + backgroundImage: urlify(nextProps.background), + filter: '' + } + }; + } + + public render(): JSX.Element { + return ( + +
+
+ + + + {this.checkErrors()} +
+ + ); + } } const styles: React.CSSProperties & any = StyleSheet.create({ - container: { - width: 100..percents(), - height: 100..percents(), - overflow: 'hidden', - position: 'relative', - color: '#F1F1F1', - borderRadius: 4 - }, - picture: { - width: 100..percents(), - height: 100..percents(), - cursor: 'pointer', - backgroundRepeat: 'no-repeat', - backgroundSize: `${100..percents()} ${100..percents()}`, - transition: `${75}ms filter linear`, - boxShadow: `${0} ${0} ${0} ${2..px()} ${rgba(255, 255, 255, 0.12)} inset` - }, - icon: { - position: 'absolute', - color: rgba(255, 255, 255, 0.6), - top: 40..percents(), - left: 40..percents(), - cursor: 'pointer' - } + container: { + width: 100..percents(), + height: 100..percents(), + overflow: 'hidden', + position: 'relative', + color: '#F1F1F1', + borderRadius: 4 + }, + picture: { + width: 100..percents(), + height: 100..percents(), + cursor: 'pointer', + backgroundRepeat: 'no-repeat', + backgroundSize: `${100..percents()} ${100..percents()}`, + transition: `${75}ms filter linear`, + boxShadow: `${0} ${0} ${0} ${2..px()} ${rgba(255, 255, 255, 0.12)} inset` + }, + icon: { + position: 'absolute', + color: rgba(255, 255, 255, 0.6), + top: 40..percents(), + left: 40..percents(), + cursor: 'pointer' + } }); diff --git a/sources/client/app/components/CirclePercentage.tsx b/sources/client/app/components/CirclePercentage.tsx index 2e8f2f05..444fb4a5 100644 --- a/sources/client/app/components/CirclePercentage.tsx +++ b/sources/client/app/components/CirclePercentage.tsx @@ -7,83 +7,83 @@ import { VitrineComponent } from './VitrineComponent'; import * as lessVars from 'less-vars-loader?camelCase&resolveVariables!../../resources/less/theme/globals/site.variables'; interface Props { - percentage: number; - color: string; + percentage: number; + color: string; } export class CirclePercentage extends VitrineComponent { - public constructor(props: Props) { - super(props); - } + public constructor(props: Props) { + super(props); + } - public render(): JSX.Element { - return ( - - - - - {this.props.percentage} - - - / 100 - - {this.checkErrors()} - - ); - } + public render(): JSX.Element { + return ( + + + + + {this.props.percentage} + + + / 100 + + {this.checkErrors()} + + ); + } } const progressKeyframe: React.CSSProperties & any = { - '0%': { - strokeDasharray: '0 100' - } + '0%': { + strokeDasharray: '0 100' + } }; const styles: React.CSSProperties & any = StyleSheet.create({ - svg: { - display: 'block', - height: 110, - width: 110, - margin: margin(10, 'auto') - }, - circle: { - fill: 'none', - strokeWidth: 2.8, - strokeLinecap: 'round', - animationName: progressKeyframe, - animation: '500ms ease-out forwards' - }, - backgroundCircle: { - stroke: rgba(0, 0, 0, 0.3), - fill: 'none', - strokeWidth: 2.8, - strokeLinecap: 'round', - animationName: progressKeyframe, - animation: '500ms ease-out forwards' - }, - text: { - fill: lessVars.textColor, - fontSize: 13 - }, - backgroundText: { - fill: rgba(213, 213, 213, 0.4), - fontSize: 5 - } + svg: { + display: 'block', + height: 110, + width: 110, + margin: margin(10, 'auto') + }, + circle: { + fill: 'none', + strokeWidth: 2.8, + strokeLinecap: 'round', + animationName: progressKeyframe, + animation: '500ms ease-out forwards' + }, + backgroundCircle: { + stroke: rgba(0, 0, 0, 0.3), + fill: 'none', + strokeWidth: 2.8, + strokeLinecap: 'round', + animationName: progressKeyframe, + animation: '500ms ease-out forwards' + }, + text: { + fill: lessVars.textColor, + fontSize: 13 + }, + backgroundText: { + fill: rgba(213, 213, 213, 0.4), + fontSize: 5 + } }); diff --git a/sources/client/app/components/ContextMenu.tsx b/sources/client/app/components/ContextMenu.tsx index edc0ba6c..d6056050 100644 --- a/sources/client/app/components/ContextMenu.tsx +++ b/sources/client/app/components/ContextMenu.tsx @@ -11,171 +11,171 @@ import { serverListener } from '../ServerListener'; import { VitrineComponent } from './VitrineComponent'; interface Props { - playableGames: GamesCollection; - launchGame: (launchedGame: PlayableGame) => void; - setGameToEdit: (gameToEdit: PlayableGame) => void; - openGameAddModal: () => void; - openTimePlayedEditionModal: () => void; + playableGames: GamesCollection; + launchGame: (launchedGame: PlayableGame) => void; + setGameToEdit: (gameToEdit: PlayableGame) => void; + openGameAddModal: () => void; + openTimePlayedEditionModal: () => void; } interface State { - toDeleteGame: PlayableGame; - confirmVisible: boolean; - transitionVisible: boolean; + toDeleteGame: PlayableGame; + confirmVisible: boolean; + transitionVisible: boolean; } export class ContextMenu extends VitrineComponent { - public constructor(props: Props) { - super(props); - - this.state = { - toDeleteGame: null, - confirmVisible: false, - transitionVisible: false - }; - - this.removeGame = this.removeGame.bind(this); - this.resetModalData = this.resetModalData.bind(this); - this.launchClick = this.launchClick.bind(this); - this.editClick = this.editClick.bind(this); - this.editTimeClick = this.editTimeClick.bind(this); - this.deleteClick = this.deleteClick.bind(this); - this.animateModal = this.animateModal.bind(this); - } - - private launchClick(event: any, data: any, target: HTMLElement) { - this.contextAction(target, 'launch'); - } - - private editClick(event: any, data: any, target: HTMLElement) { - this.contextAction(target, 'edit'); - } - - private editTimeClick(event: any, data: any, target: HTMLElement) { - this.contextAction(target, 'editTime'); - } - - private deleteClick(event: any, data: any, target: HTMLElement) { - this.contextAction(target, 'delete'); - } - - private removeGame() { - serverListener.send('remove-game', this.state.toDeleteGame.uuid); - this.resetModalData(); - } - - private resetModalData() { - this.setState({ - confirmVisible: false - }, () => { - setTimeout(() => { - this.setState({ - toDeleteGame: null, - transitionVisible: false - }); - }, this.modalsTransitionDuration); - }); - } - - private contextAction(target: HTMLElement, action: string) { - const gameUuid: string = target.children[0].id.replace('sidebar-game:', ''); - const game: PlayableGame = this.props.playableGames.getGame(gameUuid); - - switch (action) { - case 'launch': { - this.props.launchGame(game); - break; - } - case 'edit': { - this.props.setGameToEdit(game); - this.props.openGameAddModal(); - break; - } - case 'editTime': { - this.props.setGameToEdit(game); - this.props.openTimePlayedEditionModal(); - break; - } - case 'delete': { - this.setState({ - confirmVisible: true, - toDeleteGame: game - }); - break; - } - } - } - - private animateModal(startingAnimation: boolean) { - if (startingAnimation === this.state.confirmVisible) - this.setState({ - transitionVisible: this.state.confirmVisible - }); - } - - public render(): JSX.Element { - return ( -
- - - {localizer.f('play')} - - - {localizer.f('edit')} - - - {localizer.f('editTimePlayed')} - - - - {localizer.f('delete')} - - - - - {localizer.f('removeGame')} - - - - - - - -
- ); - } + public constructor(props: Props) { + super(props); + + this.state = { + toDeleteGame: null, + confirmVisible: false, + transitionVisible: false + }; + + this.removeGame = this.removeGame.bind(this); + this.resetModalData = this.resetModalData.bind(this); + this.launchClick = this.launchClick.bind(this); + this.editClick = this.editClick.bind(this); + this.editTimeClick = this.editTimeClick.bind(this); + this.deleteClick = this.deleteClick.bind(this); + this.animateModal = this.animateModal.bind(this); + } + + private launchClick(event: any, data: any, target: HTMLElement) { + this.contextAction(target, 'launch'); + } + + private editClick(event: any, data: any, target: HTMLElement) { + this.contextAction(target, 'edit'); + } + + private editTimeClick(event: any, data: any, target: HTMLElement) { + this.contextAction(target, 'editTime'); + } + + private deleteClick(event: any, data: any, target: HTMLElement) { + this.contextAction(target, 'delete'); + } + + private removeGame() { + serverListener.send('remove-game', this.state.toDeleteGame.uuid); + this.resetModalData(); + } + + private resetModalData() { + this.setState({ + confirmVisible: false + }, () => { + setTimeout(() => { + this.setState({ + toDeleteGame: null, + transitionVisible: false + }); + }, this.modalsTransitionDuration); + }); + } + + private contextAction(target: HTMLElement, action: string) { + const gameUuid: string = target.children[0].id.replace('sidebar-game:', ''); + const game: PlayableGame = this.props.playableGames.getGame(gameUuid); + + switch (action) { + case 'launch': { + this.props.launchGame(game); + break; + } + case 'edit': { + this.props.setGameToEdit(game); + this.props.openGameAddModal(); + break; + } + case 'editTime': { + this.props.setGameToEdit(game); + this.props.openTimePlayedEditionModal(); + break; + } + case 'delete': { + this.setState({ + confirmVisible: true, + toDeleteGame: game + }); + break; + } + } + } + + private animateModal(startingAnimation: boolean) { + if (startingAnimation === this.state.confirmVisible) + this.setState({ + transitionVisible: this.state.confirmVisible + }); + } + + public render(): JSX.Element { + return ( +
+ + + {localizer.f('play')} + + + {localizer.f('edit')} + + + {localizer.f('editTimePlayed')} + + + + {localizer.f('delete')} + + + + + {localizer.f('removeGame')} + + + + + + + +
+ ); + } } const styles: React.CSSProperties & any = StyleSheet.create({ - modal: { - margin: margin(22..rem(), 'auto') - }, - modalContent: { - fontSize: 16 - } + modal: { + margin: margin(22..rem(), 'auto') + }, + modalContent: { + fontSize: 16 + } }); diff --git a/sources/client/app/components/DatePicker.tsx b/sources/client/app/components/DatePicker.tsx index 429f74bb..a67954ba 100644 --- a/sources/client/app/components/DatePicker.tsx +++ b/sources/client/app/components/DatePicker.tsx @@ -9,63 +9,63 @@ import { VitrineComponent } from './VitrineComponent'; import { faCalendarAlt, faTrash } from '@fortawesome/fontawesome-free-solid'; interface Props { - value: string | Date | moment.Moment; - dateFormat: string; - onChange: (event: any) => void; - inputProps?: any; + value: string | Date | moment.Moment; + dateFormat: string; + onChange: (event: any) => void; + inputProps?: any; } export class DatePicker extends VitrineComponent { - public constructor() { - super(); + public constructor() { + super(); - this.renderInput = this.renderInput.bind(this); - } + this.renderInput = this.renderInput.bind(this); + } - private removeDateButtonClick(props: any, openCalendar: () => void) { - if (props.value) - props.onChange({ - target: { value: '' } - }); - else - openCalendar(); - } + private removeDateButtonClick(props: any, openCalendar: () => void) { + if (props.value) + props.onChange({ + target: { value: '' } + }); + else + openCalendar(); + } - private renderInput(props: any, openCalendar: () => void): JSX.Element { - const removeDateButton: JSX.Element = ( - - ); + private renderInput(props: any, openCalendar: () => void): JSX.Element { + const removeDateButton: JSX.Element = ( + + ); - return ( -
- -
- ); - } + return ( +
+ +
+ ); + } - public render(): JSX.Element { - return ( - - ); - } + public render(): JSX.Element { + return ( + + ); + } } diff --git a/sources/client/app/components/EmulatorSettingsRow.tsx b/sources/client/app/components/EmulatorSettingsRow.tsx index 3356d2ec..3c56f87e 100644 --- a/sources/client/app/components/EmulatorSettingsRow.tsx +++ b/sources/client/app/components/EmulatorSettingsRow.tsx @@ -10,138 +10,138 @@ import { VitrineComponent } from './VitrineComponent'; import { faFolderOpen } from '@fortawesome/fontawesome-free-solid'; interface Props { - platforms: any[]; - emulatorData: any; - emulator: any; - onChange: (emulatorConfig: any) => void; + platforms: any[]; + emulatorData: any; + emulator: any; + onChange: (emulatorConfig: any) => void; } interface State { - active: boolean; - path: string; - command?: string; + active: boolean; + path: string; + command?: string; } export class EmulatorSettingsRow extends VitrineComponent { - public constructor(props: Props) { - super(props); + public constructor(props: Props) { + super(props); - this.state = { - active: !!this.props.emulator, - path: (this.props.emulator) ? (this.props.emulator.path) : (this.props.emulatorData.path), - command: (this.props.emulator) ? (this.props.emulator.command || this.props.emulatorData.command) : (this.props.emulatorData.command) - }; + this.state = { + active: !!this.props.emulator, + path: (this.props.emulator) ? (this.props.emulator.path) : (this.props.emulatorData.path), + command: (this.props.emulator) ? (this.props.emulator.command || this.props.emulatorData.command) : (this.props.emulatorData.command) + }; - this.activeCheckBox = this.activeCheckBox.bind(this); - this.programButton = this.programButton.bind(this); - this.commandLineChange = this.commandLineChange.bind(this); - } + this.activeCheckBox = this.activeCheckBox.bind(this); + this.programButton = this.programButton.bind(this); + this.commandLineChange = this.commandLineChange.bind(this); + } - private activeCheckBox(event: any, data: any) { - this.setState({ - active: data.checked - }, () => { - this.props.onChange(this.getEmulatorFromState()); - }); - } + private activeCheckBox(event: any, data: any) { + this.setState({ + active: data.checked + }, () => { + this.props.onChange(this.getEmulatorFromState()); + }); + } - private programButton() { - const path: string = openExecutableDialog(); - if (!path) - return; - this.setState({ - path - }, () => { - this.props.onChange(this.getEmulatorFromState()); - }); - } + private programButton() { + const path: string = openExecutableDialog(); + if (!path) + return; + this.setState({ + path + }, () => { + this.props.onChange(this.getEmulatorFromState()); + }); + } - private commandLineChange(event: any) { - this.setState({ - command: event.target.value - }, () => { - this.props.onChange(this.getEmulatorFromState()); - }); - } + private commandLineChange(event: any) { + this.setState({ + command: event.target.value + }, () => { + this.props.onChange(this.getEmulatorFromState()); + }); + } - private getEmulatorFromState(): any { - const emulator: any = { id: this.props.emulatorData.id }; - if (this.state.active) - emulator.path = this.state.path || null; - else - return emulator; - if (this.state.command !== this.props.emulatorData.command) - emulator.command = this.state.command; - return emulator; - } + private getEmulatorFromState(): any { + const emulator: any = { id: this.props.emulatorData.id }; + if (this.state.active) + emulator.path = this.state.path || null; + else + return emulator; + if (this.state.command !== this.props.emulatorData.command) + emulator.command = this.state.command; + return emulator; + } - public render(): JSX.Element { - const platforms: string[] = this.props.emulatorData.platforms.map((platformId: any) => - this.props.platforms.filter((platform: any) => platform.id === platformId)[0].name - ); - return ( - - - {this.props.emulatorData.name} - - - {platforms.join(', ')} - - - - - - - - - } - labelPosition={'right'} - size={'small'} - className={(!this.state.active) ? (css(styles.inactiveInput)) : ('')} - readOnly={true} - value={this.state.path} - onClick={(this.state.active) ? (this.programButton) : (null)} - /> - - -
- -
-
-
- ); - } + public render(): JSX.Element { + const platforms: string[] = this.props.emulatorData.platforms.map((platformId: any) => + this.props.platforms.filter((platform: any) => platform.id === platformId)[0].name + ); + return ( + + + {this.props.emulatorData.name} + + + {platforms.join(', ')} + + + + + + + + + } + labelPosition={'right'} + size={'small'} + className={(!this.state.active) ? (css(styles.inactiveInput)) : ('')} + readOnly={true} + value={this.state.path} + onClick={(this.state.active) ? (this.programButton) : (null)} + /> + + +
+ +
+
+
+ ); + } } const styles: React.CSSProperties & any = StyleSheet.create({ - emulatorTr: { - transition: `${150}ms ease` - }, - inactiveTr: { - color: rgba(119, 119, 119, 0.75), - backgroundColor: rgba(56, 56, 56, 0.45) - }, - inactiveInput: { - color: rgba(202, 202, 202, 0.35), - backgroundColor: '#2d2b28' - }, - commandInput: { - fontFamily: 'Inconsolata' - } + emulatorTr: { + transition: `${150}ms ease` + }, + inactiveTr: { + color: rgba(119, 119, 119, 0.75), + backgroundColor: rgba(56, 56, 56, 0.45) + }, + inactiveInput: { + color: rgba(202, 202, 202, 0.35), + backgroundColor: '#2d2b28' + }, + commandInput: { + fontFamily: 'Inconsolata' + } }); diff --git a/sources/client/app/components/ErrorsWrapper.tsx b/sources/client/app/components/ErrorsWrapper.tsx index fa91b39d..43bede07 100644 --- a/sources/client/app/components/ErrorsWrapper.tsx +++ b/sources/client/app/components/ErrorsWrapper.tsx @@ -7,96 +7,96 @@ import { localizer } from '../Localizer'; import { serverListener } from '../ServerListener'; interface State { - visible: boolean; - error?: Error; + visible: boolean; + error?: Error; } export class ErrorsWrapper extends React.Component<{}, State> { - constructor(props: any) { - super(props); + constructor(props: any) { + super(props); - this.state = { - visible: false - }; - } + this.state = { + visible: false + }; + } - private quitApplication() { - serverListener.send('quit-application', false); - } + private quitApplication() { + serverListener.send('quit-application', false); + } - private relaunchApplication() { - serverListener.send('quit-application', true); - } + private relaunchApplication() { + serverListener.send('quit-application', true); + } - public componentDidCatch(error: Error) { - this.setState({ - error, - visible: true - }); - } + public componentDidCatch(error: Error) { + this.setState({ + error, + visible: true + }); + } - public render(): JSX.Element { - if (this.state.error) - return ( - - - {localizer.f('crash')} - - - :( -
-							{this.state.error.stack}
-						
-
- - - - -
- ); - else - return this.props.children as JSX.Element; - } + public render(): JSX.Element { + if (this.state.error) + return ( + + + {localizer.f('crash')} + + + :( +
+              {this.state.error.stack}
+            
+
+ + + + +
+ ); + else + return this.props.children as JSX.Element; + } } const styles: React.CSSProperties & any = StyleSheet.create({ - modal: { - margin: margin(13..rem(), 'auto'), - cursor: 'default', - userSelect: 'none' - }, - errorIcon: { - fontSize: 205, - position: 'absolute', - color: rgba(255, 50, 50, 0.12), - top: -50, - right: 50 - }, - errorStack: { - fontFamily: 'Inconsolata', - fontSize: 16, - padding: padding(10), - overflowX: 'auto', - color: '#BDB3B3', - backgroundColor: '#272020', - border: `solid ${1..px()} #463131`, - cursor: 'text', - userSelect: 'text', - '::selection': { - backgroundColor: rgba(101, 55, 55, 0.26) - } - } + modal: { + margin: margin(13..rem(), 'auto'), + cursor: 'default', + userSelect: 'none' + }, + errorIcon: { + fontSize: 205, + position: 'absolute', + color: rgba(255, 50, 50, 0.12), + top: -50, + right: 50 + }, + errorStack: { + fontFamily: 'Inconsolata', + fontSize: 16, + padding: padding(10), + overflowX: 'auto', + color: '#BDB3B3', + backgroundColor: '#272020', + border: `solid ${1..px()} #463131`, + cursor: 'text', + userSelect: 'text', + '::selection': { + backgroundColor: rgba(101, 55, 55, 0.26) + } + } }); diff --git a/sources/client/app/components/GameAddModal.tsx b/sources/client/app/components/GameAddModal.tsx index ee58a80b..d788f1e3 100644 --- a/sources/client/app/components/GameAddModal.tsx +++ b/sources/client/app/components/GameAddModal.tsx @@ -20,555 +20,555 @@ import { faFolderOpen } from '@fortawesome/fontawesome-free-solid'; import { PlayableGame } from '../../../models/PlayableGame'; interface Props { - internetConnection: boolean; - selectedGame: PlayableGame; - potentialGameToAdd: PotentialGame; - gameToEdit: PlayableGame; - visible: boolean; - igdbResearchModalVisible: boolean; - addPlayableGames: (playableGames: PlayableGame[]) => void; - editPlayableGame: (playableGame: PlayableGame) => void; - setPotentialGameToAdd: (potentialGame: PotentialGame) => void; - setGameToEdit: (playableGame: PlayableGame) => void; - selectGame: (selectedGame: PlayableGame) => void; - closeGameAddModal: () => void; - closeIgdbResearchModal: () => void; - closeTimePlayedEditionModal: () => void; + internetConnection: boolean; + selectedGame: PlayableGame; + potentialGameToAdd: PotentialGame; + gameToEdit: PlayableGame; + visible: boolean; + igdbResearchModalVisible: boolean; + addPlayableGames: (playableGames: PlayableGame[]) => void; + editPlayableGame: (playableGame: PlayableGame) => void; + setPotentialGameToAdd: (potentialGame: PotentialGame) => void; + setGameToEdit: (playableGame: PlayableGame) => void; + selectGame: (selectedGame: PlayableGame) => void; + closeGameAddModal: () => void; + closeIgdbResearchModal: () => void; + closeTimePlayedEditionModal: () => void; } interface State { - gameData: Partial<{ - name: string; - series: string; - date: string; - developer: string; - publisher: string; - genres: string; - rating: number; - summary: string; - executable: string; - arguments: string; - cover: string; - backgroundScreen: string; - potentialBackgrounds: string[]; - source: GameSource; - }>; - editing: boolean; - modalVisible: boolean; - igdbFilled: boolean; - submitButtonLoading: boolean; - igdbButtonLoading: boolean; - transitionVisible: boolean; + gameData: Partial<{ + name: string; + series: string; + date: string; + developer: string; + publisher: string; + genres: string; + rating: number; + summary: string; + executable: string; + arguments: string; + cover: string; + backgroundScreen: string; + potentialBackgrounds: string[]; + source: GameSource; + }>; + editing: boolean; + modalVisible: boolean; + igdbFilled: boolean; + submitButtonLoading: boolean; + igdbButtonLoading: boolean; + transitionVisible: boolean; } export class GameAddModal extends VitrineComponent { - private readonly emptyState: State; + private readonly emptyState: State; - public constructor(props: Props) { - super(props); + public constructor(props: Props) { + super(props); - this.emptyState = { - gameData: { - name: '', - series: '', - date: '', - developer: '', - publisher: '', - genres: '', - rating: undefined, - summary: '', - executable: '', - arguments: '', - cover: '', - backgroundScreen: '', - potentialBackgrounds: [], - source: GameSource.LOCAL - }, - editing: false, - modalVisible: this.props.visible, - igdbFilled: false, - submitButtonLoading: false, - igdbButtonLoading: false, - transitionVisible: true - }; - this.state = { ...this.emptyState }; + this.emptyState = { + gameData: { + name: '', + series: '', + date: '', + developer: '', + publisher: '', + genres: '', + rating: undefined, + summary: '', + executable: '', + arguments: '', + cover: '', + backgroundScreen: '', + potentialBackgrounds: [], + source: GameSource.LOCAL + }, + editing: false, + modalVisible: this.props.visible, + igdbFilled: false, + submitButtonLoading: false, + igdbButtonLoading: false, + transitionVisible: true + }; + this.state = { ...this.emptyState }; - this.closeModal = this.closeModal.bind(this); - this.changeBackgroundHandler = this.changeBackgroundHandler.bind(this); - this.gameCoverClickHandler = this.gameCoverClickHandler.bind(this); - this.inputChangeHandler = this.inputChangeHandler.bind(this); - this.dateChangeHandler = this.dateChangeHandler.bind(this); - this.ratingChangeHandler = this.ratingChangeHandler.bind(this); - this.executableButton = this.executableButton.bind(this); - this.searchIgdbButton = this.searchIgdbButton.bind(this); - this.submitButton = this.submitButton.bind(this); - this.animateModal = this.animateModal.bind(this); - } + this.closeModal = this.closeModal.bind(this); + this.changeBackgroundHandler = this.changeBackgroundHandler.bind(this); + this.gameCoverClickHandler = this.gameCoverClickHandler.bind(this); + this.inputChangeHandler = this.inputChangeHandler.bind(this); + this.dateChangeHandler = this.dateChangeHandler.bind(this); + this.ratingChangeHandler = this.ratingChangeHandler.bind(this); + this.executableButton = this.executableButton.bind(this); + this.searchIgdbButton = this.searchIgdbButton.bind(this); + this.submitButton = this.submitButton.bind(this); + this.animateModal = this.animateModal.bind(this); + } - private fillIgdbGame(gameInfos: any) { - this.setState({ - gameData: { - ...this.state.gameData, - name: gameInfos.name, - series: gameInfos.series || '', - date: (gameInfos.releaseDate) ? (moment(gameInfos.releaseDate).format('DD/MM/YYYY')) : (''), - developer: gameInfos.developer || '', - publisher: gameInfos.publisher || '', - genres: (gameInfos.genres.length) ? (gameInfos.genres.join(', ')) : (''), - rating: gameInfos.rating || '', - summary: gameInfos.summary || '', - cover: gameInfos.cover, - potentialBackgrounds: gameInfos.screenshots || [], - backgroundScreen: (gameInfos.screenshots.length) ? (gameInfos.screenshots[0]) : ('') - }, - igdbFilled: true, - igdbButtonLoading: false - }); - this.props.closeIgdbResearchModal(); - } + private fillIgdbGame(gameInfos: any) { + this.setState({ + gameData: { + ...this.state.gameData, + name: gameInfos.name, + series: gameInfos.series || '', + date: (gameInfos.releaseDate) ? (moment(gameInfos.releaseDate).format('DD/MM/YYYY')) : (''), + developer: gameInfos.developer || '', + publisher: gameInfos.publisher || '', + genres: (gameInfos.genres.length) ? (gameInfos.genres.join(', ')) : (''), + rating: gameInfos.rating || '', + summary: gameInfos.summary || '', + cover: gameInfos.cover, + potentialBackgrounds: gameInfos.screenshots || [], + backgroundScreen: (gameInfos.screenshots.length) ? (gameInfos.screenshots[0]) : ('') + }, + igdbFilled: true, + igdbButtonLoading: false + }); + this.props.closeIgdbResearchModal(); + } - private addPlayableGame(game: PlayableGame) { - this.props.addPlayableGames([game]); - this.closeModal(); - notify(`${game.name} ${localizer.f('addingGameToast')}.`, true); - this.setState({ - submitButtonLoading: false - }); - } + private addPlayableGame(game: PlayableGame) { + this.props.addPlayableGames([game]); + this.closeModal(); + notify(`${game.name} ${localizer.f('addingGameToast')}.`, true); + this.setState({ + submitButtonLoading: false + }); + } - private editPlayableGame(game: PlayableGame) { - this.props.editPlayableGame(game); - if (game.uuid === this.props.selectedGame.uuid) - this.props.selectGame(game); - if (this.props.igdbResearchModalVisible) - this.props.closeTimePlayedEditionModal(); - if (this.props.visible) - this.closeModal(); - notify(`${game.name} ${localizer.f('editingGameToast')}.`, true); - this.setState({ - submitButtonLoading: false - }); - } + private editPlayableGame(game: PlayableGame) { + this.props.editPlayableGame(game); + if (game.uuid === this.props.selectedGame.uuid) + this.props.selectGame(game); + if (this.props.igdbResearchModalVisible) + this.props.closeTimePlayedEditionModal(); + if (this.props.visible) + this.closeModal(); + notify(`${game.name} ${localizer.f('editingGameToast')}.`, true); + this.setState({ + submitButtonLoading: false + }); + } - private closeModal() { - this.props.closeGameAddModal(); - setTimeout( () => { - this.props.setPotentialGameToAdd(null); - this.props.setGameToEdit(null); - this.setState({ - ...this.emptyState, - transitionVisible: false - }); - }, this.modalsTransitionDuration); - } + private closeModal() { + this.props.closeGameAddModal(); + setTimeout( () => { + this.props.setPotentialGameToAdd(null); + this.props.setGameToEdit(null); + this.setState({ + ...this.emptyState, + transitionVisible: false + }); + }, this.modalsTransitionDuration); + } - private gameCoverClickHandler() { - const cover: string = openImageDialog(); - if (cover) - this.setState({ - gameData: { - ...this.state.gameData, - cover - } - }); - } + private gameCoverClickHandler() { + const cover: string = openImageDialog(); + if (cover) + this.setState({ + gameData: { + ...this.state.gameData, + cover + } + }); + } - private inputChangeHandler(event: any) { - const name: string | any = event.target.name; - const value: string = event.target.value; + private inputChangeHandler(event: any) { + const name: string | any = event.target.name; + const value: string = event.target.value; - this.setState({ - gameData: { - ...this.state.gameData, - [name]: value - } - }); - } + this.setState({ + gameData: { + ...this.state.gameData, + [name]: value + } + }); + } - private dateChangeHandler(date: moment.Moment | string) { - this.setState({ - gameData: { - ...this.state.gameData, - date: (typeof date === 'string') ? (date) : (date.format('DD/MM/YYYY')) - } - }); - } + private dateChangeHandler(date: moment.Moment | string) { + this.setState({ + gameData: { + ...this.state.gameData, + date: (typeof date === 'string') ? (date) : (date.format('DD/MM/YYYY')) + } + }); + } - private ratingChangeHandler(rating: number | any) { - this.setState({ - gameData: { - ...this.state.gameData, - rating - } - }); - } + private ratingChangeHandler(rating: number | any) { + this.setState({ + gameData: { + ...this.state.gameData, + rating + } + }); + } - private executableButton() { - const executable: string = openExecutableDialog(); - if (!executable) - return; - this.setState({ - gameData: { - ...this.state.gameData, - executable - } - }); - } + private executableButton() { + const executable: string = openExecutableDialog(); + if (!executable) + return; + this.setState({ + gameData: { + ...this.state.gameData, + executable + } + }); + } - private changeBackgroundHandler(backgroundScreen: string) { - this.setState({ - gameData: { - ...this.state.gameData, - backgroundScreen - } - }); - } + private changeBackgroundHandler(backgroundScreen: string) { + this.setState({ + gameData: { + ...this.state.gameData, + backgroundScreen + } + }); + } - private searchIgdbButton() { - this.setState({ - igdbButtonLoading: true - }); - serverListener.send('search-igdb-games', this.state.gameData.name); - } + private searchIgdbButton() { + this.setState({ + igdbButtonLoading: true + }); + serverListener.send('search-igdb-games', this.state.gameData.name); + } - private submitButton() { - const gameInfos: any = { ...this.state.gameData }; - delete gameInfos.potentialBackgrounds; - if (gameInfos.cover && !gameInfos.cover.startsWith('http') && !gameInfos.cover.startsWith('file://')) - gameInfos.cover = `file://${gameInfos.cover}`; - if (gameInfos.backgroundScreen && !gameInfos.backgroundScreen.startsWith('http') && !gameInfos.backgroundScreen.startsWith('file://')) - gameInfos.backgroundScreen = `file://${gameInfos.backgroundScreen}`; + private submitButton() { + const gameInfos: any = { ...this.state.gameData }; + delete gameInfos.potentialBackgrounds; + if (gameInfos.cover && !gameInfos.cover.startsWith('http') && !gameInfos.cover.startsWith('file://')) + gameInfos.cover = `file://${gameInfos.cover}`; + if (gameInfos.backgroundScreen && !gameInfos.backgroundScreen.startsWith('http') && !gameInfos.backgroundScreen.startsWith('file://')) + gameInfos.backgroundScreen = `file://${gameInfos.backgroundScreen}`; - this.setState({ - submitButtonLoading: true - }); - if (this.state.editing) - serverListener.send('edit-game', this.props.gameToEdit.uuid, gameInfos); - else - serverListener.send('add-game', gameInfos); - } + this.setState({ + submitButtonLoading: true + }); + if (this.state.editing) + serverListener.send('edit-game', this.props.gameToEdit.uuid, gameInfos); + else + serverListener.send('add-game', gameInfos); + } - private animateModal(startingAnimation: boolean) { - if (startingAnimation === this.props.visible) - this.setState({ - transitionVisible: this.props.visible - }); - } + private animateModal(startingAnimation: boolean) { + if (startingAnimation === this.props.visible) + this.setState({ + transitionVisible: this.props.visible + }); + } - public componentDidMount() { - serverListener.listen('send-igdb-game', this.fillIgdbGame.bind(this)) - .listen('add-playable-game', this.addPlayableGame.bind(this)) - .listen('edit-playable-game', this.editPlayableGame.bind(this)); - } + public componentDidMount() { + serverListener.listen('send-igdb-game', this.fillIgdbGame.bind(this)) + .listen('add-playable-game', this.addPlayableGame.bind(this)) + .listen('edit-playable-game', this.editPlayableGame.bind(this)); + } - public static getDerivedStateFromProps(nextProps: Props, prevState: State): Partial { - let gameToHandle: PotentialGame; - let editing: boolean; + public static getDerivedStateFromProps(nextProps: Props, prevState: State): Partial { + let gameToHandle: PotentialGame; + let editing: boolean; - if (nextProps.gameToEdit) { - gameToHandle = nextProps.gameToEdit; - editing = true; - } - else if (nextProps.potentialGameToAdd) { - gameToHandle = nextProps.potentialGameToAdd; - editing = false; - } - else - return null; + if (nextProps.gameToEdit) { + gameToHandle = nextProps.gameToEdit; + editing = true; + } + else if (nextProps.potentialGameToAdd) { + gameToHandle = nextProps.potentialGameToAdd; + editing = false; + } + else + return null; - const [ executable, args ]: string[] = (gameToHandle.commandLine.length > 1) ? (gameToHandle.commandLine) : ([gameToHandle.commandLine[0], '']); - return (!prevState.igdbFilled) ? ({ - gameData: { - name: gameToHandle.name, - cover: gameToHandle.details.cover, - source: gameToHandle.source, - executable, - arguments: args, - series: gameToHandle.details.series || '', - date: (gameToHandle.details.releaseDate) ? (moment(gameToHandle.details.releaseDate).format('DD/MM/YYYY')) : (''), - developer: gameToHandle.details.developer || '', - publisher: gameToHandle.details.publisher || '', - genres: (gameToHandle.details.genres) ? (gameToHandle.details.genres.join(', ')) : (''), - rating: gameToHandle.details.rating || '', - summary: gameToHandle.details.summary || '', - potentialBackgrounds: (gameToHandle.details.backgroundScreen) ? ([gameToHandle.details.backgroundScreen]) : ([]), - backgroundScreen: gameToHandle.details.backgroundScreen || '', - }, - editing - }) : ({ - igdbFilled: false - }); - } + const [ executable, args ]: string[] = (gameToHandle.commandLine.length > 1) ? (gameToHandle.commandLine) : ([gameToHandle.commandLine[0], '']); + return (!prevState.igdbFilled) ? ({ + gameData: { + name: gameToHandle.name, + cover: gameToHandle.details.cover, + source: gameToHandle.source, + executable, + arguments: args, + series: gameToHandle.details.series || '', + date: (gameToHandle.details.releaseDate) ? (moment(gameToHandle.details.releaseDate).format('DD/MM/YYYY')) : (''), + developer: gameToHandle.details.developer || '', + publisher: gameToHandle.details.publisher || '', + genres: (gameToHandle.details.genres) ? (gameToHandle.details.genres.join(', ')) : (''), + rating: gameToHandle.details.rating || '', + summary: gameToHandle.details.summary || '', + potentialBackgrounds: (gameToHandle.details.backgroundScreen) ? ([gameToHandle.details.backgroundScreen]) : ([]), + backgroundScreen: gameToHandle.details.backgroundScreen || '', + }, + editing + }) : ({ + igdbFilled: false + }); + } - public render(): JSX.Element { - return ( - - - {(this.state.editing) ? (localizer.f('editGameLabel')) : (localizer.f('addGameLabel'))} - - - - -
- -
-
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -