Skip to content

Commit

Permalink
Merge branch 'hotfix/9.0.3' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
colin969 committed Aug 28, 2020
2 parents 37ba806 + 1224bd5 commit 2af869e
Show file tree
Hide file tree
Showing 29 changed files with 512 additions and 453 deletions.
1 change: 1 addition & 0 deletions .github/workflows/latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- master
- 'release/**'
- 'hotfix/**'

jobs:
release:
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
# Release 9.0.3

## New

- Starting a `tag:` search in the search bar will list tag suggestions that you can click on to fill in.

## Changed

- Tag Suggestions dropdowns can use Tab to navigate the list and Enter to select a tag suggestion. Focus is returned to the input element afterwards.

## Fixed

- Adding a game to a playlist now puts it at the end of the playlist (instead of at the beginning).
- It is no longer possible to add a game to a playlist it is already in.
- `content` folder is now created when loading curation meta files.
- Elevate is now packed on Release, was missing prior
- Log Watcher now outputs logs in realtime on Windows
- `Export Meta` now exports YAML instead of TXT

# Release 9.0.2

## New
Expand Down
5 changes: 5 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const copyFiles = [
to: './extern/7zip-bin',
filter: ['${os}/**/*']
},
{
from: './extern/elevate',
to: './extern/elevate',
filter: ['**']
},
'./lang',
'./licenses',
'./.installed',
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flashpoint-launcher",
"version": "9.0.2",
"version": "9.0.3",
"description": "A desktop application used to browse, manage and play games from BlueMaxima's Flashpoint",
"main": "build/main/index.js",
"config": {
Expand Down Expand Up @@ -32,7 +32,6 @@
"license": "MIT",
"dependencies": {
"axios": "0.19.2",
"chokidar": "3.4.0",
"connected-react-router": "6.8.0",
"electron-updater": "4.3.1",
"fast-xml-parser": "3.16.0",
Expand Down
25 changes: 25 additions & 0 deletions src/back/game/GameManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,31 @@ export namespace GameManager {
}
}

/** Adds a new Playlist Game (to the end of the playlist). */
export async function addPlaylistGame(playlistId: string, gameId: string): Promise<void> {
const repository = getManager().getRepository(PlaylistGame);

const duplicate = await repository.createQueryBuilder()
.where('playlistId = :playlistId', { playlistId })
.andWhere('gameId = :gameId', { gameId })
.getOne();

if (duplicate) { return; }

const highestOrder = await repository.createQueryBuilder('pg')
.where('pg.playlistId = :playlistId', { playlistId })
.orderBy('pg.order', 'DESC')
.select('pg.order')
.getOne();

await repository.save<PlaylistGame>({
gameId: gameId,
playlistId: playlistId,
order: highestOrder ? highestOrder.order + 1 : 0,
notes: '',
});
}

/** Updates a Playlist Game */
export async function updatePlaylistGame(playlistGame: PlaylistGame): Promise<PlaylistGame> {
const playlistGameRepository = getManager().getRepository(PlaylistGame);
Expand Down
11 changes: 5 additions & 6 deletions src/back/importGame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ export async function importCuration(opts: ImportCurationOpts): Promise<void> {
await (async () => {
// Copy each paired content folder one at a time (allows for cancellation)
for (const pair of contentToMove) {
await copyFolder(pair[0], pair[1], moveFiles, opts.openDialog, log);
await fs.copy(pair[0], pair[1], { recursive: true, preserveTimestamps: true });
// await copyFolder(pair[0], pair[1], moveFiles, opts.openDialog, log);
}
})()
.then(async () => {
Expand All @@ -133,7 +134,7 @@ export async function importCuration(opts: ImportCurationOpts): Promise<void> {
const dateStr = date.getFullYear().toString() + '-' +
(date.getUTCMonth() + 1).toString().padStart(2, '0') + '-' +
date.getUTCDate().toString().padStart(2, '0');
const backupPath = path.join(fpPath, 'Curations', '_Imported', `${dateStr}__${curation.key}`);
const backupPath = path.join(fpPath, 'Curations', 'Imported', `${dateStr}__${curation.key}`);
await copyFolder(getCurationFolder(curation, fpPath), backupPath, true, opts.openDialog, log);
}
if (log) {
Expand Down Expand Up @@ -260,13 +261,11 @@ async function importGameImage(image: CurationIndexImage, gameId: string, folder
* @param curationKey Key of the (game) curation to link
*/
async function linkContentFolder(curationKey: string, fpPath: string, isDev: boolean, exePath: string, symlinkCurationContent: boolean) {
const curationPath = path.join(fpPath, 'Curations', curationKey);
const curationPath = path.join(fpPath, 'Curations', 'Working', curationKey);
const htdocsContentPath = path.join(fpPath, htdocsPath, 'content');
// Clear out old folder if exists
console.log('Removing old Server/htdocs/content ...');
await fs.access(htdocsContentPath, fs.constants.F_OK)
.then(() => fs.remove(htdocsContentPath))
.catch((error) => { /* No file is okay, ignore error */ });
await fs.remove(htdocsContentPath);
const contentPath = path.join(curationPath, 'content');
console.log('Linking new Server/htdocs/content ...');
if (fs.existsSync(contentPath)) {
Expand Down
3 changes: 2 additions & 1 deletion src/back/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ async function onProcessMessage(message: any, sendHandle: any): Promise<void> {
for (let i = 0; i < state.serviceInfo.watch.length; i++) {
const filePath = state.serviceInfo.watch[i];
try {
const tail = new Tail(filePath, { follow: true });
// Windows requires fs.watchFile to properly update
const tail = new Tail(filePath, { follow: true, useWatchFile: true });
tail.on('line', (data) => {
log(state, newLogEntry('Log Watcher', data));
});
Expand Down
26 changes: 17 additions & 9 deletions src/back/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import { Playlist } from '@database/entity/Playlist';
import { Tag } from '@database/entity/Tag';
import { TagAlias } from '@database/entity/TagAlias';
import { TagCategory } from '@database/entity/TagCategory';
import { AddLogData, BackIn, BackInit, BackOut, BrowseChangeData, BrowseViewIndexData, BrowseViewIndexResponse, BrowseViewKeysetData, BrowseViewKeysetResponse, BrowseViewPageData, BrowseViewPageResponseData, DeleteGameData, DeleteImageData, DeletePlaylistData, DeletePlaylistGameData, DeletePlaylistGameResponse, DeletePlaylistResponse, DuplicateGameData, DuplicatePlaylistData, ExportGameData, ExportMetaEditData, ExportPlaylistData, GameMetadataSyncResponse, GetAllGamesResponseData, GetExecData, GetGameData, GetGameResponseData, GetGamesTotalResponseData, GetMainInitDataResponse, GetPlaylistData, GetPlaylistGameData, GetPlaylistGameResponse, GetPlaylistResponse, GetPlaylistsResponse, GetRendererInitDataResponse, GetSuggestionsResponseData, ImageChangeData, ImportCurationData, ImportCurationResponseData, ImportMetaEditResponseData, ImportPlaylistData, InitEventData, LanguageChangeData, LaunchAddAppData, LaunchCurationAddAppData, LaunchCurationData, LaunchGameData, LocaleUpdateData, MergeTagData, PlaylistsChangeData, RandomGamesData, RandomGamesResponseData, SaveGameData, SaveImageData, SaveLegacyPlatformData as SaveLegacyPlatformData, SavePlaylistData, SavePlaylistGameData, SavePlaylistGameResponse, SavePlaylistResponse, ServiceActionData, SetLocaleData, TagByIdData, TagByIdResponse, TagCategoryByIdData, TagCategoryByIdResponse, TagCategoryDeleteData, TagCategoryDeleteResponse, TagCategorySaveData, TagCategorySaveResponse, TagDeleteData, TagDeleteResponse, TagFindData, TagFindResponse, TagGetData, TagGetOrCreateData, TagGetResponse, TagPrimaryFixData, TagPrimaryFixResponse, TagSaveData, TagSaveResponse, TagSuggestionsData, TagSuggestionsResponse, UpdateConfigData, UploadLogResponse } from '@shared/back/types';
import { AddLogData, AddPlaylistGameData, BackIn, BackInit, BackOut, BrowseChangeData, BrowseViewIndexData, BrowseViewIndexResponse, BrowseViewKeysetData, BrowseViewKeysetResponse, BrowseViewPageData, BrowseViewPageResponseData, DeleteGameData, DeleteImageData, DeletePlaylistData, DeletePlaylistGameData, DeletePlaylistGameResponse, DeletePlaylistResponse, DuplicateGameData, DuplicatePlaylistData, ExportGameData, ExportMetaEditData, ExportPlaylistData, GameMetadataSyncResponse, GetAllGamesResponseData, GetExecData, GetGameData, GetGameResponseData, GetGamesTotalResponseData, GetMainInitDataResponse, GetPlaylistData, GetPlaylistGameData, GetPlaylistGameResponse, GetPlaylistResponse, GetPlaylistsResponse, GetRendererInitDataResponse, GetSuggestionsResponseData, ImageChangeData, ImportCurationData, ImportCurationResponseData, ImportMetaEditResponseData, ImportPlaylistData, InitEventData, LanguageChangeData, LaunchAddAppData, LaunchCurationAddAppData, LaunchCurationData, LaunchGameData, LocaleUpdateData, MergeTagData, PlaylistsChangeData, RandomGamesData, RandomGamesResponseData, SaveGameData, SaveImageData, SaveLegacyPlatformData as SaveLegacyPlatformData, SavePlaylistData, SavePlaylistGameData, SavePlaylistGameResponse, SavePlaylistResponse, ServiceActionData, SetLocaleData, TagByIdData, TagByIdResponse, TagCategoryByIdData, TagCategoryByIdResponse, TagCategoryDeleteData, TagCategoryDeleteResponse, TagCategorySaveData, TagCategorySaveResponse, TagDeleteData, TagDeleteResponse, TagFindData, TagFindResponse, TagGetData, TagGetOrCreateData, TagGetResponse, TagPrimaryFixData, TagPrimaryFixResponse, TagSaveData, TagSaveResponse, TagSuggestionsData, TagSuggestionsResponse, UpdateConfigData, UploadLogResponse } from '@shared/back/types';
import { overwriteConfigData } from '@shared/config/util';
import { LOGOS, SCREENSHOTS } from '@shared/constants';
import { stringifyCurationFormat } from '@shared/curate/format/stringifier';
import { convertGameToCurationMetaFile } from '@shared/curate/metaToMeta';
import { getContentFolderByKey } from '@shared/curate/util';
import { FilterGameOpts } from '@shared/game/GameFilter';
Expand All @@ -23,6 +22,7 @@ import { ensureDir } from 'fs-extra';
import * as path from 'path';
import * as url from 'url';
import * as util from 'util';
import * as YAML from 'yaml';
import { ConfigFile } from './ConfigFile';
import { CONFIG_FILENAME, PREFERENCES_FILENAME } from './constants';
import { GameManager } from './game/GameManager';
Expand Down Expand Up @@ -437,8 +437,8 @@ export function registerRequestCallbacks(state: BackState): void {
// Save to file
try {
await writeFile(
reqData.metaOnly ? reqData.location : path.join(reqData.location, 'meta.txt'),
stringifyCurationFormat(convertGameToCurationMetaFile(game, await TagManager.findTagCategories())));
reqData.metaOnly ? reqData.location : path.join(reqData.location, 'meta.yaml'),
YAML.stringify(convertGameToCurationMetaFile(game, await TagManager.findTagCategories())));
} catch (e) { console.error(e); }

// Copy images
Expand Down Expand Up @@ -901,6 +901,14 @@ export function registerRequestCallbacks(state: BackState): void {
});
});

state.socketServer.register<AddPlaylistGameData>(BackIn.ADD_PLAYLIST_GAME, async (event, req) => {
await GameManager.addPlaylistGame(req.data.playlistId, req.data.gameId);
respond<SavePlaylistGameResponse>(event.target, {
id: req.id,
type: BackOut.GENERIC_RESPONSE,
});
});

state.socketServer.register<SavePlaylistGameData>(BackIn.SAVE_PLAYLIST_GAME, async (event, req) => {
const playlistGame = await GameManager.updatePlaylistGame(req.data);
respond<SavePlaylistGameResponse>(event.target, {
Expand Down Expand Up @@ -1074,10 +1082,10 @@ export function registerRequestCallbacks(state: BackState): void {
openDialog: state.socketServer.openDialog(event.target),
openExternal: state.socketServer.openExternal(event.target),
});
} catch (e) {
} catch (err) {
log(state, {
source: 'Launcher',
content: e + '',
content: `Error launching curation\n${err}`,
});
}

Expand All @@ -1103,10 +1111,10 @@ export function registerRequestCallbacks(state: BackState): void {
openDialog: state.socketServer.openDialog(event.target),
openExternal: state.socketServer.openExternal(event.target),
});
} catch (e) {
} catch (err) {
log(state, {
source: 'Launcher',
content: e + '',
content: `Error launching curation addapp\n${err}`,
});
}

Expand Down Expand Up @@ -1267,7 +1275,7 @@ export function registerRequestCallbacks(state: BackState): void {
* properties in object A and B. All properties that are not equal will be added to the returned object.
* Missing properties, or those with the value undefined, in B will be ignored.
* If all property values are equal undefined is returned.
*
*
* __Note:__ Arrays work differently in order to preserve the types and indices.
* If the length of the arrays are not equal, or if not all items in the array are strictly equal (to the items of the other array),
* then the whole array will be added to the return object.
Expand Down
Loading

0 comments on commit 2af869e

Please sign in to comment.