Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7ef05d683 | ||
|
|
3706a4f78e | ||
|
|
f4cf03966c | ||
|
|
630ec88c7e | ||
|
|
8484265c2a | ||
|
|
dbdb75a888 | ||
|
|
0dc6316b5b | ||
|
|
c7d1735e4b | ||
|
|
aa93dab7fd | ||
|
|
5a9ae86cf9 | ||
|
|
7f5f94491e | ||
|
|
a2979650f2 | ||
|
|
3e2f55b9a2 | ||
|
|
8d02399238 | ||
|
|
f0d46a9d73 | ||
|
|
c3f7f4faa8 | ||
|
|
ed97c55c4e | ||
|
|
8e8932cd83 | ||
|
|
c15505062d |
@@ -0,0 +1,6 @@
|
||||
src/App/Utilities/YAML/Schema/
|
||||
*.js
|
||||
*.gen.tsx
|
||||
node_modules
|
||||
/app
|
||||
/deploy
|
||||
@@ -0,0 +1,496 @@
|
||||
root: true
|
||||
parser: "@typescript-eslint/parser"
|
||||
plugins:
|
||||
- "@typescript-eslint"
|
||||
- eslint-plugin-react
|
||||
- eslint-plugin-react-hooks
|
||||
- eslint-plugin-tsdoc
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
project:
|
||||
- ./tsconfig.json
|
||||
ecmaFeatures:
|
||||
jsx: true
|
||||
env:
|
||||
commonjs: true
|
||||
node: true
|
||||
es6: true
|
||||
browser: true
|
||||
rules:
|
||||
# Possible errors
|
||||
for-direction: 2
|
||||
getter-return: 2
|
||||
no-async-promise-executor: 1
|
||||
no-compare-neg-zero: 1
|
||||
no-cond-assign: 2
|
||||
no-constant-condition: 2
|
||||
no-control-regex: 2
|
||||
no-debugger: 2
|
||||
no-duplicate-case: 2
|
||||
no-empty-character-class: 2
|
||||
no-ex-assign: 2
|
||||
no-inner-declarations: 1
|
||||
no-invalid-regexp: 2
|
||||
no-irregular-whitespace: 2
|
||||
no-misleading-character-class: 2
|
||||
no-prototype-builtins: 2
|
||||
no-regex-spaces: 2
|
||||
no-sparse-arrays: 2
|
||||
no-template-curly-in-string: 2
|
||||
no-unreachable: 2
|
||||
no-unsafe-finally: 2
|
||||
no-unsafe-negation: 2
|
||||
require-atomic-updates: 2
|
||||
use-isnan: 2
|
||||
|
||||
# Best Practices
|
||||
accessor-pairs: 2
|
||||
class-methods-use-this: 1
|
||||
# complexity: 2
|
||||
curly:
|
||||
- 2
|
||||
- all
|
||||
default-case: 2
|
||||
dot-location:
|
||||
- 2
|
||||
- property
|
||||
# dot-notation:
|
||||
# - 2
|
||||
# - allowKeywords: false
|
||||
eqeqeq: 2
|
||||
guard-for-in: 2
|
||||
no-alert: 2
|
||||
no-caller: 2
|
||||
no-case-declarations: 2
|
||||
no-div-regex: 2
|
||||
# no-else-return:
|
||||
# - 2
|
||||
# - allowElseIf: true
|
||||
# no-empty-function: 2
|
||||
no-empty-pattern: 2
|
||||
no-eq-null: 2
|
||||
no-eval: 2
|
||||
no-extend-native:
|
||||
- 2
|
||||
- exceptions:
|
||||
- "Array"
|
||||
- "Map"
|
||||
- "Set"
|
||||
no-extra-bind: 2
|
||||
no-extra-label: 2
|
||||
no-fallthrough: 2
|
||||
no-floating-decimal: 2
|
||||
no-global-assign: 2
|
||||
no-implicit-coercion:
|
||||
- 2
|
||||
- allow:
|
||||
- "!!"
|
||||
no-implied-eval: 2
|
||||
# no-invalid-this: 2
|
||||
no-iterator: 2
|
||||
no-labels: 2
|
||||
no-lone-blocks: 2
|
||||
no-loop-func: 2
|
||||
no-multi-spaces: 2
|
||||
no-multi-str: 2
|
||||
no-new: 2
|
||||
no-new-func: 2
|
||||
no-new-wrappers: 2
|
||||
no-octal: 2
|
||||
no-octal-escape: 2
|
||||
no-param-reassign: 2
|
||||
no-proto: 2
|
||||
no-redeclare: 0
|
||||
no-return-assign: 2
|
||||
no-script-url: 2
|
||||
no-self-assign: 2
|
||||
no-self-compare: 2
|
||||
no-throw-literal: 2
|
||||
no-unmodified-loop-condition: 2
|
||||
no-unused-labels: 2
|
||||
no-useless-call: 2
|
||||
no-useless-catch: 2
|
||||
no-useless-concat: 2
|
||||
no-useless-escape: 2
|
||||
no-useless-return: 2
|
||||
no-void: 2
|
||||
no-warning-comments: 1
|
||||
no-with: 2
|
||||
prefer-named-capture-group: 1
|
||||
prefer-promise-reject-errors: 2
|
||||
radix: 2
|
||||
require-unicode-regexp: 2
|
||||
wrap-iife: 2
|
||||
yoda: 2
|
||||
|
||||
# Variables
|
||||
init-declarations: 2
|
||||
no-delete-var: 2
|
||||
no-label-var: 2
|
||||
no-shadow: 0
|
||||
no-shadow-restricted-names: 2
|
||||
# no-undef: 2
|
||||
|
||||
# Stylistic Issues
|
||||
array-bracket-spacing:
|
||||
- 2
|
||||
- always
|
||||
array-element-newline:
|
||||
- 2
|
||||
- consistent
|
||||
block-spacing: 2
|
||||
# capitalized-comments: 2
|
||||
comma-dangle:
|
||||
- 2
|
||||
- arrays: always-multiline
|
||||
objects: always-multiline
|
||||
imports: always-multiline
|
||||
exports: always-multiline
|
||||
functions: only-multiline
|
||||
comma-style: 2
|
||||
computed-property-spacing: 2
|
||||
eol-last: 2
|
||||
func-name-matching: 2
|
||||
func-names: 2
|
||||
func-style:
|
||||
- 2
|
||||
- declaration
|
||||
- allowArrowFunctions: true
|
||||
function-call-argument-newline:
|
||||
- 2
|
||||
- consistent
|
||||
function-paren-newline:
|
||||
- 2
|
||||
- multiline-arguments
|
||||
jsx-quotes: 2
|
||||
key-spacing: 2
|
||||
keyword-spacing: 2
|
||||
line-comment-position: 2
|
||||
lines-around-comment:
|
||||
- 0
|
||||
# requires an empty line before block comments
|
||||
- beforeBlockComment: true
|
||||
# requires an empty line after block comments
|
||||
afterBlockComment: false
|
||||
# requires an empty line before line comments
|
||||
beforeLineComment: true
|
||||
# requires an empty line after line comments
|
||||
afterLineComment: false
|
||||
# allows comments to appear at the start of block statements
|
||||
allowBlockStart: true
|
||||
# allows comments to appear at the end of block statements
|
||||
allowBlockEnd: false
|
||||
# allows comments to appear at the start of object literals
|
||||
allowObjectStart: true
|
||||
# allows comments to appear at the end of object literals
|
||||
allowObjectEnd: false
|
||||
# allows comments to appear at the start of array literals
|
||||
allowArrayStart: true
|
||||
# allows comments to appear at the end of array literals
|
||||
allowArrayEnd: false
|
||||
# allows comments to appear at the start of classes
|
||||
allowClassStart: true
|
||||
# allows comments to appear at the end of classes
|
||||
allowClassEnd: false
|
||||
ignorePattern: "^ *@"
|
||||
lines-between-class-members: 2
|
||||
max-len:
|
||||
- 2
|
||||
- code: 100
|
||||
ignoreComments: true
|
||||
ignoreTemplateLiterals: true
|
||||
ignorePattern: "^import |^export \\{(.*?)\\}|^ \\* |^ *it ?\\(\"\\w+"
|
||||
max-statements-per-line: [2, { max: 2 }]
|
||||
multiline-ternary:
|
||||
- 2
|
||||
- always-multiline
|
||||
new-parens: 2
|
||||
newline-per-chained-call:
|
||||
- 2
|
||||
- ignoreChainWithDepth: 2
|
||||
no-bitwise: 2
|
||||
no-continue: 2
|
||||
no-inline-comments: 2
|
||||
no-lonely-if: 2
|
||||
no-mixed-operators:
|
||||
- 2
|
||||
- groups:
|
||||
- ["&", "|", "^", "~", "<<", ">>", ">>>"]
|
||||
- ["==", "!=", "===", "!==", ">", ">=", "<", "<="]
|
||||
- ["&&", "||"]
|
||||
- ["in", "instanceof"]
|
||||
allowSamePrecedence: true
|
||||
no-mixed-spaces-and-tabs: 2
|
||||
no-multi-assign: 2
|
||||
no-multiple-empty-lines: 2
|
||||
no-negated-condition: 2
|
||||
no-new-object: 2
|
||||
no-tabs: 2
|
||||
no-trailing-spaces: 2
|
||||
no-unneeded-ternary: 2
|
||||
nonblock-statement-body-position: 2
|
||||
# object-curly-newline:
|
||||
# - 2
|
||||
# - multiline: true
|
||||
object-curly-spacing:
|
||||
- 2
|
||||
- always
|
||||
operator-assignment: 2
|
||||
operator-linebreak:
|
||||
- 2
|
||||
- before
|
||||
- overrides:
|
||||
"=": ignore
|
||||
padded-blocks:
|
||||
- 2
|
||||
- blocks: never
|
||||
classes: never
|
||||
switches: never
|
||||
padding-line-between-statements:
|
||||
- 2
|
||||
- blankLine: always
|
||||
prev: "*"
|
||||
next: return
|
||||
prefer-object-spread: 2
|
||||
quote-props:
|
||||
- 2
|
||||
- as-needed
|
||||
semi-spacing: 2
|
||||
semi-style: 2
|
||||
space-before-blocks: 2
|
||||
space-in-parens: 2
|
||||
space-infix-ops:
|
||||
- 2
|
||||
- int32Hint: true
|
||||
space-unary-ops: 2
|
||||
spaced-comment: 2
|
||||
switch-colon-spacing: 2
|
||||
template-tag-spacing:
|
||||
- 2
|
||||
- always
|
||||
|
||||
# ECMAScript 6
|
||||
arrow-body-style: 2
|
||||
arrow-parens:
|
||||
- 2
|
||||
- as-needed
|
||||
arrow-spacing: 2
|
||||
constructor-super: 2
|
||||
generator-star-spacing:
|
||||
- 2
|
||||
- after
|
||||
no-class-assign: 2
|
||||
no-new-symbol: 2
|
||||
no-this-before-super: 2
|
||||
no-useless-computed-key: 2
|
||||
no-useless-rename: 2
|
||||
no-var: 2
|
||||
object-shorthand: 2
|
||||
prefer-arrow-callback: 2
|
||||
prefer-const: 2
|
||||
prefer-destructuring:
|
||||
- 2
|
||||
- object: true
|
||||
array: false
|
||||
prefer-numeric-literals: 2
|
||||
prefer-rest-params: 2
|
||||
prefer-spread: 2
|
||||
prefer-template: 2
|
||||
require-yield: 2
|
||||
rest-spread-spacing: 2
|
||||
# sort-imports:
|
||||
# - 2
|
||||
# - ignoreCase: true
|
||||
# ignoreMemberSort: true
|
||||
symbol-description: 2
|
||||
template-curly-spacing: 2
|
||||
yield-star-spacing:
|
||||
- 2
|
||||
- after
|
||||
|
||||
# TypeScript
|
||||
"@typescript-eslint/adjacent-overload-signatures": 2
|
||||
"@typescript-eslint/array-type": 2
|
||||
"@typescript-eslint/await-thenable": 2
|
||||
# "@typescript-eslint/class-name-casing": 2
|
||||
"@typescript-eslint/consistent-type-assertions": 2
|
||||
"@typescript-eslint/member-delimiter-style":
|
||||
- 2
|
||||
- multiline:
|
||||
delimiter: none
|
||||
singleline:
|
||||
delimiter: semi
|
||||
requireLast: false
|
||||
"@typescript-eslint/naming-convention":
|
||||
- error
|
||||
- selector: interface
|
||||
format:
|
||||
- PascalCase
|
||||
custom:
|
||||
regex: "^I[A-Z]"
|
||||
match: false
|
||||
"@typescript-eslint/no-floating-promises": 2
|
||||
"@typescript-eslint/no-for-in-array": 2
|
||||
"@typescript-eslint/no-inferrable-types": 2
|
||||
"@typescript-eslint/no-misused-new": 2
|
||||
"@typescript-eslint/no-misused-promises": 2
|
||||
"@typescript-eslint/no-this-alias": 2
|
||||
"@typescript-eslint/no-unnecessary-type-arguments": 2
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": 2
|
||||
"@typescript-eslint/prefer-for-of": 2
|
||||
"@typescript-eslint/prefer-includes": 2
|
||||
"@typescript-eslint/prefer-readonly": 2
|
||||
"@typescript-eslint/promise-function-async": 2
|
||||
# "@typescript-eslint/quotes": 2
|
||||
"@typescript-eslint/require-array-sort-compare": 2
|
||||
"@typescript-eslint/require-await": 2
|
||||
"@typescript-eslint/restrict-plus-operands": 2
|
||||
# "@typescript-eslint/semi":
|
||||
# - 2
|
||||
# - never
|
||||
"@typescript-eslint/strict-boolean-expressions": 2
|
||||
"@typescript-eslint/triple-slash-reference": 2
|
||||
"@typescript-eslint/type-annotation-spacing": 2
|
||||
# "@typescript-eslint/unbound-method": 2
|
||||
"@typescript-eslint/unified-signatures": 2
|
||||
|
||||
# TypeScript Extension
|
||||
brace-style: 0
|
||||
"@typescript-eslint/brace-style":
|
||||
- 2
|
||||
- stroustrup
|
||||
comma-spacing: 0
|
||||
"@typescript-eslint/comma-spacing": 2
|
||||
func-call-spacing: 0
|
||||
"@typescript-eslint/func-call-spacing":
|
||||
- 2
|
||||
- always
|
||||
- allowNewlines: true
|
||||
indent: 0
|
||||
"@typescript-eslint/indent": 0
|
||||
no-array-constructor: 0
|
||||
"@typescript-eslint/no-array-constructor": 2
|
||||
no-extra-parens: 0
|
||||
"@typescript-eslint/no-extra-parens": 0
|
||||
no-extra-semi: 0
|
||||
"@typescript-eslint/no-extra-semi": 2
|
||||
no-unused-expressions: 0
|
||||
"@typescript-eslint/no-redeclare": 2
|
||||
"@typescript-eslint/no-shadow": 2
|
||||
"@typescript-eslint/no-unused-expressions": 2
|
||||
"@typescript-eslint/no-unused-vars":
|
||||
- 2
|
||||
- argsIgnorePattern: "^_"
|
||||
varsIgnorePattern: "^_"
|
||||
"@typescript-eslint/no-use-before-define": 2
|
||||
no-useless-constructor: 0
|
||||
"@typescript-eslint/no-useless-constructor": 2
|
||||
quotes: 0
|
||||
"@typescript-eslint/quotes":
|
||||
- 2
|
||||
- double
|
||||
- avoidEscape: true
|
||||
allowTemplateLiterals: true
|
||||
no-return-await: 0
|
||||
"@typescript-eslint/return-await": 2
|
||||
semi: 0
|
||||
"@typescript-eslint/semi":
|
||||
- 2
|
||||
- never
|
||||
- beforeStatementContinuationChars: never
|
||||
space-before-function-paren: 0
|
||||
"@typescript-eslint/space-before-function-paren": 2
|
||||
|
||||
# React
|
||||
react/boolean-prop-naming: 2
|
||||
react/destructuring-assignment: 2
|
||||
react/no-access-state-in-setstate: 2
|
||||
react/no-array-index-key: 2
|
||||
react/no-children-prop: 2
|
||||
react/no-danger: 2
|
||||
react/no-danger-with-children: 2
|
||||
react/no-deprecated: 2
|
||||
react/no-did-mount-set-state: 2
|
||||
react/no-did-update-set-state: 1
|
||||
react/no-direct-mutation-state: 2
|
||||
react/no-find-dom-node: 2
|
||||
react/no-is-mounted: 2
|
||||
# react/no-multi-comp: 2
|
||||
react/no-redundant-should-component-update: 2
|
||||
react/no-render-return-value: 2
|
||||
react/no-typos: 2
|
||||
react/no-string-refs: 2
|
||||
react/no-this-in-sfc: 2
|
||||
react/no-unescaped-entities: 2
|
||||
react/no-unsafe: 2
|
||||
react/no-unused-prop-types: 2
|
||||
react/no-unused-state: 2
|
||||
react/no-will-update-set-state: 2
|
||||
react/prefer-es6-class: 2
|
||||
react/prefer-stateless-function: 2
|
||||
react/react-in-jsx-scope: 2
|
||||
react/require-render-return: 2
|
||||
react/self-closing-comp: 2
|
||||
react/state-in-constructor:
|
||||
- 2
|
||||
- never
|
||||
react/style-prop-object: 2
|
||||
react/void-dom-elements-no-children: 2
|
||||
react/jsx-boolean-value:
|
||||
- 2
|
||||
- never
|
||||
react/jsx-child-element-spacing: 2
|
||||
react/jsx-closing-bracket-location:
|
||||
- 2
|
||||
- props-aligned
|
||||
react/jsx-closing-tag-location: 2
|
||||
react/jsx-curly-newline: 2
|
||||
react/jsx-curly-spacing: 2
|
||||
react/jsx-equals-spacing: 2
|
||||
react/jsx-first-prop-new-line: 2
|
||||
react/jsx-handler-names: 2
|
||||
# react/jsx-indent:
|
||||
# - 2
|
||||
# - 2
|
||||
react/jsx-indent-props:
|
||||
- 2
|
||||
- 2
|
||||
react/jsx-max-props-per-line:
|
||||
- 2
|
||||
- maximum: 3
|
||||
react/jsx-no-bind: 2
|
||||
react/jsx-no-comment-textnodes: 2
|
||||
react/jsx-no-literals: 2
|
||||
react/jsx-no-target-blank: 2
|
||||
react/jsx-one-expression-per-line:
|
||||
- 2
|
||||
- allow: single-child
|
||||
react/jsx-curly-brace-presence:
|
||||
- 2
|
||||
- props: never
|
||||
children: ignore
|
||||
react/jsx-fragments: 2
|
||||
react/jsx-pascal-case: 2
|
||||
react/jsx-props-no-multi-spaces: 2
|
||||
react/jsx-props-no-spreading: 2
|
||||
react/jsx-tag-spacing: 2
|
||||
react/jsx-wrap-multilines:
|
||||
- 2
|
||||
- declaration: parens-new-line
|
||||
assignment: parens-new-line
|
||||
return: parens-new-line
|
||||
arrow: parens-new-line
|
||||
condition: parens-new-line
|
||||
logical: parens-new-line
|
||||
prop: ignore
|
||||
|
||||
# React Hooks
|
||||
react-hooks/rules-of-hooks: 2
|
||||
react-hooks/exhaustive-deps: 2
|
||||
|
||||
# TSDoc
|
||||
tsdoc/syntax: warn
|
||||
settings:
|
||||
react:
|
||||
version: detect
|
||||
@@ -9,19 +9,27 @@ assignees: ''
|
||||
|
||||
## Sources
|
||||
|
||||
> List here what is included in this part of the book to implement. E.g., for special abilities, you need to list every source of entries from the book. Example (in German):
|
||||
>
|
||||
> - S. 133–150 (Berufsgeheimnisse)
|
||||
<!-- List here what is included in this part of the book to implement. E.g., for special abilities, you need to list every source of entries from the book. Use page ranges if entries span multiple pages. Example:
|
||||
|
||||
- S. X (Section/Chapter Name)
|
||||
- [ ] S. 133 (Entry A)
|
||||
- [ ] S. 133–134 (Entry B)
|
||||
|
||||
Alternatively, provide an overview of the different sections in the book where one or more relevant entries occur. Example (in German):
|
||||
|
||||
- [ ] S. 133–150 (Berufsgeheimnisse)
|
||||
|
||||
-->
|
||||
|
||||
- [ ] S. X (Entry/Section/Chapter Name)
|
||||
|
||||
## Special Notes
|
||||
|
||||
> List here any special hints to implement the sources listed above.
|
||||
>
|
||||
> - …
|
||||
<!-- List here any special hints to implement the sources listed above. Example:
|
||||
|
||||
- All entries are already present, only add source references
|
||||
- Pay attention to the layout of entry A, there is a gap that should not be in Optolith
|
||||
|
||||
Replace the dash below this comment if there are any notes. -->
|
||||
|
||||
—
|
||||
|
||||
@@ -29,8 +37,10 @@ assignees: ''
|
||||
|
||||
## Special Implementations
|
||||
|
||||
> List here what cannot be solved only using the database. Example (in German):
|
||||
>
|
||||
> - [ ] Voraussetzungen Vorliebe I-II
|
||||
<!-- List issues that track what cannot be solved only using the database. Example:
|
||||
|
||||
- #123
|
||||
|
||||
Replace the dash below this comment if there are any notes. -->
|
||||
|
||||
—
|
||||
|
||||
@@ -27,20 +27,19 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.ACCESS_TOKEN }}
|
||||
submodules: true
|
||||
- name: Use Node.js 20
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 18.x
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Compile JavaScript files
|
||||
run: npm run js:build
|
||||
- name: Build database cache
|
||||
run: npm run buildCache
|
||||
working-directory: ./src/database/contents
|
||||
- name: Compile Sass files
|
||||
run: npm run css:build
|
||||
- name: Build macOS application
|
||||
if: runner.os == 'macOS'
|
||||
run: node ./deploy/build.js --prerelease
|
||||
run: node ./deploy/build.mjs prerelease
|
||||
env:
|
||||
APPLEID: ${{ secrets.APPLEID }}
|
||||
APPLEIDPASS: ${{ secrets.APPLEIDPASS }}
|
||||
@@ -50,16 +49,16 @@ jobs:
|
||||
UPDATE_URL: ${{ secrets.UPDATE_URL }}
|
||||
- name: Build Linux application
|
||||
if: runner.os == 'Linux'
|
||||
run: node ./deploy/build.js --prerelease
|
||||
run: node ./deploy/build.mjs prerelease
|
||||
env:
|
||||
UPDATE_URL: ${{ secrets.UPDATE_URL }}
|
||||
- name: Build Windows application
|
||||
if: runner.os == 'Windows'
|
||||
run: node ./deploy/build.js --prerelease
|
||||
run: node ./deploy/build.mjs prerelease
|
||||
env:
|
||||
UPDATE_URL: ${{ secrets.UPDATE_URL }}
|
||||
- name: Deploy
|
||||
run: node ./deploy/deploy.js --prerelease
|
||||
run: node ./deploy/deploy.mjs prerelease
|
||||
env:
|
||||
HOST: ${{ secrets.HOST }}
|
||||
USERNAME: ${{ secrets.USERNAME }}
|
||||
|
||||
@@ -27,20 +27,19 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.ACCESS_TOKEN }}
|
||||
submodules: true
|
||||
- name: Use Node.js 20
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 18.x
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Compile JavaScript files
|
||||
run: npm run js:build
|
||||
- name: Build database cache
|
||||
run: npm run buildCache
|
||||
working-directory: ./src/database/contents
|
||||
- name: Compile Sass files
|
||||
run: npm run css:build
|
||||
- name: Build macOS application
|
||||
if: runner.os == 'macOS'
|
||||
run: node ./deploy/build.js --stable
|
||||
run: node ./deploy/build.mjs stable
|
||||
env:
|
||||
APPLEID: ${{ secrets.APPLEID }}
|
||||
APPLEIDPASS: ${{ secrets.APPLEIDPASS }}
|
||||
@@ -50,16 +49,16 @@ jobs:
|
||||
UPDATE_URL: ${{ secrets.UPDATE_URL }}
|
||||
- name: Build Linux application
|
||||
if: runner.os == 'Linux'
|
||||
run: node ./deploy/build.js --stable
|
||||
run: node ./deploy/build.mjs stable
|
||||
env:
|
||||
UPDATE_URL: ${{ secrets.UPDATE_URL }}
|
||||
- name: Build Windows application
|
||||
if: runner.os == 'Windows'
|
||||
run: node ./deploy/build.js --stable
|
||||
run: node ./deploy/build.mjs stable
|
||||
env:
|
||||
UPDATE_URL: ${{ secrets.UPDATE_URL }}
|
||||
- name: Deploy
|
||||
run: node ./deploy/deploy.js --stable
|
||||
run: node ./deploy/deploy.mjs stable
|
||||
env:
|
||||
HOST: ${{ secrets.HOST }}
|
||||
USERNAME: ${{ secrets.USERNAME }}
|
||||
|
||||
@@ -1,42 +1,48 @@
|
||||
name: CI
|
||||
name: Integration
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- develop-v2
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- develop-v2
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Tests
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
node-version: 20
|
||||
token: ${{ secrets.ACCESS_TOKEN }}
|
||||
submodules: true
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Compile TypeScript files
|
||||
run: npm run ts:build
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
linting:
|
||||
name: Linting
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
node-version: 20
|
||||
token: ${{ secrets.ACCESS_TOKEN }}
|
||||
submodules: true
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Run linter
|
||||
@@ -1,6 +1,4 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/.webpack/**/*
|
||||
npm-debug.log*
|
||||
.vs/
|
||||
/data/
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[submodule "app/Database"]
|
||||
path = src/database/contents
|
||||
path = app/Database
|
||||
url = https://github.com/elyukai/optolith-data.git
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
arrowParens: avoid
|
||||
printWidth: 100
|
||||
semi: false
|
||||
tabWidth: 2
|
||||
trailingComma: all
|
||||
@@ -15,14 +15,7 @@
|
||||
"typescriptreact"
|
||||
],
|
||||
"eslint.lintTask.enable": true,
|
||||
"eslint.lintTask.options": "\"src/**\"",
|
||||
"eslint.experimental.useFlatConfig": true,
|
||||
"eslint.lintTask.options": "\"src/**\" -c \"./.eslintrc.yaml\" --ext=\"ts\" --ext=\"tsx\" --ignore-pattern=\"./src/App/Utilities/YAML/Schema/**\"",
|
||||
"editor.tabSize": 2,
|
||||
"editor.detectIndentation": false,
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.detectIndentation": false
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"command": "npm start"
|
||||
},
|
||||
{
|
||||
"label": "test",
|
||||
"label": "jest",
|
||||
"command": "npm test",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
@@ -42,9 +42,18 @@
|
||||
"group": "watch"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "sass watch",
|
||||
"command": "npm run css:watch",
|
||||
"isBackground": true,
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"group": "watch"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"dependsOn": ["tsc watch", "webpack watch"],
|
||||
"dependsOn": ["tsc watch", "webpack watch", "sass watch"],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
@@ -55,14 +64,6 @@
|
||||
"command": "npm run release:pre",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "build database cache",
|
||||
"command": "npm run buildCache",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/src/database/contents"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "create release",
|
||||
"command": "npm run release:main",
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Lukas Obermann <lukas.obermann@icloud.com>
|
||||
Philipp Borucki <p.borucki@icloud.com>
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
### [1.5.2](https://github.com/elyukai/optolith-client/compare/v1.5.2-alpha.4...v1.5.2) (2025-01-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* throws during startup due to changed devtools identifiers ([7f5f944](https://github.com/elyukai/optolith-client/commit/7f5f94491e1432d66add1315889075fb5369f700)), closes [#1634](https://github.com/elyukai/optolith-client/issues/1634)
|
||||
|
||||
### [1.5.2-alpha.4](https://github.com/elyukai/optolith-client/compare/v1.5.2-alpha.3...v1.5.2-alpha.4) (2022-07-22)
|
||||
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ Clone the repo, including the private submodule.
|
||||
git clone --recurse-submodules https://github.com/elyukai/optolith-client.git
|
||||
```
|
||||
|
||||
Make sure Node.js (lastest version) is installed, nagivate into the created project folder and install all dependencies using the following command:
|
||||
Make sure Node.js (lastest version) is installed and run
|
||||
|
||||
```sh
|
||||
npm i
|
||||
@@ -64,17 +64,27 @@ This installs all necessary packages.
|
||||
|
||||
### First run
|
||||
|
||||
Compile the source code. `js:` is for TypeScript/Webpack. Webpack does not check the TypeScript validity, to check this, use `ts:` commands.
|
||||
Compile the source code. `js:` is for TypeScript/Webpack, `re:` for Reason/OCaml and `css:` for CSS/Sass. Webpack does not check the TypeScript validity, to check this, use `ts:` commands.
|
||||
|
||||
Build the source by running
|
||||
You have to run the Reason build first as it generates TypeScript files...
|
||||
|
||||
```sh
|
||||
npm run ts:build
|
||||
npm run css:build
|
||||
npm run js:build
|
||||
```
|
||||
|
||||
(There's also a shorthand for that:)
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
…or watch it for better performance for subsequent compiling on save (you need to use separate terminal instances then).
|
||||
|
||||
```sh
|
||||
npm run re:watch
|
||||
npm run css:watch
|
||||
npm run js:watch
|
||||
```
|
||||
|
||||
@@ -91,20 +101,22 @@ Run the app:
|
||||
npm start
|
||||
```
|
||||
|
||||
The [debug](https://www.npmjs.com/package/debug) package is used for some general logging. If you want to see its output, you need to set the `DEBUG` environment variable.
|
||||
### Stylesheets
|
||||
|
||||
To compile the SCSS files, use
|
||||
|
||||
```sh
|
||||
DEBUG=* npm start
|
||||
```
|
||||
|
||||
In PowerShell you need to write this instead:
|
||||
|
||||
```sh
|
||||
$env:DEBUG='*'; npm start
|
||||
npm run css:build
|
||||
```
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
Clean the files built by the Reason compiler, if there are any issue with it.
|
||||
|
||||
```sh
|
||||
npm run re:clean
|
||||
```
|
||||
|
||||
Lint all project TS files using ESLint.
|
||||
|
||||
```sh
|
||||
|
||||
@@ -2,21 +2,12 @@
|
||||
|
||||
Welcome to the repository for Optolith, a desktop application for The Dark Eye 5th Edition. Nice to see you here! 👋🏻
|
||||
|
||||
> [!CAUTION]
|
||||
> This is the branch of the upcoming V2 version. This is **not production-ready**. If you need access to the V1 line of releases, check out the `develop-V1` branch.
|
||||
>
|
||||
> Note that the self-building constraints below also apply to the V1.
|
||||
|
||||
## Install
|
||||
|
||||
You can download the app [here (German page)](http://www.ulisses-ebooks.de/product/209711) or here [here (English page)](http://www.drivethrurpg.com/product/220253) (same app on both pages). You'll get an installer for Windows with Auto Update support and a DMG for Mac. For Linux, you get an AppImage, which _should_ support Auto Update but it doesnt seem to work currently. You also get a tar.gz if you don't like AppImage.
|
||||
You can download the app [here (German page)](http://www.ulisses-ebooks.de/product/209711) or here [here (English page)](http://www.drivethrurpg.com/product/220253) (same app on both pages). You'll get an installer for Windows with Auto Update support and a DMG for Mac. For Linux, you get an AppImage, which *should* support Auto Update but it doesnt seem to work currently. You also get a tar.gz if you don't like AppImage.
|
||||
|
||||
It is available for Windows 7+ as well as for Linux (Ubuntu 12.04+, Fedora 21, Debian 8) and macOS 10.9+ x64.
|
||||
|
||||
### Self-Building and Package Registries
|
||||
|
||||
Please note that self-building is only possible in a restricted way, as the underlying database is private due to licensing reasons. You can follow the in the [Contributing Guide](CONTRIBUTING.md) to obtain a version of the database from an already existing release. Please note that due to these licensing restrictions distribution via package managers like `brew` or `apt`
|
||||
|
||||
## Goal
|
||||
|
||||
Optolith was built and is developed based on a few key criteria:
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
export interface RawConfig {
|
||||
herolistSortOrder: "name" | "datemodified" | "dateModified"
|
||||
herolistVisibilityFilter: "all" | "own" | "shared"
|
||||
racesSortOrder: "name" | "cost"
|
||||
racesValueVisibility?: boolean
|
||||
culturesSortOrder: "name" | "cost"
|
||||
culturesVisibilityFilter: "all" | "common"
|
||||
culturesValueVisibility?: boolean
|
||||
professionsSortOrder: "name" | "cost"
|
||||
professionsVisibilityFilter: "all" | "common"
|
||||
professionsGroupVisibilityFilter: 0 | 1 | 2 | 3
|
||||
professionsFromExpansionsVisibility?: boolean
|
||||
advantagesDisadvantagesCultureRatingVisibility: boolean
|
||||
talentsSortOrder: "name" | "group" | "ic"
|
||||
talentsCultureRatingVisibility: boolean
|
||||
combatTechniquesSortOrder: "name" | "group" | "ic"
|
||||
specialAbilitiesSortOrder: "name" | "group" | "groupname"
|
||||
spellsSortOrder: "name" | "group" | "property" | "ic"
|
||||
spellsUnfamiliarVisibility: boolean
|
||||
liturgiesSortOrder: "name" | "group" | "ic"
|
||||
equipmentSortOrder: "name" | "groupname" | "where" | "weight"
|
||||
equipmentGroupVisibilityFilter: number
|
||||
sheetCheckAttributeValueVisibility?: boolean
|
||||
sheetUseParchment?: boolean
|
||||
sheetShowRules?: boolean
|
||||
sheetZoomFactor?: number
|
||||
enableActiveItemHints: boolean
|
||||
locale?: string
|
||||
fallbackLocale?: string
|
||||
theme?: "light" | "dark"
|
||||
enableEditingHeroAfterCreationPhase?: boolean
|
||||
meleeItemTemplatesCombatTechniqueFilter?: string
|
||||
rangedItemTemplatesCombatTechniqueFilter?: string
|
||||
enableAnimations?: boolean
|
||||
}
|
||||
@@ -1,90 +1,74 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft-07/schema",
|
||||
"$id": "/config.schema.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"$id": "Schema/Config/Config.l10n.schema.json",
|
||||
"$ref": "#/definitions/Config",
|
||||
"definitions": {
|
||||
"Config": {
|
||||
"description": "The user-configurable app-wide settings.",
|
||||
"title": "RawConfig",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"locale": {
|
||||
"type": "string"
|
||||
},
|
||||
"fallbackLocale": {
|
||||
"type": "string"
|
||||
},
|
||||
"herolistSortOrder": {
|
||||
"$ref": "#/definitions/CharactersSortOrder"
|
||||
"enum": ["name", "datemodified", "dateModified"]
|
||||
},
|
||||
"herolistVisibilityFilter": {
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "all"
|
||||
},
|
||||
{
|
||||
"const": "own"
|
||||
},
|
||||
{
|
||||
"const": "shared"
|
||||
}
|
||||
]
|
||||
"enum": ["all", "own", "shared"]
|
||||
},
|
||||
"racesSortOrder": {
|
||||
"$ref": "#/definitions/RacesSortOrder"
|
||||
"enum": ["name", "cost"]
|
||||
},
|
||||
"racesValueVisibility": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"culturesSortOrder": {
|
||||
"$ref": "#/definitions/CulturesSortOrder"
|
||||
"enum": ["name", "cost"]
|
||||
},
|
||||
"culturesVisibilityFilter": {
|
||||
"$ref": "#/definitions/CulturesVisibilityFilter"
|
||||
"enum": ["all", "common"]
|
||||
},
|
||||
"culturesValueVisibility": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"professionsSortOrder": {
|
||||
"$ref": "#/definitions/ProfessionsSortOrder"
|
||||
"enum": ["name", "cost"]
|
||||
},
|
||||
"professionsVisibilityFilter": {
|
||||
"$ref": "#/definitions/ProfessionsVisibilityFilter"
|
||||
},
|
||||
"professionsGroupVisibilityFilter": {
|
||||
"$ref": "#/definitions/ProfessionsGroupVisibilityFilter"
|
||||
"enum": ["all", "common"]
|
||||
},
|
||||
"professionsFromExpansionsVisibility": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"professionsGroupVisibilityFilter": {
|
||||
"enum": [0, 1, 2, 3]
|
||||
},
|
||||
"advantagesDisadvantagesCultureRatingVisibility": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"talentsSortOrder": {
|
||||
"$ref": "#/definitions/SkillsSortOrder"
|
||||
"enum": ["name", "group", "ic"]
|
||||
},
|
||||
"talentsCultureRatingVisibility": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"combatTechniquesSortOrder": {
|
||||
"$ref": "#/definitions/CombatTechniquesSortOrder"
|
||||
"enum": ["name", "group", "ic"]
|
||||
},
|
||||
"specialAbilitiesSortOrder": {
|
||||
"$ref": "#/definitions/SpecialAbilitiesSortOrder"
|
||||
"enum": ["name", "group", "groupname"]
|
||||
},
|
||||
"spellsSortOrder": {
|
||||
"$ref": "#/definitions/SpellsSortOrder"
|
||||
"enum": ["name", "group", "property", "ic"]
|
||||
},
|
||||
"spellsUnfamiliarVisibility": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"liturgiesSortOrder": {
|
||||
"$ref": "#/definitions/LiturgiesSortOrder"
|
||||
"enum": ["name", "group", "ic"]
|
||||
},
|
||||
"equipmentSortOrder": {
|
||||
"$ref": "#/definitions/EquipmentSortOrder"
|
||||
"enum": ["name", "groupname", "where", "weight"]
|
||||
},
|
||||
"equipmentGroupVisibilityFilter": {
|
||||
"type": "number"
|
||||
"type": "integer"
|
||||
},
|
||||
"sheetCheckAttributeValueVisibility": {
|
||||
"type": "boolean"
|
||||
@@ -92,14 +76,23 @@
|
||||
"sheetUseParchment": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sheetShowRules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sheetZoomFactor": {
|
||||
"type": "number"
|
||||
},
|
||||
"enableActiveItemHints": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string"
|
||||
},
|
||||
"fallbackLocale": {
|
||||
"type": "string"
|
||||
},
|
||||
"theme": {
|
||||
"$ref": "#/definitions/Theme"
|
||||
"enum": ["light", "dark"]
|
||||
},
|
||||
"enableEditingHeroAfterCreationPhase": {
|
||||
"type": "boolean"
|
||||
@@ -136,101 +129,6 @@
|
||||
"enableActiveItemHints"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"CharactersSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"datemodified",
|
||||
"datecreated"
|
||||
]
|
||||
},
|
||||
"RacesSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"cost"
|
||||
]
|
||||
},
|
||||
"CulturesSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"cost"
|
||||
]
|
||||
},
|
||||
"CulturesVisibilityFilter": {
|
||||
"enum": [
|
||||
"all",
|
||||
"common"
|
||||
]
|
||||
},
|
||||
"ProfessionsSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"cost"
|
||||
]
|
||||
},
|
||||
"ProfessionsVisibilityFilter": {
|
||||
"enum": [
|
||||
"all",
|
||||
"common"
|
||||
]
|
||||
},
|
||||
"ProfessionsGroupVisibilityFilter": {
|
||||
"enum": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
},
|
||||
"SkillsSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"group",
|
||||
"ic"
|
||||
]
|
||||
},
|
||||
"CombatTechniquesSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"group",
|
||||
"ic"
|
||||
]
|
||||
},
|
||||
"SpecialAbilitiesSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"group",
|
||||
"groupname"
|
||||
]
|
||||
},
|
||||
"SpellsSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"group",
|
||||
"property",
|
||||
"ic"
|
||||
]
|
||||
},
|
||||
"LiturgiesSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"group",
|
||||
"ic"
|
||||
]
|
||||
},
|
||||
"EquipmentSortOrder": {
|
||||
"enum": [
|
||||
"name",
|
||||
"groupname",
|
||||
"where",
|
||||
"weight"
|
||||
]
|
||||
},
|
||||
"Theme": {
|
||||
"enum": [
|
||||
"light",
|
||||
"dark"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 275 KiB After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 265 KiB After Width: | Height: | Size: 265 KiB |
|
Before Width: | Height: | Size: 818 KiB After Width: | Height: | Size: 818 KiB |
|
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 689 B |
|
Before Width: | Height: | Size: 640 B After Width: | Height: | Size: 640 B |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 519 KiB After Width: | Height: | Size: 519 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 415 KiB After Width: | Height: | Size: 415 KiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.3 MiB |
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "optolith-client",
|
||||
"version": "0.1.0",
|
||||
"sources": [
|
||||
{ "dir": "deploy" },
|
||||
{ "dir": "src" },
|
||||
{ "dir": "src/App/Actions" },
|
||||
{ "dir": "src/App/Constants" },
|
||||
{ "dir": "src/App/Containers" },
|
||||
{ "dir": "src/App/Models" },
|
||||
{ "dir": "src/App/Reducers" },
|
||||
{ "dir": "src/App/Selectors" },
|
||||
{ "dir": "src/App/Utilities" },
|
||||
{ "dir": "src/App/Utilities/__tests__", "type": "dev" },
|
||||
{ "dir": "src/App/Utilities/YAML" },
|
||||
{ "dir": "src/App/Views" },
|
||||
{ "dir": "src/App/Views/Universal" },
|
||||
{ "dir": "src/Control" },
|
||||
{ "dir": "src/Data" },
|
||||
{ "dir": "src/Data/__tests__", "type": "dev" },
|
||||
{ "dir": "src/Debug" },
|
||||
{ "dir": "src/System" },
|
||||
{ "dir": "src/shims" }
|
||||
],
|
||||
"package-specs": {
|
||||
"module": "commonjs",
|
||||
"in-source": true
|
||||
},
|
||||
"suffix": ".bs.js",
|
||||
"bs-dependencies": [
|
||||
"@glennsl/bs-json",
|
||||
"@glennsl/bs-jest",
|
||||
"reason-react"
|
||||
],
|
||||
"reason": {
|
||||
"react-jsx": 3
|
||||
},
|
||||
"warnings": {
|
||||
"error" : "+101"
|
||||
},
|
||||
"namespace": true,
|
||||
"refmt": 3,
|
||||
"gentypeconfig": {
|
||||
"module": "commonjs",
|
||||
"language": "typescript",
|
||||
"shims": {
|
||||
"Js": "Js",
|
||||
"ReasonPervasives": "ReasonPervasives"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
// @ts-check
|
||||
import builder from "electron-builder"
|
||||
import { notarize } from "./notarize.js"
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
|
||||
// Detect channel
|
||||
|
||||
if (!args.includes("--stable") && !args.includes("--prerelease")) {
|
||||
throw new TypeError(`Missing channel argument (either "--stable" or "--prerelease")`)
|
||||
}
|
||||
|
||||
const isPrerelease = args.includes("--prerelease")
|
||||
|
||||
console.log(`Detected channel: ${isPrerelease ? "prerelease" : "stable"}`)
|
||||
|
||||
// Detect OS
|
||||
|
||||
let osKey
|
||||
let osName
|
||||
|
||||
if (process.argv.includes("--linux") || process.platform === "linux") {
|
||||
osKey = /** @type {const} */ ("LINUX")
|
||||
osName = "Linux"
|
||||
} else if (process.argv.includes("--mac") || process.platform === "darwin") {
|
||||
osKey = /** @type {const} */ ("MAC")
|
||||
osName = "macOS"
|
||||
} else if (process.argv.includes("--win") || process.platform === "win32") {
|
||||
osKey = /** @type {const} */ ("WINDOWS")
|
||||
osName = "Windows"
|
||||
} else {
|
||||
throw new TypeError(`The target operating system cannot be inferred from the environment.`)
|
||||
}
|
||||
|
||||
console.log(`Detected operating system: ${osName}`)
|
||||
|
||||
// Prepare electron-builder configuration
|
||||
|
||||
/**
|
||||
* @type {import("electron-builder").Configuration}
|
||||
*/
|
||||
const config = {
|
||||
appId: isPrerelease ? "com.lukasobermann.optolithinsider" : "com.lukasobermann.optolith",
|
||||
productName: isPrerelease ? "Optolith Insider" : "Optolith",
|
||||
copyright:
|
||||
"© 2017–present Lukas Obermann. This product was created under a license. Das Schwarze Auge and its logo as well as Aventuria, Dere, Myranor, Riesland, Tharun and Uthuria and their logos are trademarks of Significant GbR. The title and contents of this book are protected under the copyright laws of the United States of America. No part of this publication may be reproduced, stored in retrieval systems or transmitted, in any form or by any means, whether electronic, mechanical, photocopy, recording, or otherwise, without prior written consent by Ulisses Spiele GmbH, Waldems. This publication includes material that is protected under copyright laws by Ulisses Spiele and/or other authors. Such material is used under the Community Content Agreement for the SCRIPTORIUM AVENTURIS. All other original materials in this work is copyright 2017-present by Lukas Obermann and published under the Community Content Agreement for the SCRIPTORIUM AVENTURIS.",
|
||||
files: [
|
||||
".webpack/**",
|
||||
"LICENSE",
|
||||
"node_modules/optolith-database-schema/schema/**",
|
||||
"src/database/contents/cache/**",
|
||||
"src/database/contents/Compatibility/**",
|
||||
"src/database/contents/Data/**",
|
||||
],
|
||||
asar: false, // otherwise optolith-database-schema package is not properly resolved
|
||||
asarUnpack: [
|
||||
"node_modules/optolith-character-schema/**",
|
||||
"node_modules/optolith-database-schema/**",
|
||||
"src/database/contents/**",
|
||||
],
|
||||
directories: {
|
||||
output: isPrerelease ? "dist/insider" : "dist",
|
||||
},
|
||||
win: {
|
||||
target: [
|
||||
{
|
||||
target: "nsis",
|
||||
arch: ["x64", "ia32"],
|
||||
},
|
||||
],
|
||||
icon: isPrerelease ? "src/assets/icon/AppList.targetsize-512.pre.png" : "src/assets/icon/icon.ico",
|
||||
artifactName: isPrerelease ? "OptolithInsiderSetup_${version}.${ext}" : "OptolithSetup_${version}.${ext}",
|
||||
},
|
||||
nsis: {
|
||||
oneClick: false,
|
||||
perMachine: false,
|
||||
allowToChangeInstallationDirectory: true,
|
||||
differentialPackage: true,
|
||||
},
|
||||
linux: {
|
||||
category: "RolePlaying",
|
||||
target: [
|
||||
{
|
||||
target: "AppImage",
|
||||
arch: ["x64"],
|
||||
},
|
||||
{
|
||||
target: "tar.gz",
|
||||
arch: ["x64"],
|
||||
},
|
||||
],
|
||||
executableName: isPrerelease ? "OptolithInsider" : "Optolith",
|
||||
icon: isPrerelease ? "src/assets/icon/icon.pre.png" : "src/assets/icon/AppList.targetsize-512.png",
|
||||
artifactName: isPrerelease ? "OptolithInsider_${version}.${ext}" : "Optolith_${version}.${ext}",
|
||||
},
|
||||
mac: {
|
||||
category: "public.app-category.role-playing-games",
|
||||
type: "distribution",
|
||||
target: [
|
||||
{
|
||||
target: "default",
|
||||
arch: "universal",
|
||||
},
|
||||
],
|
||||
icon: isPrerelease ? "src/assets/icon/AppIcon.pre.icns" : "src/assets/icon/AppIcon.icns",
|
||||
artifactName: isPrerelease ? "OptolithInsider_${version}.${ext}" : "Optolith_${version}.${ext}",
|
||||
mergeASARs: false,
|
||||
darkModeSupport: true,
|
||||
gatekeeperAssess: true,
|
||||
},
|
||||
publish: {
|
||||
provider: "generic",
|
||||
url: isPrerelease ? `${process.env.UPDATE_URL}/insider/\${os}` : `${process.env.UPDATE_URL}/\${os}`,
|
||||
channel: "latest",
|
||||
},
|
||||
afterSign: osKey === "MAC" ? notarize : undefined,
|
||||
}
|
||||
|
||||
await builder.build({
|
||||
config,
|
||||
targets: builder.Platform[osKey].createTarget(),
|
||||
})
|
||||
|
||||
console.log(`Build finished successfully.`)
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,58 +0,0 @@
|
||||
// @ts-check
|
||||
import { notarize as electronNotarize } from "@electron/notarize"
|
||||
|
||||
/**
|
||||
* Notarizes the app package after it has been built. It detects the
|
||||
* authentication method from the environment variables.
|
||||
* @param context {import("electron-builder").AfterPackContext}
|
||||
*/
|
||||
export const notarize = async context => {
|
||||
const { electronPlatformName, appOutDir } = context
|
||||
|
||||
if (electronPlatformName === "darwin") {
|
||||
const appName = context.packager.appInfo.productFilename
|
||||
|
||||
if (
|
||||
typeof process.env.APPLEID === "string" &&
|
||||
typeof process.env.APPLEIDPASS === "string" &&
|
||||
typeof process.env.TEAMID === "string"
|
||||
) {
|
||||
console.log(`Notarizing "${appName}.app" via Apple ID ...`)
|
||||
await electronNotarize({
|
||||
tool: "notarytool",
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleId: process.env.APPLEID,
|
||||
appleIdPassword: process.env.APPLEIDPASS,
|
||||
teamId: process.env.TEAMID,
|
||||
})
|
||||
console.log(`Notarization successful`)
|
||||
} else if (
|
||||
typeof process.env.APPLEAPIKEY === "string" &&
|
||||
typeof process.env.APPLEAPIKEYID === "string" &&
|
||||
typeof process.env.APPLEAPIISSUER === "string"
|
||||
) {
|
||||
console.log(`Notarizing "${appName}.app" via App Store Connect API ...`)
|
||||
await electronNotarize({
|
||||
tool: "notarytool",
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleApiKey: process.env.APPLEAPIKEY,
|
||||
appleApiKeyId: process.env.APPLEAPIKEYID,
|
||||
appleApiIssuer: process.env.APPLEAPIISSUER,
|
||||
})
|
||||
console.log(`Notarization successful`)
|
||||
} else if (typeof process.env.KEYCHAINPROFILE === "string") {
|
||||
console.log(`Notarizing "${appName}.app" via Keychain ...`)
|
||||
await electronNotarize({
|
||||
tool: "notarytool",
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
keychain: process.env.KEYCHAIN,
|
||||
keychainProfile: process.env.KEYCHAINPROFILE,
|
||||
})
|
||||
console.log(`Notarization successful`)
|
||||
} else {
|
||||
throw new Error(
|
||||
`Notarization failed: No valid authentication method found in environment. Please provide either APPLEID and APPLEIDPASS, or APPLEAPIKEY, APPLEAPIKEYID and APPLEAPIISSUER, or (optional) KEYCHAIN and KEYCHAINPROFILE.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// @ts-check
|
||||
/**
|
||||
* @param {"prerelease" | "stable"} channel
|
||||
*/
|
||||
const channelSuffix = channel => {
|
||||
switch (channel) {
|
||||
case "prerelease": return "Insider"
|
||||
case "stable": return ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./platform.mjs").System} os
|
||||
* @param {"prerelease" | "stable"} channel
|
||||
*/
|
||||
const prefix = (os, channel) => {
|
||||
switch (os) {
|
||||
case "win": return `Optolith${channelSuffix(channel)}Setup`
|
||||
case "linux":
|
||||
case "mac": return `Optolith${channelSuffix(channel)}`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./platform.mjs").System} os
|
||||
*/
|
||||
const extensions = os => {
|
||||
switch (os) {
|
||||
case "win": return [".exe", ".exe.blockmap"]
|
||||
case "linux": return [".AppImage", ".tar.gz"]
|
||||
case "mac": return [".dmg", ".dmg.blockmap", ".zip", ".zip.blockmap"]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./platform.mjs").System} os
|
||||
* @param {"prerelease" | "stable"} channel
|
||||
* @param {string} version
|
||||
*/
|
||||
export const getApplicationFileNames = (os, channel, version) =>
|
||||
extensions(os).map(ext => `${prefix(os, channel)}_${version}${ext}`)
|
||||
|
||||
/**
|
||||
* @param {"win" | "mac" | "linux"} os
|
||||
*/
|
||||
export const getUpdateFileName = os => {
|
||||
switch (os) {
|
||||
case "win": return "latest.yml"
|
||||
case "linux": return "latest-linux.yml"
|
||||
default: return "latest-mac.yml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// @ts-check
|
||||
import { notarize } from "./notarize.mjs"
|
||||
|
||||
/**
|
||||
* @type {import("electron-builder").Configuration}
|
||||
*/
|
||||
const config = {
|
||||
appId: "com.lukasobermann.optolith",
|
||||
productName: "Optolith",
|
||||
copyright: "© 2017–present Lukas Obermann. This product was created under a license. Das Schwarze Auge and its logo as well as Aventuria, Dere, Myranor, Riesland, Tharun and Uthuria and their logos are trademarks of Significant GbR. The title and contents of this book are protected under the copyright laws of the United States of America. No part of this publication may be reproduced, stored in retrieval systems or transmitted, in any form or by any means, whether electronic, mechanical, photocopy, recording, or otherwise, without prior written consent by Ulisses Spiele GmbH, Waldems. This publication includes material that is protected under copyright laws by Ulisses Spiele and/or other authors. Such material is used under the Community Content Agreement for the SCRIPTORIUM AVENTURIS. All other original materials in this work is copyright 2017-present by Lukas Obermann and published under the Community Content Agreement for the SCRIPTORIUM AVENTURIS.",
|
||||
directories: {
|
||||
output: "dist"
|
||||
},
|
||||
files: [
|
||||
"app/**/*",
|
||||
"LICENSE"
|
||||
],
|
||||
win: {
|
||||
target: [
|
||||
{
|
||||
target: "nsis",
|
||||
arch: [
|
||||
"x64",
|
||||
"ia32"
|
||||
]
|
||||
}
|
||||
],
|
||||
icon: "app/icon.ico",
|
||||
artifactName: "OptolithSetup_${version}.${ext}"
|
||||
},
|
||||
nsis: {
|
||||
perMachine: true,
|
||||
differentialPackage: true,
|
||||
deleteAppDataOnUninstall: false,
|
||||
},
|
||||
linux: {
|
||||
category: "RolePlaying",
|
||||
executableName: "Optolith",
|
||||
icon: "app",
|
||||
target: [
|
||||
{
|
||||
target: "AppImage",
|
||||
arch: [
|
||||
"x64"
|
||||
]
|
||||
},
|
||||
{
|
||||
target: "tar.gz",
|
||||
arch: [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
],
|
||||
artifactName: "Optolith_${version}.${ext}"
|
||||
},
|
||||
mac: {
|
||||
category: "public.app-category.role-playing-games",
|
||||
type: "distribution",
|
||||
icon: "app/icon.icns",
|
||||
target: [
|
||||
{
|
||||
target: "default",
|
||||
arch: "universal"
|
||||
}
|
||||
],
|
||||
artifactName: "Optolith_${version}.${ext}",
|
||||
entitlements: "deploy/entitlements.mac.plist",
|
||||
entitlementsInherit: "deploy/entitlements.mac.plist",
|
||||
hardenedRuntime: true,
|
||||
gatekeeperAssess: false,
|
||||
},
|
||||
dmg: {
|
||||
sign: false
|
||||
},
|
||||
publish: {
|
||||
"provider": "generic",
|
||||
"url": `${process.env.UPDATE_URL}/\${os}`,
|
||||
"channel": "latest"
|
||||
},
|
||||
afterSign: notarize,
|
||||
}
|
||||
|
||||
export default config
|
||||
@@ -0,0 +1,27 @@
|
||||
// @ts-check
|
||||
import builder from "electron-builder"
|
||||
import { getSystem } from "./platform.mjs"
|
||||
|
||||
const [channel] = process.argv.slice(2)
|
||||
|
||||
if (channel !== "stable" && channel !== "prerelease") {
|
||||
throw new TypeError (`publishToServer requires a specified channel ("stable" or "prerelease"), but it received ${channel}`)
|
||||
}
|
||||
|
||||
const config =
|
||||
channel === "prerelease"
|
||||
? (await import("./build.prerelease.config.mjs")).default
|
||||
: (await import("./build.config.mjs")).default
|
||||
|
||||
process.on ('unhandledRejection', error => {
|
||||
throw new Error(`Unhandled promise rejection: ${/** @type {Error} */ (error).toString ()}`)
|
||||
})
|
||||
|
||||
const os = getSystem()
|
||||
|
||||
const plaformKey = os === "linux" ? "LINUX" : os === "mac" ? "MAC" : "WINDOWS"
|
||||
|
||||
await builder.build({
|
||||
config,
|
||||
targets: builder.Platform[plaformKey].createTarget(),
|
||||
})
|
||||
@@ -0,0 +1,84 @@
|
||||
// @ts-check
|
||||
import { notarize } from "./notarize.mjs"
|
||||
|
||||
/**
|
||||
* @type {import ("electron-builder") .Configuration}
|
||||
*/
|
||||
const config = {
|
||||
appId: "com.lukasobermann.optolithinsider",
|
||||
productName: "Optolith Insider",
|
||||
copyright: "© 2017–present Lukas Obermann. This product was created under a license. Das Schwarze Auge and its logo as well as Aventuria, Dere, Myranor, Riesland, Tharun and Uthuria and their logos are trademarks of Significant GbR. The title and contents of this book are protected under the copyright laws of the United States of America. No part of this publication may be reproduced, stored in retrieval systems or transmitted, in any form or by any means, whether electronic, mechanical, photocopy, recording, or otherwise, without prior written consent by Ulisses Spiele GmbH, Waldems. This publication includes material that is protected under copyright laws by Ulisses Spiele and/or other authors. Such material is used under the Community Content Agreement for the SCRIPTORIUM AVENTURIS. All other original materials in this work is copyright 2017-present by Lukas Obermann and published under the Community Content Agreement for the SCRIPTORIUM AVENTURIS.",
|
||||
directories: {
|
||||
output: "dist/insider"
|
||||
},
|
||||
files: [
|
||||
"app/**/*",
|
||||
"LICENSE"
|
||||
],
|
||||
asarUnpack: "app/Database/**/*",
|
||||
win: {
|
||||
target: [
|
||||
{
|
||||
target: "nsis",
|
||||
arch: [
|
||||
"x64",
|
||||
"ia32"
|
||||
]
|
||||
}
|
||||
],
|
||||
icon: "app/icon.ico",
|
||||
artifactName: "OptolithInsiderSetup_${version}.${ext}"
|
||||
},
|
||||
nsis: {
|
||||
perMachine: true,
|
||||
differentialPackage: true,
|
||||
deleteAppDataOnUninstall: false,
|
||||
},
|
||||
linux: {
|
||||
category: "RolePlaying",
|
||||
executableName: "OptolithInsider",
|
||||
icon: "app",
|
||||
target: [
|
||||
{
|
||||
target: "AppImage",
|
||||
arch: [
|
||||
"x64"
|
||||
]
|
||||
},
|
||||
{
|
||||
target: "tar.gz",
|
||||
arch: [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
],
|
||||
artifactName: "OptolithInsider_${version}.${ext}"
|
||||
},
|
||||
mac: {
|
||||
category: "public.app-category.role-playing-games",
|
||||
type: "distribution",
|
||||
icon: "app/icon.icns",
|
||||
target: [
|
||||
{
|
||||
target: "default",
|
||||
arch: "universal"
|
||||
}
|
||||
],
|
||||
artifactName: "OptolithInsider_${version}.${ext}",
|
||||
entitlements: "deploy/entitlements.mac.plist",
|
||||
entitlementsInherit: "deploy/entitlements.mac.plist",
|
||||
hardenedRuntime: true,
|
||||
gatekeeperAssess: false,
|
||||
},
|
||||
dmg: {
|
||||
sign: false
|
||||
},
|
||||
publish: {
|
||||
"provider": "generic",
|
||||
"url": `${process.env.UPDATE_URL}/insider/\${os}`,
|
||||
"channel": "latest"
|
||||
},
|
||||
afterSign: notarize,
|
||||
}
|
||||
|
||||
export default config
|
||||
@@ -1,93 +0,0 @@
|
||||
// @ts-check
|
||||
import { join } from "node:path"
|
||||
import packageJson from "../package.json" assert { type: "json" }
|
||||
import { run, upload } from "./uploader.js"
|
||||
|
||||
/**
|
||||
* Needed env variables:
|
||||
* - `HOST`
|
||||
* - `USERNAME`
|
||||
* - `PASSWORD`
|
||||
* - `ROOT`
|
||||
*
|
||||
* Optional env variables:
|
||||
* - `CI`
|
||||
*/
|
||||
const { HOST, USERNAME, PASSWORD, ROOT = "/", CI } = process.env
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
|
||||
// Detect channel
|
||||
|
||||
if (!args.includes("--stable") && !args.includes("--prerelease")) {
|
||||
throw new TypeError(`Missing channel argument (either "--stable" or "--prerelease")`)
|
||||
}
|
||||
|
||||
const isPrerelease = args.includes("--prerelease")
|
||||
|
||||
console.log(`Detected channel: ${isPrerelease ? "prerelease" : "stable"}`)
|
||||
|
||||
// Detect OS
|
||||
|
||||
let os
|
||||
let osName
|
||||
|
||||
if (process.argv.includes("--linux") || process.platform === "linux") {
|
||||
os = /** @type {const} */ ("linux")
|
||||
osName = "Linux"
|
||||
} else if (process.argv.includes("--mac") || process.platform === "darwin") {
|
||||
os = /** @type {const} */ ("mac")
|
||||
osName = "macOS"
|
||||
} else if (process.argv.includes("--win") || process.platform === "win32") {
|
||||
os = /** @type {const} */ ("win")
|
||||
osName = "Windows"
|
||||
} else {
|
||||
throw new TypeError(`The target operating system cannot be inferred from the environment.`)
|
||||
}
|
||||
|
||||
console.log(`Detected operating system: ${osName}`)
|
||||
|
||||
// Infer files to upload
|
||||
|
||||
let fileExtensions
|
||||
let updateInfoFileName
|
||||
|
||||
switch (os) {
|
||||
case "win":
|
||||
fileExtensions = [".exe", ".exe.blockmap"]
|
||||
updateInfoFileName = "latest.yml"
|
||||
break
|
||||
case "linux":
|
||||
fileExtensions = [".AppImage", ".tar.gz"]
|
||||
updateInfoFileName = "latest-linux.yml"
|
||||
break
|
||||
case "mac":
|
||||
fileExtensions = [".dmg", ".dmg.blockmap", ".zip", ".zip.blockmap"]
|
||||
updateInfoFileName = "latest-mac.yml"
|
||||
break
|
||||
}
|
||||
|
||||
const fileNames = [
|
||||
...fileExtensions.map(ext => {
|
||||
const chPart = isPrerelease ? "Insider" : ""
|
||||
const osPart = os === "win" ? "Setup" : ""
|
||||
return `Optolith${chPart}${osPart}_${packageJson.version}${ext}`
|
||||
}),
|
||||
updateInfoFileName,
|
||||
]
|
||||
|
||||
console.log(`Files to upload: ${fileNames.join(", ")}.`)
|
||||
|
||||
// Upload files
|
||||
|
||||
const localDir = isPrerelease ? join("dist", "insider") : join("dist")
|
||||
const remoteDir = join(ROOT, isPrerelease ? "insider" : ".", os)
|
||||
|
||||
await run({ host: HOST, username: USERNAME, password: PASSWORD }, async client => {
|
||||
for (const fileName of fileNames) {
|
||||
console.log(`Uploading ${fileName} ...`)
|
||||
await upload(client, localDir, remoteDir, fileName)
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`Uploading files finished successfully.`)
|
||||
@@ -0,0 +1,52 @@
|
||||
// @ts-check
|
||||
import packageJson from "../package.json" assert { type: "json" }
|
||||
import { getApplicationFileNames, getUpdateFileName } from "./assetNames.mjs"
|
||||
import { getLocalPath } from "./localPath.mjs"
|
||||
import { getSystem, getSystemName } from "./platform.mjs"
|
||||
import { run, upload } from "./remoteConnection.mjs"
|
||||
import { getRemotePath } from "./remotePath.mjs"
|
||||
|
||||
/**
|
||||
* Needed env variables:
|
||||
* - `HOST`
|
||||
* - `USERNAME`
|
||||
* - `PASSWORD`
|
||||
* - `ROOT`
|
||||
*
|
||||
* Optional env variables:
|
||||
* - `CI`
|
||||
*/
|
||||
const {
|
||||
HOST,
|
||||
USERNAME,
|
||||
PASSWORD,
|
||||
ROOT = "/",
|
||||
CI,
|
||||
} = process.env
|
||||
|
||||
const [channel] = process.argv.slice(2)
|
||||
const os = getSystem()
|
||||
|
||||
if (channel !== "stable" && channel !== "prerelease") {
|
||||
throw new TypeError(`publishToServer requires a specified channel ("stable" or "prerelease"), but it received ${channel}`)
|
||||
}
|
||||
|
||||
console.log(`Preparing to upload update files for "${getSystemName(os)}" on "${channel}" channel...`)
|
||||
|
||||
const localDir = getLocalPath(channel)
|
||||
const remoteDir = getRemotePath(ROOT, channel, os)
|
||||
|
||||
const updateFileName = getUpdateFileName(os)
|
||||
const applicationFileNames = getApplicationFileNames(os, channel, packageJson.version)
|
||||
|
||||
console.log(`Files to upload: ${[updateFileName, ...applicationFileNames] .join (", ")}.`)
|
||||
|
||||
await run({ host: HOST, username: USERNAME, password: PASSWORD }, async client => {
|
||||
for (const applicationFileName of applicationFileNames) {
|
||||
await upload(client, localDir, remoteDir, applicationFileName)
|
||||
}
|
||||
|
||||
await upload(client, localDir, remoteDir, updateFileName)
|
||||
})
|
||||
|
||||
console.log(`Uploading files finished successfully.`)
|
||||
@@ -0,0 +1,12 @@
|
||||
// @ts-check
|
||||
import { join } from "path"
|
||||
|
||||
/**
|
||||
* @param {"prerelease" | "stable"} channel
|
||||
*/
|
||||
export const getLocalPath = channel => {
|
||||
switch (channel) {
|
||||
case "prerelease": return join("dist", "insider")
|
||||
case "stable": return join("dist")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// @ts-check
|
||||
import { notarize as electronNotarize } from 'electron-notarize'
|
||||
|
||||
/**
|
||||
* @param context {import("electron-builder").AfterPackContext}
|
||||
*/
|
||||
export const notarize = async (context) => {
|
||||
const { electronPlatformName, appOutDir } = context
|
||||
|
||||
if (electronPlatformName === 'darwin') {
|
||||
const appName = context.packager.appInfo.productFilename
|
||||
|
||||
console.log(`Notarizing "${appName}.app"...`)
|
||||
|
||||
await electronNotarize({
|
||||
tool: "notarytool",
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleId: /** @type {string} */ (process.env.APPLEID),
|
||||
appleIdPassword: /** @type {string} */ (process.env.APPLEIDPASS),
|
||||
teamId: /** @type {string} */ (process.env.TEAMID),
|
||||
})
|
||||
|
||||
console.log(`Notarization successful`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// @ts-check
|
||||
import { platform } from "os"
|
||||
|
||||
/**
|
||||
* @typedef {"win" | "mac" | "linux"} System
|
||||
* @returns {System}
|
||||
*/
|
||||
export const getSystem = () => {
|
||||
switch (platform()) {
|
||||
case "win32": return "win"
|
||||
case "darwin": return "mac"
|
||||
default: return "linux"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {System} system
|
||||
*/
|
||||
export const getSystemName = system => {
|
||||
switch (system) {
|
||||
case "win": return "Windows"
|
||||
case "mac": return "macOS"
|
||||
case "linux": return "Linux"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// @ts-check
|
||||
import { join } from "path"
|
||||
import { join as joinPosix } from "path/posix"
|
||||
import Client from "ssh2-sftp-client"
|
||||
|
||||
/**
|
||||
* @param {Client.ConnectOptions} options
|
||||
* @param {(client: Client) => Promise<void>} action
|
||||
*/
|
||||
export const run = async (options, action) => {
|
||||
const client = new Client()
|
||||
console.log("Connecting to server ...")
|
||||
await client.connect(options)
|
||||
console.log(`Server connection established.`)
|
||||
await action(client)
|
||||
await client.end ()
|
||||
console.log("Closed server connection.")
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Client} client
|
||||
* @param {string} localDir
|
||||
* @param {string} remoteDir
|
||||
* @param {string} fileName
|
||||
*/
|
||||
export const upload = async (client, localDir, remoteDir, fileName) => {
|
||||
console.log(`Uploading ${fileName} ...`);
|
||||
|
||||
await client.fastPut (
|
||||
join (localDir, fileName),
|
||||
joinPosix (remoteDir, fileName),
|
||||
{
|
||||
step: !process.env.CI ? (totalTransferred, _, total) => {
|
||||
const percent = Math.floor (totalTransferred / total * 100)
|
||||
console.log(`Progress: ${percent}%`);
|
||||
} : undefined
|
||||
}
|
||||
)
|
||||
|
||||
console.log(`Upload done: ${fileName}.`);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// @ts-check
|
||||
import { join } from "path/posix"
|
||||
|
||||
/**
|
||||
* @param {"prerelease" | "stable"} channel
|
||||
*/
|
||||
const remoteChannelPath = channel => {
|
||||
switch (channel) {
|
||||
case "prerelease": return "insider"
|
||||
case "stable": return "."
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./platform.mjs").System} os
|
||||
*/
|
||||
const remoteOsPath = os => {
|
||||
switch (os) {
|
||||
case "win": return "win"
|
||||
case "linux": return "linux"
|
||||
default: return "mac"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} root
|
||||
* @param {"prerelease" | "stable"} channel
|
||||
* @param {import("./platform.mjs").System} os
|
||||
*/
|
||||
export const getRemotePath = (root, channel, os) =>
|
||||
join(root, remoteChannelPath(channel), remoteOsPath(os))
|
||||
@@ -1,51 +0,0 @@
|
||||
// @ts-check
|
||||
import { join } from "path"
|
||||
import { join as joinPosix } from "path/posix"
|
||||
import Client from "ssh2-sftp-client"
|
||||
|
||||
/**
|
||||
* Create a new sftp/ssh client and use it for the callback. The connection will
|
||||
* be cleaned up afterwards.
|
||||
* @param {Client.ConnectOptions} options
|
||||
* @param {(client: Client) => Promise<void>} action
|
||||
*/
|
||||
export const run = async (options, action) => {
|
||||
const client = new Client()
|
||||
console.log("Connecting to server ...")
|
||||
await client.connect(options)
|
||||
console.log(`Server connection established.`)
|
||||
await action(client)
|
||||
await client.end()
|
||||
console.log("Closed server connection.")
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads a file from a local directory to a remote directory using the given
|
||||
* client.
|
||||
* @param {Client} client
|
||||
* @param {string} localDir
|
||||
* @param {string} remoteDir
|
||||
* @param {string} fileName
|
||||
*/
|
||||
export const upload = async (client, localDir, remoteDir, fileName) => {
|
||||
console.log(`Uploading ${fileName} ...`)
|
||||
|
||||
let didStep = false
|
||||
|
||||
await client.fastPut(join(localDir, fileName), joinPosix(remoteDir, fileName), {
|
||||
step: !process.env.CI
|
||||
? (totalTransferred, _, total) => {
|
||||
if (didStep) {
|
||||
process.stdout.clearLine(0)
|
||||
process.stdout.cursorTo(0)
|
||||
} else {
|
||||
didStep = true
|
||||
}
|
||||
const percent = Math.floor((totalTransferred / total) * 100)
|
||||
process.stdout.write(`Progress: ${percent}%`)
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
|
||||
console.log(`Upload done: ${fileName}`)
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
# `.icns` file from `.iconset` folder
|
||||
|
||||
```sh
|
||||
iconutil -c icns <PATH_TO_FOLDER>
|
||||
```
|
||||
|
||||
Make sure all of the following files are available. The tool is **case-sensitive**.
|
||||
|
||||
```
|
||||
icon_16.png
|
||||
icon_16@2x.png
|
||||
icon_32.png
|
||||
icon_32@2x.png
|
||||
icon_128.png
|
||||
icon_128@2x.png
|
||||
icon_256.png
|
||||
icon_256@2x.png
|
||||
icon_512.png
|
||||
icon_512@2x.png
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"appId": "com.lukasobermann.optolith",
|
||||
"productName": "Optolith",
|
||||
"directories": { "output": "dist" },
|
||||
"files": ["app/**/*", "LICENSE"],
|
||||
"npmRebuild": false,
|
||||
"mac": {
|
||||
"category": "public.app-category.role-playing-games",
|
||||
"icon": "app/icon.icns",
|
||||
"target": [
|
||||
{ "target": "dmg", "arch": ["arm64", "x64"] },
|
||||
{ "target": "zip", "arch": ["arm64", "x64"] }
|
||||
],
|
||||
"artifactName": "Optolith_${version}_${arch}.${ext}",
|
||||
"identity": null
|
||||
},
|
||||
"dmg": { "sign": false }
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"appId": "com.lukasobermann.optolith",
|
||||
"productName": "Optolith",
|
||||
"directories": {
|
||||
"output": "dist"
|
||||
},
|
||||
"files": [
|
||||
"app/**/*",
|
||||
"LICENSE"
|
||||
],
|
||||
"npmRebuild": false,
|
||||
"win": {
|
||||
"target": [
|
||||
{
|
||||
"target": "nsis",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"icon": "app/icon.ico",
|
||||
"artifactName": "OptolithSetup_${version}.${ext}"
|
||||
},
|
||||
"nsis": {
|
||||
"perMachine": false,
|
||||
"deleteAppDataOnUninstall": false
|
||||
},
|
||||
"linux": {
|
||||
"category": "RolePlaying",
|
||||
"executableName": "Optolith",
|
||||
"icon": "app",
|
||||
"target": [
|
||||
{
|
||||
"target": "AppImage",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "tar.gz",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"artifactName": "Optolith_${version}.${ext}"
|
||||
},
|
||||
"publish": null
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
// @ts-check
|
||||
import { FlatCompat } from "@eslint/eslintrc"
|
||||
import js from "@eslint/js"
|
||||
import eslintConfigPrettier from "eslint-config-prettier"
|
||||
import jsdoc from "eslint-plugin-jsdoc"
|
||||
import react from "eslint-plugin-react"
|
||||
import globals from "globals"
|
||||
import ts from "typescript-eslint"
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: import.meta.dirname,
|
||||
})
|
||||
|
||||
/** @type {import('eslint').Linter.Config[]} */
|
||||
export default [
|
||||
js.configs.recommended,
|
||||
react.configs.flat.recommended,
|
||||
react.configs.flat['jsx-runtime'],
|
||||
...compat.extends("plugin:react-hooks/recommended"),
|
||||
.../** @type {import('eslint').Linter.Config[]} */ (ts.configs.recommended),
|
||||
jsdoc.configs["flat/recommended-typescript-error"],
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.browser,
|
||||
},
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Possible problems
|
||||
"require-atomic-updates": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
|
||||
// Suggestions
|
||||
"accessor-pairs": "error",
|
||||
"arrow-body-style": "error",
|
||||
"class-methods-use-this": "warn",
|
||||
"default-case": "error",
|
||||
eqeqeq: "error",
|
||||
"guard-for-in": "error",
|
||||
"init-declarations": "error",
|
||||
"no-alert": "error",
|
||||
"no-caller": "error",
|
||||
"no-eval": "error",
|
||||
"no-extend-native": [
|
||||
2,
|
||||
{
|
||||
exceptions: ["Array", "Map", "Set"],
|
||||
},
|
||||
],
|
||||
"no-extra-bind": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-iterator": "error",
|
||||
"no-labels": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-multi-str": "error",
|
||||
"no-new": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-octal": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "error",
|
||||
"no-proto": "error",
|
||||
"no-redeclare": "off",
|
||||
"no-return-assign": "error",
|
||||
"no-script-url": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-useless-call": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-concat": "error",
|
||||
"no-useless-rename": "error",
|
||||
"no-useless-return": "error",
|
||||
"no-var": "error",
|
||||
"no-void": "error",
|
||||
"no-warning-comments": "error",
|
||||
"object-shorthand": "error",
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-const": "error",
|
||||
"prefer-destructuring": [
|
||||
2,
|
||||
{
|
||||
VariableDeclarator: {
|
||||
array: true,
|
||||
object: true,
|
||||
},
|
||||
AssignmentExpression: {
|
||||
array: false,
|
||||
object: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
"prefer-named-capture-group": "warn",
|
||||
"prefer-numeric-literals": "error",
|
||||
"prefer-object-has-own": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "error",
|
||||
radix: "error",
|
||||
"require-unicode-regexp": "error",
|
||||
"symbol-description": "error",
|
||||
yoda: "error",
|
||||
|
||||
// TypeScript
|
||||
"@typescript-eslint/adjacent-overload-signatures": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/consistent-type-assertions": "error",
|
||||
"@typescript-eslint/member-delimiter-style": [
|
||||
2,
|
||||
{
|
||||
multiline: {
|
||||
delimiter: "none",
|
||||
},
|
||||
singleline: {
|
||||
delimiter: "semi",
|
||||
requireLast: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{
|
||||
selector: "interface",
|
||||
format: ["PascalCase"],
|
||||
custom: {
|
||||
regex: "^I[A-Z]",
|
||||
match: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-redeclare": "error",
|
||||
"@typescript-eslint/no-shadow": [
|
||||
"error",
|
||||
{
|
||||
ignoreTypeValueShadow: true,
|
||||
}
|
||||
],
|
||||
"no-unused-expressions": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-expressions": "error",
|
||||
"@typescript-eslint/no-use-before-define": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/prefer-for-of": "error",
|
||||
"@typescript-eslint/prefer-readonly": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
"@typescript-eslint/strict-boolean-expressions": "error",
|
||||
"@typescript-eslint/switch-exhaustiveness-check": "error",
|
||||
|
||||
// React
|
||||
"react/boolean-prop-naming": "error",
|
||||
"react/destructuring-assignment": "error",
|
||||
"react/no-access-state-in-setstate": "error",
|
||||
"react/no-array-index-key": "error",
|
||||
"react/no-children-prop": "error",
|
||||
"react/no-danger": "error",
|
||||
"react/no-danger-with-children": "error",
|
||||
"react/no-deprecated": "error",
|
||||
"react/no-did-mount-set-state": "error",
|
||||
"react/no-did-update-set-state": "warn",
|
||||
"react/no-direct-mutation-state": "error",
|
||||
"react/no-find-dom-node": "error",
|
||||
"react/no-is-mounted": "error",
|
||||
"react/no-redundant-should-component-update": "error",
|
||||
"react/no-render-return-value": "error",
|
||||
"react/no-typos": "error",
|
||||
"react/no-string-refs": "error",
|
||||
"react/no-this-in-sfc": "error",
|
||||
"react/no-unescaped-entities": "error",
|
||||
"react/no-unsafe": "error",
|
||||
"react/no-unused-prop-types": "error",
|
||||
"react/no-unused-state": "error",
|
||||
"react/no-will-update-set-state": "error",
|
||||
"react/prefer-es6-class": "error",
|
||||
"react/prefer-stateless-function": "error",
|
||||
"react/prop-types": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react/require-render-return": "error",
|
||||
"react/self-closing-comp": "error",
|
||||
"react/state-in-constructor": [2, "never"],
|
||||
"react/style-prop-object": "error",
|
||||
"react/void-dom-elements-no-children": "error",
|
||||
"react/jsx-boolean-value": [2, "never"],
|
||||
"react/jsx-child-element-spacing": "error",
|
||||
"react/jsx-closing-tag-location": "error",
|
||||
"react/jsx-curly-newline": "error",
|
||||
"react/jsx-curly-spacing": "error",
|
||||
"react/jsx-equals-spacing": "error",
|
||||
"react/jsx-first-prop-new-line": "error",
|
||||
"react/jsx-indent-props": [2, 2],
|
||||
"react/jsx-no-bind": "error",
|
||||
"react/jsx-no-comment-textnodes": "error",
|
||||
"react/jsx-no-literals": "error",
|
||||
"react/jsx-no-target-blank": "error",
|
||||
"react/jsx-one-expression-per-line": [
|
||||
2,
|
||||
{
|
||||
allow: "single-child",
|
||||
},
|
||||
],
|
||||
"react/jsx-curly-brace-presence": [
|
||||
2,
|
||||
{
|
||||
props: "never",
|
||||
children: "ignore",
|
||||
},
|
||||
],
|
||||
"react/jsx-fragments": "error",
|
||||
"react/jsx-pascal-case": "error",
|
||||
"react/jsx-props-no-multi-spaces": "error",
|
||||
"react/jsx-props-no-spreading": "error",
|
||||
"react/jsx-tag-spacing": "error",
|
||||
"react/jsx-wrap-multilines": [
|
||||
2,
|
||||
{
|
||||
declaration: "parens-new-line",
|
||||
assignment: "parens-new-line",
|
||||
return: "parens-new-line",
|
||||
arrow: "parens-new-line",
|
||||
condition: "parens-new-line",
|
||||
logical: "parens-new-line",
|
||||
prop: "ignore",
|
||||
},
|
||||
],
|
||||
|
||||
// React Hooks
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "error",
|
||||
|
||||
// JSDoc
|
||||
"jsdoc/check-tag-names": [
|
||||
"error",
|
||||
{
|
||||
definedTags: ["main", "integer", "minItems"],
|
||||
},
|
||||
],
|
||||
"jsdoc/require-jsdoc": [
|
||||
"error",
|
||||
{
|
||||
contexts: [
|
||||
"TSInterfaceDeclaration",
|
||||
"TSMethodSignature",
|
||||
"TSEnumDeclaration",
|
||||
"TSTypeAliasDeclaration",
|
||||
"ExportNamedDeclaration > VariableDeclaration",
|
||||
],
|
||||
publicOnly: true,
|
||||
require: {
|
||||
ArrowFunctionExpression: true,
|
||||
ClassDeclaration: true,
|
||||
ClassExpression: true,
|
||||
FunctionDeclaration: true,
|
||||
FunctionExpression: true,
|
||||
MethodDefinition: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"jsdoc/require-param": "off",
|
||||
"jsdoc/require-returns": "off",
|
||||
"jsdoc/require-description": [
|
||||
"error",
|
||||
{
|
||||
contexts: [
|
||||
"any",
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
},
|
||||
eslintConfigPrettier,
|
||||
{
|
||||
ignores: [
|
||||
".webpack/**",
|
||||
"*.config.js",
|
||||
"deploy/**",
|
||||
"src/App/**",
|
||||
"src/Control/**",
|
||||
"src/Data/**",
|
||||
"src/Debug/**",
|
||||
"src/System/**",
|
||||
"src/database/contents/**",
|
||||
],
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
// @ts-check
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
globals: {
|
||||
"ts-jest": {
|
||||
tsconfig: "tsconfig.test.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// @ts-check
|
||||
import { join } from "node:path"
|
||||
import { jsonSchema } from "optolith-tsjsonschemamd/renderers"
|
||||
|
||||
/** @type {import("optolith-tsjsonschemamd").GeneratorOptions} */
|
||||
export default {
|
||||
sourceDir: join("src", "shared", "schema"),
|
||||
outputs: [
|
||||
{
|
||||
targetDir: join("src", "assets", "schema"),
|
||||
renderer: jsonSchema({ spec: "Draft_07" }),
|
||||
}
|
||||
],
|
||||
clean: true,
|
||||
verbose: false
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "optolith",
|
||||
"productName": "Optolith",
|
||||
"version": "2.0.0-alpha.1",
|
||||
"version": "1.6.0",
|
||||
"description": "A generator for heroes for the P&P-RPG 'The Dark Eye'.",
|
||||
"author": {
|
||||
"name": "Lukas Obermann",
|
||||
@@ -9,82 +9,98 @@
|
||||
},
|
||||
"homepage": "https://optolith.app",
|
||||
"license": "MPL-2.0",
|
||||
"main": ".webpack/main.cjs",
|
||||
"main": "app/main.js",
|
||||
"dependencies": {
|
||||
"@optolith/entity-descriptions": "^0.2.1",
|
||||
"@reduxjs/toolkit": "^2.2.7",
|
||||
"adm-zip": "^0.5.16",
|
||||
"debug": "^4.3.7",
|
||||
"electron-updater": "^6.3.9",
|
||||
"@electron/remote": "^2.0.8",
|
||||
"adm-zip": "^0.5.1",
|
||||
"ajv": "6.12.6",
|
||||
"electron-devtools-installer": "^3.2.1",
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-updater": "^5.0.5",
|
||||
"electron-window-state": "5.0.3",
|
||||
"immer": "^10.1.1",
|
||||
"moment": "^2.30.1",
|
||||
"moment": "^2.29.4",
|
||||
"mousetrap": "1.6.5",
|
||||
"optolith-character-schema": "^0.0.3",
|
||||
"optolith-database-schema": "^0.17.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-redux": "^9.1.2",
|
||||
"rehype-raw": "^7.0.0",
|
||||
"remark-breaks": "^4.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"semver": "^7.5.4"
|
||||
"react": "16.13.1",
|
||||
"react-custom-scrollbars": "4.2.1",
|
||||
"react-dom": "16.13.1",
|
||||
"react-markdown": "^8.0.0",
|
||||
"react-portal": "4.2.1",
|
||||
"react-redux": "7.2.1",
|
||||
"react-textfit": "1.1.0",
|
||||
"redux": "4.0.5",
|
||||
"redux-devtools-extension": "2.13.8",
|
||||
"redux-thunk": "2.3.0",
|
||||
"rehype-raw": "^5.1.0",
|
||||
"remark-breaks": "^2.0.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"reselect": "4.0.0",
|
||||
"semver": "7.3.2",
|
||||
"tslib": "^2.3.1",
|
||||
"yaml": "1.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron/notarize": "^2.5.0",
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.11.1",
|
||||
"@rspack/cli": "^1.0.8",
|
||||
"@rspack/core": "^1.0.8",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@types/node": "^22.7.4",
|
||||
"@types/react": "^18.3.11",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-redux": "^7.1.34",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/ssh2-sftp-client": "^9.0.4",
|
||||
"css-loader": "^7.1.2",
|
||||
"electron": "^32.1.2",
|
||||
"electron-builder": "^25.1.7",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-jsdoc": "^50.3.1",
|
||||
"eslint-plugin-react": "^7.37.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-tsdoc": "^0.3.0",
|
||||
"glob": "^11.0.0",
|
||||
"globals": "^15.10.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"optolith-tsjsonschemamd": "^0.10.7",
|
||||
"resolve-url-loader": "^5.0.0",
|
||||
"sass": "^1.79.4",
|
||||
"sass-loader": "^16.0.2",
|
||||
"ssh2-sftp-client": "^11.0.0",
|
||||
"standard-version": "^9.5.0",
|
||||
"tsx": "^4.19.1",
|
||||
"typescript": "^5.6.2",
|
||||
"typescript-eslint": "^8.8.0"
|
||||
"@commitlint/cli": "11.0.0",
|
||||
"@commitlint/config-conventional": "11.0.0",
|
||||
"@types/classnames": "2.2.11",
|
||||
"@types/jest": "26.0.15",
|
||||
"@types/mousetrap": "1.6.4",
|
||||
"@types/node": "14.14.7",
|
||||
"@types/react": "16.9.56",
|
||||
"@types/react-custom-scrollbars": "4.0.7",
|
||||
"@types/react-dom": "16.9.9",
|
||||
"@types/react-portal": "4.0.2",
|
||||
"@types/react-redux": "7.1.11",
|
||||
"@types/semver": "7.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||
"@typescript-eslint/parser": "^5.10.0",
|
||||
"custom-env": "2.0.1",
|
||||
"dotenv": "8.2.0",
|
||||
"electron": "^19.0.8",
|
||||
"electron-builder": "^23.1.0",
|
||||
"electron-notarize": "^1.2.1",
|
||||
"eslint": "^8.7.0",
|
||||
"eslint-plugin-react": "^7.28.0",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"eslint-plugin-tsdoc": "^0.2.14",
|
||||
"fs-extra": "9.0.1",
|
||||
"gentype": "3.38.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"husky": "^4.3.8",
|
||||
"jest": "^26.6.3",
|
||||
"sass": "1.29.0",
|
||||
"ssh2-sftp-client": "^9.0.1",
|
||||
"standard-version": "^9.3.1",
|
||||
"ts-jest": "^26.5.6",
|
||||
"ts-loader": "^9.2.6",
|
||||
"typescript": "^4.5.5",
|
||||
"webpack": "^5.67.0",
|
||||
"webpack-cli": "^4.9.2"
|
||||
},
|
||||
"scripts": {
|
||||
"prerelease:win": "set NODE_ENV=development && node ./build/build.js --win --prerelease",
|
||||
"prerelease:linux": "NODE_ENV=development node -r dotenv/config ./build/build.js --linux --prerelease",
|
||||
"prerelease:mac": "NODE_ENV=development node ./build/build.js --mac --prerelease",
|
||||
"stable:win": "set NODE_ENV=production && node ./build/build.js --win --stable",
|
||||
"stable:linux": "NODE_ENV=production node ./build/build.js --linux --stable",
|
||||
"stable:mac": "NODE_ENV=production node ./build/build.js --mac --stable",
|
||||
"js:build": "rspack build",
|
||||
"js:watch": "rspack build -w",
|
||||
"prerelease:win": "set NODE_ENV=development && node ./deploy/buildInsiderWin.js",
|
||||
"prerelease:linux": "NODE_ENV=development node -r dotenv/config ./deploy/buildInsiderLinux.js",
|
||||
"prerelease:mac": "NODE_ENV=development node ./deploy/buildInsiderMac.js",
|
||||
"stable:win": "set NODE_ENV=production && node ./deploy/buildWin.js",
|
||||
"stable:linux": "NODE_ENV=production node ./deploy/buildLinux.js",
|
||||
"stable:mac": "NODE_ENV=production node ./deploy/buildMac.js",
|
||||
"css:build": "sass --style=compressed src/Main.scss app/main.css",
|
||||
"css:watch": "sass --watch --style=compressed src/Main.scss app/main.css",
|
||||
"build": "npm run ts:build && npm run css:build && npm run js:build",
|
||||
"js:build": "webpack",
|
||||
"js:watch": "webpack -w",
|
||||
"ts:build": "tsc",
|
||||
"ts:watch": "tsc -w",
|
||||
"createschemas": "otjsmd",
|
||||
"lint": "eslint \"src/**\"",
|
||||
"start": "electron --js-flags='--stack-size=5000' .",
|
||||
"test": "glob -c \"node --import tsx --test\" \"./src/shared/**/*.test.ts\"",
|
||||
"lint": "eslint \"src/\" --ext \".ts\" --ext \".tsx\"",
|
||||
"start": "electron .",
|
||||
"test": "jest",
|
||||
"circ": "madge -c ./src",
|
||||
"release:main": "standard-version --skip.commit --skip.tag",
|
||||
"release:pre": "standard-version --prerelease=alpha",
|
||||
"buildicns": "iconutil -c icns src/assets/icon/AppIcon.iconset && iconutil -c icns src/assets/icon/AppIcon.pre.iconset"
|
||||
"release:pre": "standard-version --prerelease=alpha"
|
||||
},
|
||||
"repository": "github:elyukai/optolith-client",
|
||||
"type": "module"
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
import { resolve } from "node:path"
|
||||
import { getOptimization } from "./rspack.optimization.js"
|
||||
import { rendererPlugins } from "./rspack.plugins.js"
|
||||
import { rules } from "./rspack.rules.js"
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {EnvironmentMode} mode
|
||||
* @returns {import("@rspack/core").Configuration[]}
|
||||
*/
|
||||
const createRendererConfig = (name, mode) => [
|
||||
{
|
||||
name: `renderer_${name}`,
|
||||
mode,
|
||||
entry: {
|
||||
[`renderer_${name}`]: `./src/${name}_window/index.tsx`,
|
||||
},
|
||||
target: "electron-renderer",
|
||||
optimization: getOptimization(`renderer_${name}`),
|
||||
module: {
|
||||
rules: rules,
|
||||
},
|
||||
resolve: {
|
||||
symlinks: false,
|
||||
conditionNames: ["browser", "default", "import", "require"],
|
||||
},
|
||||
output: {
|
||||
path: resolve(import.meta.dirname, ".webpack"),
|
||||
filename: "[name].js",
|
||||
globalObject: "globalThis",
|
||||
},
|
||||
plugins: rendererPlugins(mode),
|
||||
externals: {
|
||||
"electron/renderer": "commonjs electron/renderer",
|
||||
"electron/common": "commonjs electron/common",
|
||||
},
|
||||
externalsPresets: {
|
||||
electronRenderer: true,
|
||||
},
|
||||
profile: true,
|
||||
devtool: "source-map",
|
||||
},
|
||||
{
|
||||
name: `renderer_${name}_preload`,
|
||||
mode,
|
||||
entry: {
|
||||
[`renderer_${name}_preload`]: `./src/${name}_window_preload/index.ts`,
|
||||
},
|
||||
target: "electron-preload",
|
||||
module: {
|
||||
rules: rules,
|
||||
},
|
||||
resolve: {
|
||||
symlinks: false,
|
||||
},
|
||||
output: {
|
||||
path: resolve(import.meta.dirname, ".webpack"),
|
||||
filename: "[name].cjs",
|
||||
},
|
||||
externals: {
|
||||
"electron/renderer": "commonjs electron/renderer",
|
||||
"electron/common": "commonjs electron/common",
|
||||
},
|
||||
externalsPresets: {
|
||||
electronPreload: true,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* @typedef {"development" | "production"} EnvironmentMode
|
||||
* @returns {import("@rspack/core").Configuration[]}
|
||||
*/
|
||||
export default () => {
|
||||
/** @type {EnvironmentMode} */
|
||||
const mode = process.env.NODE_ENV === "production" ? "production" : "development"
|
||||
|
||||
return [
|
||||
{
|
||||
name: "main",
|
||||
mode,
|
||||
entry: {
|
||||
main: "./src/main/index.ts",
|
||||
},
|
||||
target: "electron-main",
|
||||
optimization: getOptimization("main"),
|
||||
module: {
|
||||
rules: rules,
|
||||
},
|
||||
resolve: {
|
||||
symlinks: false,
|
||||
},
|
||||
output: {
|
||||
path: resolve(import.meta.dirname, ".webpack"),
|
||||
filename: "[name].cjs",
|
||||
},
|
||||
externals: {
|
||||
"electron/main": "commonjs electron/main",
|
||||
"electron/common": "commonjs electron/common",
|
||||
},
|
||||
externalsPresets: {
|
||||
electronMain: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "database",
|
||||
mode,
|
||||
entry: {
|
||||
database: "./src/database/index.ts",
|
||||
},
|
||||
target: "electron-main",
|
||||
optimization: getOptimization("database"),
|
||||
module: {
|
||||
rules: rules,
|
||||
},
|
||||
resolve: {
|
||||
symlinks: false,
|
||||
},
|
||||
output: {
|
||||
path: resolve(import.meta.dirname, ".webpack"),
|
||||
filename: "[name].cjs",
|
||||
},
|
||||
externalsPresets: {
|
||||
electronMain: true,
|
||||
},
|
||||
externals: {
|
||||
"optolith-database-schema": "module optolith-database-schema",
|
||||
},
|
||||
},
|
||||
...createRendererConfig("main", mode),
|
||||
...createRendererConfig("updater", mode),
|
||||
...createRendererConfig("settings", mode),
|
||||
]
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* @param {string} processType
|
||||
* @returns {import("@rspack/core").Configuration["optimization"]}
|
||||
*/
|
||||
export const getOptimization = (processType) => ({
|
||||
splitChunks: {
|
||||
chunks: "all",
|
||||
cacheGroups: {
|
||||
default: {
|
||||
name: processType,
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
},
|
||||
defaultVendors: {
|
||||
name: `${processType}_vendors`,
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -1,20 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
import rspack from "@rspack/core"
|
||||
import HtmlWebpackPlugin from "html-webpack-plugin"
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("./rspack.config.js").EnvironmentMode} mode
|
||||
* @returns {import("@rspack/core").Configuration["plugins"]}
|
||||
*/
|
||||
export const rendererPlugins = (mode) => [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "[name].html",
|
||||
template: "./src/template.html",
|
||||
}),
|
||||
new rspack.CssExtractRspackPlugin({
|
||||
filename: `assets/css/${mode === "development" ? "[name].css" : "[name].[hash].css"}`,
|
||||
chunkFilename: `assets/css/${mode === "development" ? "[id].css" : "[id].[hash].css"}`,
|
||||
}),
|
||||
]
|
||||
@@ -1,73 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
import rspack from "@rspack/core"
|
||||
|
||||
/**
|
||||
* @type {Required<import("@rspack/core").ModuleOptions>["rules"]}
|
||||
*/
|
||||
export const rules = [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: "builtin:swc-loader",
|
||||
resolve: {
|
||||
extensionAlias: {
|
||||
'.js': ['.tsx', '.ts', 'jsx', '.js'],
|
||||
},
|
||||
},
|
||||
options: {
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
},
|
||||
transform: {
|
||||
react: {
|
||||
runtime: 'automatic',
|
||||
throwIfNamespace: true,
|
||||
useBuiltins: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'javascript/auto',
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|svg)$/i,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: "assets/images/[name].[hash][ext][query]",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(icns|ico)$/i,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: "assets/icons/[name].[hash][ext][query]",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|otf|woff2?)$/i,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: "assets/fonts/[name].[hash][ext][query]",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(css|sass|scss)$/,
|
||||
use: [
|
||||
rspack.CssExtractRspackPlugin.loader,
|
||||
"css-loader",
|
||||
"resolve-url-loader",
|
||||
{
|
||||
loader: "sass-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
generator: {
|
||||
filename: "assets/css/[name].[hash][ext][query]",
|
||||
},
|
||||
type: "javascript/auto",
|
||||
},
|
||||
]
|
||||
@@ -1,18 +1,11 @@
|
||||
import { Action, UnknownAction } from "redux"
|
||||
import { Action, AnyAction } from "redux"
|
||||
import { ThunkAction, ThunkDispatch } from "redux-thunk"
|
||||
import { AppStateRecord } from "../Models/AppState"
|
||||
|
||||
export type ReduxAction<R = void, D extends Action = UnknownAction> = ThunkAction<
|
||||
R,
|
||||
AppStateRecord,
|
||||
undefined,
|
||||
D
|
||||
>
|
||||
export type ReduxAction<R = void, D extends Action = AnyAction> =
|
||||
ThunkAction<R, AppStateRecord, undefined, D>
|
||||
|
||||
export type ReduxActions<R = void, D extends Action = UnknownAction> = ReduxAction<R, D> | D
|
||||
export type ReduxActions<R = void, D extends Action = AnyAction> = ReduxAction<R, D> | D
|
||||
|
||||
export type ReduxDispatch<A extends Action = UnknownAction> = ThunkDispatch<
|
||||
AppStateRecord,
|
||||
undefined,
|
||||
A
|
||||
>
|
||||
export type ReduxDispatch<A extends Action = AnyAction> =
|
||||
ThunkDispatch<AppStateRecord, undefined, A>
|
||||
|
||||
@@ -34,6 +34,7 @@ import { translate, translateP } from "../Utilities/I18n"
|
||||
import { pipe, pipe_ } from "../Utilities/pipe"
|
||||
import { misNumberM } from "../Utilities/typeCheckUtils"
|
||||
import { getWikiEntry } from "../Utilities/WikiUtils"
|
||||
import { WikiInfoSelector } from "../Views/InlineWiki/WikiInfo"
|
||||
import { ReduxAction, ReduxDispatch } from "./Actions"
|
||||
import { addAlert, addNotEnoughAPAlert, AlertOptions } from "./AlertActions"
|
||||
|
||||
@@ -466,6 +467,14 @@ export const switchRatingVisibility = (): SwitchDisAdvRatingVisibilityAction =>
|
||||
type: ActionTypes.SWITCH_DISADV_RATING_VISIBILITY,
|
||||
})
|
||||
|
||||
export const setRule = (selector: WikiInfoSelector, rule: string): SaveRuleAction => ({
|
||||
type: ActionTypes.SET_CUSTOM_RULE,
|
||||
payload: {
|
||||
rule,
|
||||
selector,
|
||||
},
|
||||
})
|
||||
|
||||
export interface SetActiveAdvantagesFilterTextAction {
|
||||
type: ActionTypes.SET_ADVANTAGES_FILTER_TEXT
|
||||
payload: {
|
||||
@@ -525,3 +534,11 @@ export const setInactiveDisadvantagesFilterText =
|
||||
filterText,
|
||||
},
|
||||
})
|
||||
|
||||
export interface SaveRuleAction {
|
||||
type: ActionTypes.SET_CUSTOM_RULE
|
||||
payload: {
|
||||
rule: string
|
||||
selector: WikiInfoSelector
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ export const requestConfigSave: ReduxAction<Promise<boolean>> =
|
||||
Just (UISSA.sheetCheckAttributeValueVisibility (uiSettingsState)),
|
||||
sheetUseParchment:
|
||||
Just (UISSA.sheetUseParchment (uiSettingsState)),
|
||||
sheetShowRules:
|
||||
Just (UISSA.sheetShowRules (uiSettingsState)),
|
||||
sheetZoomFactor:
|
||||
UISSA.sheetZoomFactor (uiSettingsState),
|
||||
theme: Just (UISSA.theme (uiSettingsState)),
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { SWITCH_SHEET_ATTR_VALUE_VISIBILITY, SWITCH_SHEET_USE_PARCHMENT, SET_SHEET_ZOOM_FACTOR } from "../Constants/ActionTypes"
|
||||
import {
|
||||
SWITCH_SHEET_ATTR_VALUE_VISIBILITY,
|
||||
SWITCH_SHEET_USE_PARCHMENT,
|
||||
SET_SHEET_ZOOM_FACTOR,
|
||||
SWITCH_SHEET_SHOW_RULES
|
||||
} from "../Constants/ActionTypes"
|
||||
|
||||
export interface SwitchSheetAttributeValueVisibilityAction {
|
||||
type: SWITCH_SHEET_ATTR_VALUE_VISIBILITY
|
||||
@@ -16,6 +21,13 @@ export const switchUseParchment = (): SwitchSheetUseParchmentAction => ({
|
||||
type: SWITCH_SHEET_USE_PARCHMENT,
|
||||
})
|
||||
|
||||
export interface SwitchSheetShowRules {
|
||||
type: SWITCH_SHEET_SHOW_RULES
|
||||
}
|
||||
export const switchShowRules = (): SwitchSheetShowRules => ({
|
||||
type: SWITCH_SHEET_SHOW_RULES,
|
||||
})
|
||||
|
||||
export interface SetSheetZoomFactor {
|
||||
type: SET_SHEET_ZOOM_FACTOR
|
||||
payload: {
|
||||
|
||||
@@ -321,6 +321,9 @@ export type SET_DISADV_TIER = "SET_DISADV_TIER"
|
||||
export const SWITCH_DISADV_RATING_VISIBILITY = "SWITCH_DISADV_RATING_VISIBILITY"
|
||||
export type SWITCH_DISADV_RATING_VISIBILITY = "SWITCH_DISADV_RATING_VISIBILITY"
|
||||
|
||||
export const SET_CUSTOM_RULE = "SET_CUSTOM_RULE"
|
||||
export type SET_CUSTOM_RULE = "SET_CUSTOM_RULE"
|
||||
|
||||
export const ADD_TALENT_POINT = "ADD_TALENT_POINT"
|
||||
export type ADD_TALENT_POINT = "ADD_TALENT_POINT"
|
||||
export const REMOVE_TALENT_POINT = "REMOVE_TALENT_POINT"
|
||||
@@ -615,6 +618,9 @@ export type SWITCH_SHEET_ATTR_VALUE_VISIBILITY = "SWITCH_SHEET_ATTR_VALUE_VISIBI
|
||||
export const SWITCH_SHEET_USE_PARCHMENT = "SWITCH_SHEET_USE_PARCHMENT"
|
||||
export type SWITCH_SHEET_USE_PARCHMENT = "SWITCH_SHEET_USE_PARCHMENT"
|
||||
|
||||
export const SWITCH_SHEET_SHOW_RULES = "SWITCH_SHEET_SHOW_RULES"
|
||||
export type SWITCH_SHEET_SHOW_RULES = "SWITCH_SHEET_SHOW_RULES"
|
||||
|
||||
export const SET_SHEET_ZOOM_FACTOR = "SET_SHEET_ZOOM_FACTOR"
|
||||
export type SET_SHEET_ZOOM_FACTOR = "SET_SHEET_ZOOM_FACTOR"
|
||||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
import { connect } from "react-redux"
|
||||
import { fromJust, isJust, Maybe } from "../../Data/Maybe"
|
||||
import { ReduxDispatch } from "../Actions/Actions"
|
||||
import * as AttributesActions from "../Actions/AttributesActions"
|
||||
import * as SubwindowsActions from "../Actions/SubwindowsActions"
|
||||
import { EnergyId } from "../Constants/Ids"
|
||||
import { AppStateRecord } from "../Models/AppState"
|
||||
import { getAdjustmentValue, getAttributesForView, getAttributeSum, getAvailableAdjustmentIds } from "../Selectors/attributeSelectors"
|
||||
import { getDerivedCharacteristics } from "../Selectors/derivedCharacteristicsSelectors"
|
||||
import { getMaxTotalAttributeValues } from "../Selectors/elSelectors"
|
||||
import { getIsInCharacterCreation, getIsRemovingEnabled } from "../Selectors/phaseSelectors"
|
||||
import { getAddPermanentEnergy, getCurrentAttributeAdjustmentId, getEditPermanentEnergy } from "../Selectors/stateSelectors"
|
||||
import { Attributes, AttributesDispatchProps, AttributesOwnProps, AttributesStateProps } from "../Views/Attributes/Attributes"
|
||||
|
||||
const mapStateToProps =
|
||||
(state: AppStateRecord, ownProps: AttributesOwnProps): AttributesStateProps => ({
|
||||
adjustmentValue: getAdjustmentValue (state, ownProps),
|
||||
attributes: getAttributesForView (state, ownProps),
|
||||
availableAttributeIds: getAvailableAdjustmentIds (state, ownProps),
|
||||
currentAttributeId: getCurrentAttributeAdjustmentId (state),
|
||||
isInCharacterCreation: getIsInCharacterCreation (state),
|
||||
isRemovingEnabled: getIsRemovingEnabled (state),
|
||||
derived: getDerivedCharacteristics (state, ownProps),
|
||||
maxTotalAttributeValues: getMaxTotalAttributeValues (state),
|
||||
sum: getAttributeSum (state, ownProps),
|
||||
getEditPermanentEnergy: getEditPermanentEnergy (state),
|
||||
getAddPermanentEnergy: getAddPermanentEnergy (state),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch: ReduxDispatch): AttributesDispatchProps => ({
|
||||
addPoint: async (id: string) => {
|
||||
await dispatch (AttributesActions.addAttributePoint (id))
|
||||
},
|
||||
removePoint: (id: string) => {
|
||||
dispatch (AttributesActions.removeAttributePoint (id))
|
||||
},
|
||||
addLifePoint: async () => {
|
||||
await dispatch (AttributesActions.addLifePoint)
|
||||
},
|
||||
addArcaneEnergyPoint: async () => {
|
||||
await dispatch (AttributesActions.addArcaneEnergyPoint)
|
||||
},
|
||||
addKarmaPoint: async () => {
|
||||
await dispatch (AttributesActions.addKarmaPoint)
|
||||
},
|
||||
removeLifePoint: () => {
|
||||
dispatch (AttributesActions.removeLifePoint ())
|
||||
},
|
||||
removeArcaneEnergyPoint: () => {
|
||||
dispatch (AttributesActions.removeArcaneEnergyPoint ())
|
||||
},
|
||||
removeKarmaPoint: () => {
|
||||
dispatch (AttributesActions.removeKarmaPoint ())
|
||||
},
|
||||
addLostLPPoint: () => {
|
||||
dispatch (AttributesActions.addLostLPPoint ())
|
||||
},
|
||||
removeLostLPPoint: () => {
|
||||
dispatch (AttributesActions.removeLostLPPoint ())
|
||||
},
|
||||
addLostLPPoints: (value: number) => {
|
||||
dispatch (AttributesActions.addLostLPPoints (value))
|
||||
},
|
||||
addBoughtBackAEPoint: async () => {
|
||||
await dispatch (AttributesActions.addBoughtBackAEPoint)
|
||||
},
|
||||
removeBoughtBackAEPoint: () => {
|
||||
dispatch (AttributesActions.removeBoughtBackAEPoint ())
|
||||
},
|
||||
addLostAEPoint: () => {
|
||||
dispatch (AttributesActions.addLostAEPoint ())
|
||||
},
|
||||
removeLostAEPoint: () => {
|
||||
dispatch (AttributesActions.removeLostAEPoint ())
|
||||
},
|
||||
addLostAEPoints: (value: number) => {
|
||||
dispatch (AttributesActions.addLostAEPoints (value))
|
||||
},
|
||||
addBoughtBackKPPoint: async () => {
|
||||
await dispatch (AttributesActions.addBoughtBackKPPoint)
|
||||
},
|
||||
removeBoughtBackKPPoint: () => {
|
||||
dispatch (AttributesActions.removeBoughtBackKPPoint ())
|
||||
},
|
||||
addLostKPPoint: () => {
|
||||
dispatch (AttributesActions.addLostKPPoint ())
|
||||
},
|
||||
removeLostKPPoint: () => {
|
||||
dispatch (AttributesActions.removeLostKPPoint ())
|
||||
},
|
||||
addLostKPPoints: (value: number) => {
|
||||
dispatch (AttributesActions.addLostKPPoints (value))
|
||||
},
|
||||
openAddPermanentEnergyLoss: (energy: EnergyId) => {
|
||||
console.log (`openAddPermanentEnergyLoss (${energy})`)
|
||||
dispatch (SubwindowsActions.openAddPermanentEnergyLoss (energy))
|
||||
},
|
||||
closeAddPermanentEnergyLoss: () => {
|
||||
console.log (`closeAddPermanentEnergyLoss ()`)
|
||||
dispatch (SubwindowsActions.closeAddPermanentEnergyLoss ())
|
||||
},
|
||||
openEditPermanentEnergy: (energy: EnergyId) => {
|
||||
console.log (`openEditPermanentEnergy (${energy})`)
|
||||
dispatch (SubwindowsActions.openEditPermanentEnergy (energy))
|
||||
},
|
||||
closeEditPermanentEnergy: () => {
|
||||
console.log (`closeEditPermanentEnergy ()`)
|
||||
dispatch (SubwindowsActions.closeEditPermanentEnergy ())
|
||||
},
|
||||
setAdjustmentId: (id: Maybe<string>) => {
|
||||
if (isJust (id)) {
|
||||
dispatch (AttributesActions.setAdjustmentId (fromJust (id)))
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const connectAttributes =
|
||||
connect<AttributesStateProps, AttributesDispatchProps, AttributesOwnProps, AppStateRecord> (
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)
|
||||
|
||||
export const AttributesContainer = connectAttributes (Attributes)
|
||||
@@ -0,0 +1,50 @@
|
||||
import { connect } from "react-redux"
|
||||
import { ReduxDispatch } from "../Actions/Actions"
|
||||
import * as CombatTechniquesActions from "../Actions/CombatTechniquesActions"
|
||||
import { AppStateRecord } from "../Models/AppState"
|
||||
import { CombatTechniquesSortOptions } from "../Models/Config"
|
||||
import { getAttributesForSheet } from "../Selectors/attributeSelectors"
|
||||
import { getFilteredCombatTechniques } from "../Selectors/combatTechniquesSelectors"
|
||||
import { getIsRemovingEnabled } from "../Selectors/phaseSelectors"
|
||||
import { getCombatTechniquesFilterText } from "../Selectors/stateSelectors"
|
||||
import { getCombatTechniquesSortOrder } from "../Selectors/uisettingsSelectors"
|
||||
import { CombatTechniques, CombatTechniquesDispatchProps, CombatTechniquesOwnProps, CombatTechniquesStateProps } from "../Views/CombatTechniques/CombatTechniques"
|
||||
|
||||
const mapStateToProps = (
|
||||
state: AppStateRecord,
|
||||
ownProps: CombatTechniquesOwnProps
|
||||
): CombatTechniquesStateProps => ({
|
||||
attributes: getAttributesForSheet (state, ownProps),
|
||||
isRemovingEnabled: getIsRemovingEnabled (state),
|
||||
list: getFilteredCombatTechniques (state, ownProps),
|
||||
sortOrder: getCombatTechniquesSortOrder (state),
|
||||
filterText: getCombatTechniquesFilterText (state),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch: ReduxDispatch) => ({
|
||||
async addPoint (id: string) {
|
||||
await dispatch (CombatTechniquesActions.addCombatTechniquePoint (id))
|
||||
},
|
||||
removePoint (id: string) {
|
||||
dispatch (CombatTechniquesActions.removeCombatTechniquePoint (id))
|
||||
},
|
||||
setSortOrder (sortOrder: CombatTechniquesSortOptions) {
|
||||
dispatch (CombatTechniquesActions.setCombatTechniquesSortOrder (sortOrder))
|
||||
},
|
||||
setFilterText (filterText: string) {
|
||||
dispatch (CombatTechniquesActions.setCombatTechniquesFilterText (filterText))
|
||||
},
|
||||
})
|
||||
|
||||
const connectCombatTechniques =
|
||||
connect<
|
||||
CombatTechniquesStateProps,
|
||||
CombatTechniquesDispatchProps,
|
||||
CombatTechniquesOwnProps,
|
||||
AppStateRecord
|
||||
> (
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)
|
||||
|
||||
export const CombatTechniquesContainer = connectCombatTechniques (CombatTechniques)
|
||||
@@ -0,0 +1,58 @@
|
||||
import { ipcRenderer } from "electron"
|
||||
import { connect } from "react-redux"
|
||||
import { fromJust, isJust, Maybe } from "../../Data/Maybe"
|
||||
import { ReduxDispatch } from "../Actions/Actions"
|
||||
import * as ConfigActions from "../Actions/ConfigActions"
|
||||
import * as FallbackLocaleActions from "../Actions/FallbackLocaleActions"
|
||||
import * as IOActions from "../Actions/IOActions"
|
||||
import * as LocaleActions from "../Actions/LocaleActions"
|
||||
import { AppStateRecord } from "../Models/AppState"
|
||||
import { Locale, Theme } from "../Models/Config"
|
||||
import { getUserSelectableSupportedLanguages } from "../Selectors/localeSelectors"
|
||||
import { getFallbackLocaleId, getFallbackLocaleType, getLocaleId, getLocaleType } from "../Selectors/stateSelectors"
|
||||
import { areAnimationsEnabled, getIsEditingHeroAfterCreationPhaseEnabled, getTheme } from "../Selectors/uisettingsSelectors"
|
||||
import { IPCChannels } from "../Utilities/IPCChannels"
|
||||
import { Settings, SettingsDispatchProps, SettingsOwnProps, SettingsStateProps } from "../Views/Settings/Settings"
|
||||
|
||||
const mapStateToProps = (state: AppStateRecord): SettingsStateProps => ({
|
||||
localeString: getLocaleId (state),
|
||||
localeType: getLocaleType (state),
|
||||
fallbackLocaleString: getFallbackLocaleId (state),
|
||||
fallbackLocaleType: getFallbackLocaleType (state),
|
||||
isEditingHeroAfterCreationPhaseEnabled: getIsEditingHeroAfterCreationPhaseEnabled (state),
|
||||
areAnimationsEnabled: areAnimationsEnabled (state),
|
||||
theme: getTheme (state),
|
||||
languages: getUserSelectableSupportedLanguages (state),
|
||||
isCheckForUpdatesDisabled: !(ipcRenderer.sendSync (IPCChannels.IsUpdaterEnabled) as boolean),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch: ReduxDispatch): SettingsDispatchProps => ({
|
||||
setTheme (theme: Maybe<Theme>) {
|
||||
if (isJust (theme)) {
|
||||
dispatch (ConfigActions.setTheme (fromJust (theme)))
|
||||
}
|
||||
},
|
||||
switchEnableEditingHeroAfterCreationPhase () {
|
||||
dispatch (ConfigActions.switchEnableEditingHeroAfterCreationPhase ())
|
||||
},
|
||||
async saveConfig () {
|
||||
await dispatch (IOActions.requestConfigSave)
|
||||
},
|
||||
setLocale (id: Maybe<Locale>) {
|
||||
dispatch (LocaleActions.setLocale (id))
|
||||
},
|
||||
setFallbackLocale (id: Maybe<Locale>) {
|
||||
dispatch (FallbackLocaleActions.setFallbackLocale (id))
|
||||
},
|
||||
switchEnableAnimations () {
|
||||
dispatch (ConfigActions.switchEnableAnimations ())
|
||||
},
|
||||
})
|
||||
|
||||
const connectSettings =
|
||||
connect<SettingsStateProps, SettingsDispatchProps, SettingsOwnProps, AppStateRecord> (
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)
|
||||
|
||||
export const SettingsContainer = connectSettings (Settings)
|
||||