- Added changelog for 1.0.2
- Changed version number - Fixed global shortcuts - macOS: App quits on close - Fixed attribute adjustment in attributes tab
This commit is contained in:
+25
-1
@@ -1,3 +1,27 @@
|
||||
# 1.0.2
|
||||
|
||||
- Fixed issue with rendering list items of advantages/disadvantages/special abilities.
|
||||
- Fixed shortcuts being global.
|
||||
- Reloading a hero with `Stigma (Albino)` won't change selected eye color anymore.
|
||||
|
||||
## macOS
|
||||
|
||||
- App now quits automatically on close.
|
||||
|
||||
## English Specific
|
||||
|
||||
- Fixed list of professions.
|
||||
|
||||
## German Specific
|
||||
|
||||
- Fixed typo in failed check description of skill "Driving".
|
||||
- Fixed attribute adjustment in attributes tab.
|
||||
- Fixed levels of required instances of `Principles` and `Obligations` of `Blessed One of Kor`.
|
||||
|
||||
# 1.0.1
|
||||
|
||||
- Fixed special abilities tab.
|
||||
|
||||
# 1.0.0
|
||||
|
||||
### New Features / Breaking Changes
|
||||
@@ -39,7 +63,7 @@
|
||||
- The AP cost for profession variants are now considered when calculating AP spent.
|
||||
- Activating spells is now disabled the limits of EL are reached.
|
||||
- Fixed showing separators when sorting spells or liturgical chants by group.
|
||||
- Fxied text fields in animal section of the character sheet breaking layout or showing up twice.
|
||||
- Fixed text fields in animal section of the character sheet breaking layout or showing up twice.
|
||||
- Fixed AP used for dis/advantages shown in window used for adding them. Remaining parts of the old AP system have been removed.
|
||||
- Fixed saving heroes (previously saved heroes are not currupted).
|
||||
- Fixed filters for list of races and list of professions.
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "optolyth",
|
||||
"productName": "Optolyth",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"description": "A generator for heroes for the P&P-RPG 'The Dark Eye'.",
|
||||
"author": {
|
||||
"name": "Lukas Obermann",
|
||||
@@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"@std/esm": "^0.9.2",
|
||||
"classnames": "^2.2.5",
|
||||
"electron-localshortcut": "^3.1.0",
|
||||
"electron-log": "^2.2.12",
|
||||
"electron-updater": "^2.17.3",
|
||||
"electron-window-state": "^4.1.1",
|
||||
|
||||
+12
-9
@@ -23,14 +23,17 @@ import { addErrorAlert } from './actions/AlertActions';
|
||||
import { requestClose, requestInitialData, setUpdateDownloadProgress, updateAvailable, updateNotAvailable } from './actions/IOActions';
|
||||
import { showAbout } from './actions/LocationActions';
|
||||
import { AppContainer } from './containers/App';
|
||||
import { app, AppState } from './reducers/app';
|
||||
import { app } from './reducers/app';
|
||||
import { getLocaleMessages } from './selectors/stateSelectors';
|
||||
import { _translate } from './utils/I18n';
|
||||
import { isDialogOpen } from './utils/SubwindowsUtils';
|
||||
import localShortcut = require('electron-localshortcut');
|
||||
|
||||
const store = createStore<AppState>(app, applyMiddleware(ReduxThunk));
|
||||
const store = createStore(app, applyMiddleware(ReduxThunk));
|
||||
|
||||
store.dispatch(requestInitialData()).then(() => {
|
||||
const currentWindow = remote.getCurrentWindow();
|
||||
|
||||
if (remote.process.platform === 'darwin') {
|
||||
const { dispatch, getState } = store;
|
||||
const locale = getLocaleMessages(getState())!;
|
||||
@@ -91,27 +94,27 @@ store.dispatch(requestInitialData()).then(() => {
|
||||
remote.Menu.setApplicationMenu(menu);
|
||||
});
|
||||
|
||||
remote.globalShortcut.register('Cmd+Q', () => {
|
||||
localShortcut.register(currentWindow, 'Cmd+Q', () => {
|
||||
store.dispatch(quitAccelerator());
|
||||
});
|
||||
}
|
||||
|
||||
remote.globalShortcut.register('CmdOrCtrl+Z', () => {
|
||||
localShortcut.register(currentWindow, 'CmdOrCtrl+Z', () => {
|
||||
store.dispatch(undoAccelerator());
|
||||
});
|
||||
remote.globalShortcut.register('CmdOrCtrl+Y', () => {
|
||||
localShortcut.register(currentWindow, 'CmdOrCtrl+Y', () => {
|
||||
store.dispatch(redoAccelerator());
|
||||
});
|
||||
remote.globalShortcut.register('CmdOrCtrl+Shift+Z', () => {
|
||||
localShortcut.register(currentWindow, 'CmdOrCtrl+Shift+Z', () => {
|
||||
store.dispatch(redoAccelerator());
|
||||
});
|
||||
remote.globalShortcut.register('CmdOrCtrl+S', () => {
|
||||
localShortcut.register(currentWindow, 'CmdOrCtrl+S', () => {
|
||||
store.dispatch(saveHeroAccelerator());
|
||||
});
|
||||
remote.globalShortcut.register('CmdOrCtrl+W', () => {
|
||||
localShortcut.register(currentWindow, 'CmdOrCtrl+W', () => {
|
||||
store.dispatch(backAccelerator());
|
||||
});
|
||||
remote.globalShortcut.register('CmdOrCtrl+O', () => {
|
||||
localShortcut.register(currentWindow, 'CmdOrCtrl+O', () => {
|
||||
store.dispatch(openSettingsAccelerator());
|
||||
});
|
||||
ipcRenderer.send('loading-done');
|
||||
|
||||
+1
-9
@@ -135,19 +135,11 @@ async function main() {
|
||||
createWindow();
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
else {
|
||||
globalShortcut.register('Cmd+Q', () => {
|
||||
app.quit();
|
||||
});
|
||||
}
|
||||
app.quit();
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
if (mainWindow === null) {
|
||||
globalShortcut.unregister('Cmd+Q');
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ import { herolist, HerolistState } from './herolist';
|
||||
import { locale, LocaleState } from './locale';
|
||||
import { ui, UIState } from './ui';
|
||||
import { wiki, WikiState } from './wikiReducer';
|
||||
import { Action } from 'redux';
|
||||
|
||||
export interface AppState {
|
||||
currentHero: CurrentHeroState;
|
||||
@@ -23,4 +24,4 @@ const appSlices = combineReducers<AppState>({
|
||||
wiki
|
||||
});
|
||||
|
||||
export const app = reduceReducers(appSlices, appPost);
|
||||
export const app = reduceReducers<AppState, Action>(appSlices, appPost);
|
||||
|
||||
@@ -13,7 +13,7 @@ type Action = ReceiveInitialDataAction | RedoAction | UndoAction;
|
||||
export function appPost(
|
||||
state: AppState,
|
||||
action: Action,
|
||||
previousState: AppState,
|
||||
previousState: AppState | undefined,
|
||||
): AppState {
|
||||
switch (action.type) {
|
||||
case ActionTypes.RECEIVE_INITIAL_DATA: {
|
||||
@@ -71,7 +71,7 @@ export function appPost(
|
||||
},
|
||||
};
|
||||
}
|
||||
else if ((areAllRuleBooksEnabled(previousState) && !areAllRuleBooksEnabled(state) && !getEnabledRuleBooks(state).has('US25208') || getEnabledRuleBooks(previousState).has('US25208') && !getEnabledRuleBooks(state).has('US25208')) && getCurrentTab(state) === 'zoneArmor') {
|
||||
else if (previousState && (areAllRuleBooksEnabled(previousState) && !areAllRuleBooksEnabled(state) && !getEnabledRuleBooks(state).has('US25208') || getEnabledRuleBooks(previousState).has('US25208') && !getEnabledRuleBooks(state).has('US25208')) && getCurrentTab(state) === 'zoneArmor') {
|
||||
return {
|
||||
...state,
|
||||
ui: {
|
||||
@@ -87,7 +87,7 @@ export function appPost(
|
||||
}
|
||||
|
||||
case ActionTypes.REDO: {
|
||||
if (getPhase(previousState) === 2 && getPhase(state) === 3 && ['advantages', 'disadvantages'].includes(getCurrentTab(state))) {
|
||||
if (previousState && getPhase(previousState) === 2 && getPhase(state) === 3 && ['advantages', 'disadvantages'].includes(getCurrentTab(state))) {
|
||||
return {
|
||||
...state,
|
||||
ui: {
|
||||
|
||||
@@ -144,14 +144,14 @@ export function dependentInstances(state = initialState, action: Action) {
|
||||
const currentAttribute = state.attributes.get(current)!;
|
||||
const nextAttribute = state.attributes.get(next)!;
|
||||
|
||||
const setItem = (attribute: Data.AttributeInstance) => {
|
||||
const setItem = (attribute: Data.AttributeInstance, remove?: boolean) => {
|
||||
return (state: DependentInstancesState) => {
|
||||
return ListUtils.setStateItem(
|
||||
state,
|
||||
attribute.id,
|
||||
{
|
||||
...attribute,
|
||||
mod: attribute.mod - value
|
||||
mod: attribute.mod + (remove === true ? -value : value)
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -159,7 +159,7 @@ export function dependentInstances(state = initialState, action: Action) {
|
||||
|
||||
return ListUtils.mergeReducedOptionalState(
|
||||
state,
|
||||
setItem(currentAttribute),
|
||||
setItem(currentAttribute, true),
|
||||
setItem(nextAttribute),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -203,23 +203,59 @@ export const getAdjustmentValue = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
export const getCurrentAdjustmentAttribute = createSelector(
|
||||
getAdjustmentValue,
|
||||
getAttributes,
|
||||
getForView,
|
||||
(adjustmentValue, attributes, attributesCalculated) => {
|
||||
const currentAttribute = Array.from(attributes.values()).find(e => {
|
||||
return e.mod === adjustmentValue;
|
||||
});
|
||||
|
||||
return currentAttribute &&
|
||||
attributesCalculated.find(e => {
|
||||
return e.id === currentAttribute.id;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export const getCurrentAdjustmentId = createSelector(
|
||||
getCurrentAdjustmentAttribute,
|
||||
attribute => attribute && attribute.id
|
||||
);
|
||||
|
||||
export const getAvailableAdjustmentIds = createSelector(
|
||||
getCurrentRace,
|
||||
getAdjustmentValue,
|
||||
getAttributes,
|
||||
getForView,
|
||||
(race, adjustmentValue, attributes, attributesCalculated) => {
|
||||
getCurrentAdjustmentAttribute,
|
||||
(race, adjustmentValue, attributes, attributesCalculated, currentAttribute) => {
|
||||
const arr = race && race.attributeAdjustmentsSelection[1];
|
||||
|
||||
if (arr) {
|
||||
if (
|
||||
currentAttribute &&
|
||||
typeof currentAttribute.max === 'number' &&
|
||||
typeof adjustmentValue === 'number' &&
|
||||
currentAttribute.value > currentAttribute.max - adjustmentValue
|
||||
) {
|
||||
return [currentAttribute.id];
|
||||
}
|
||||
|
||||
return arr.filter(id => {
|
||||
const attribute = attributes.get(id);
|
||||
const attributeCalculated = attributesCalculated.find(e => e.id === id);
|
||||
|
||||
if (attribute && attributeCalculated) {
|
||||
if (attribute.mod === adjustmentValue) {
|
||||
return !attributeCalculated.max || attributeCalculated.max - adjustmentValue >= attribute.value;
|
||||
if (
|
||||
attributeCalculated.max === undefined ||
|
||||
currentAttribute && currentAttribute.id === id
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
else if (typeof adjustmentValue === 'number') {
|
||||
return !attributeCalculated.max || attributeCalculated.max + adjustmentValue >= attribute.value;
|
||||
return attributeCalculated.max + adjustmentValue >= attribute.value;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -228,16 +264,3 @@ export const getAvailableAdjustmentIds = createSelector(
|
||||
return [];
|
||||
}
|
||||
);
|
||||
|
||||
export const getCurrentAdjustmentId = createSelector(
|
||||
getAvailableAdjustmentIds,
|
||||
getAdjustmentValue,
|
||||
getAttributes,
|
||||
(availableAdjustmentIds, adjustmentValue, attributes) => {
|
||||
const currentAttribute = [...attributes.values()].find(e => availableAdjustmentIds.includes(e.id) && e.mod === adjustmentValue);
|
||||
if (currentAttribute) {
|
||||
return currentAttribute.id;
|
||||
}
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
Vendored
+34
@@ -155,3 +155,37 @@ declare module 'remark-breaks' {
|
||||
|
||||
export = ph;
|
||||
}
|
||||
|
||||
declare module 'electron-localshortcut' {
|
||||
import { Accelerator, BrowserWindow } from 'electron';
|
||||
|
||||
namespace LocalShortcut {
|
||||
|
||||
// Docs: http://electron.atom.io/docs/api/global-shortcut
|
||||
|
||||
/**
|
||||
* When the accelerator is already taken by other applications, this call will
|
||||
* still return false. This behavior is intended by operating systems, since they
|
||||
* don't want applications to fight for global shortcuts.
|
||||
*/
|
||||
export function isRegistered(window: BrowserWindow, accelerator: Accelerator): boolean;
|
||||
/**
|
||||
* Registers a global shortcut of accelerator. The callback is called when the
|
||||
* registered shortcut is pressed by the user. When the accelerator is already
|
||||
* taken by other applications, this call will silently fail. This behavior is
|
||||
* intended by operating systems, since they don't want applications to fight for
|
||||
* global shortcuts.
|
||||
*/
|
||||
export function register(window: BrowserWindow, accelerator: Accelerator, callback: Function): void;
|
||||
/**
|
||||
* Unregisters the global shortcut of accelerator.
|
||||
*/
|
||||
export function unregister(window: BrowserWindow, accelerator: Accelerator): void;
|
||||
/**
|
||||
* Unregisters all of the global shortcuts.
|
||||
*/
|
||||
export function unregisterAll(window: BrowserWindow): void;
|
||||
}
|
||||
|
||||
export = LocalShortcut;
|
||||
}
|
||||
|
||||
+14
-3
@@ -115,16 +115,27 @@ export function mergeReducedOptionalState<I extends Instance>(
|
||||
): DependentInstancesState;
|
||||
export function mergeReducedOptionalState<I extends Instance>(
|
||||
oldState: DependentInstancesState,
|
||||
instance?: I,
|
||||
instance?: I | BothInstancesStateReducer<I>,
|
||||
...reducers: BothInstancesStateReducer<I>[]
|
||||
): DependentInstancesState {
|
||||
return reducers.reduce(
|
||||
const allReducers = [...reducers];
|
||||
|
||||
let secondArg: I | undefined;
|
||||
|
||||
if (typeof instance === 'function') {
|
||||
allReducers.unshift(instance);
|
||||
}
|
||||
else {
|
||||
secondArg = instance;
|
||||
}
|
||||
|
||||
return allReducers.reduce(
|
||||
(oldState, reducer) => {
|
||||
const oldStateCopy = {
|
||||
...oldState
|
||||
};
|
||||
|
||||
const newState = reducer(oldStateCopy, instance);
|
||||
const newState = reducer(oldStateCopy, secondArg);
|
||||
|
||||
const keys = Object.keys(newState) as (keyof DependentInstancesState)[];
|
||||
|
||||
|
||||
@@ -699,6 +699,7 @@ export function convertHero(hero: Hero) {
|
||||
}
|
||||
entry.clientVersion = '0.51.4';
|
||||
}
|
||||
|
||||
if (satisfies(entry.clientVersion, '< 1.0.0')) {
|
||||
if (entry.activatable.hasOwnProperty('DISADV_45') && entry.activatable.DISADV_45.some(e => e.sid === 1)) {
|
||||
entry.pers.haircolor = 24;
|
||||
@@ -706,5 +707,34 @@ export function convertHero(hero: Hero) {
|
||||
}
|
||||
entry.clientVersion = '1.0.0';
|
||||
}
|
||||
|
||||
if (satisfies(entry.clientVersion, '< 1.0.2')) {
|
||||
let adjValue = 0;
|
||||
|
||||
if (entry.r === 'R_1' || entry.r === 'R_3') {
|
||||
adjValue = 1;
|
||||
}
|
||||
else if (entry.r === 'R_2') {
|
||||
adjValue = -2;
|
||||
}
|
||||
else if (entry.r === 'R_4') {
|
||||
adjValue = -2;
|
||||
}
|
||||
|
||||
let index = entry.attr.values.findIndex(e => e[2] === adjValue);
|
||||
|
||||
if (index === -1) {
|
||||
index = entry.attr.values.findIndex(e => e[2] !== 0);
|
||||
}
|
||||
|
||||
entry.attr.values = entry.attr.values.map((e, i) => {
|
||||
const inter = [...e] as [string, number, number];
|
||||
inter[2] = i === index ? adjValue : 0;
|
||||
return inter;
|
||||
});
|
||||
|
||||
entry.clientVersion = '1.0.2';
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export function AttributesAdjustment(props: AttributesAdjustmentProps) {
|
||||
}))}
|
||||
value={currentAttributeId}
|
||||
onChange={setAdjustmentId}
|
||||
disabled={currentAttributeId === undefined}
|
||||
disabled={currentAttributeId === undefined || availableAttributeIds.length === 1}
|
||||
/>}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user