initial release
This commit is contained in:
commit
d88d61bb3b
0
.env.build.testing
Normal file
0
.env.build.testing
Normal file
1
.env.development
Normal file
1
.env.development
Normal file
@ -0,0 +1 @@
|
|||||||
|
NEXT_PUBLIC_HOST=http://127.0.0.1:3000
|
||||||
2
.env.production
Normal file
2
.env.production
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
NEXT_PUBLIC_HOST=https://dmscreen.silas.link
|
||||||
|
SOCKET_TIMEOUT=10000
|
||||||
3
.env.testing
Normal file
3
.env.testing
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SOCKET_TIMEOUT=400
|
||||||
|
SOCKET_POLLING=1
|
||||||
|
|
||||||
310
.eslintrc.json
Normal file
310
.eslintrc.json
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"airbnb",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"prettier",
|
||||||
|
"prettier/prettier",
|
||||||
|
"plugin:import/typescript"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"experimentalObjectRestSpread": true,
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": 9,
|
||||||
|
"sourceType": "module",
|
||||||
|
"project": "./tsconfig.json",
|
||||||
|
"tsconfigRootDir": "./"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react",
|
||||||
|
"@typescript-eslint",
|
||||||
|
"react-hooks",
|
||||||
|
"sort-imports-es6-autofix",
|
||||||
|
"no-relative-import-paths"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"react/jsx-uses-react": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"react/jsx-uses-vars": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"react-hooks/rules-of-hooks": "error",
|
||||||
|
// Checks rules of Hooks
|
||||||
|
"react-hooks/exhaustive-deps": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"additionalHooks": "(useToolHandler|useOnDemandFrame|useAbort|useSecondaryButtonClicked|useAnimatedSpring|useHotkeyDown|useHotkey|useEvent|useServerUpdate)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// Checks effect dependencies
|
||||||
|
"jsx-a11y/no-static-element-interactions": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"sort-imports-es6-autofix/sort-imports-es6": [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
"ignoreCase": false,
|
||||||
|
"ignoreMemberSort": false,
|
||||||
|
"memberSyntaxSortOrder": [
|
||||||
|
"none",
|
||||||
|
"all",
|
||||||
|
"multiple",
|
||||||
|
"single"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-relative-import-paths/no-relative-import-paths": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"allowSameFolder": false,
|
||||||
|
"rootDir": "src",
|
||||||
|
"prefix": "@"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"react/jsx-filename-extension": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"extensions": [
|
||||||
|
".tsx"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"import/extensions": [
|
||||||
|
"error",
|
||||||
|
"ignorePackages",
|
||||||
|
{
|
||||||
|
"js": "never",
|
||||||
|
"jsx": "never",
|
||||||
|
"ts": "never",
|
||||||
|
"tsx": "never"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-shadow": "off",
|
||||||
|
"@typescript-eslint/consistent-type-imports": "error",
|
||||||
|
"@typescript-eslint/no-shadow": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"lines-between-class-members": [
|
||||||
|
"warn",
|
||||||
|
"always",
|
||||||
|
{
|
||||||
|
"exceptAfterSingleLine": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"react/sort-comp": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"order": [
|
||||||
|
"static-variables",
|
||||||
|
"instance-variables",
|
||||||
|
"static-methods",
|
||||||
|
"lifecycle",
|
||||||
|
"render",
|
||||||
|
"/^render.+$/",
|
||||||
|
"instance-methods",
|
||||||
|
"everything-else"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"react/destructuring-assignment": [
|
||||||
|
"error",
|
||||||
|
"always",
|
||||||
|
{
|
||||||
|
"ignoreClassFields": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"react/state-in-constructor": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"react/no-unknown-property": "off",
|
||||||
|
"no-bitwise": "off",
|
||||||
|
"import/no-unresolved": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"ignore": [
|
||||||
|
"^mdast$"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"import/no-extraneous-dependencies": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"devDependencies": [
|
||||||
|
"test/**/*.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-return-assign": [
|
||||||
|
"error",
|
||||||
|
"except-parens"
|
||||||
|
],
|
||||||
|
"react/require-default-props": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"varsIgnorePattern": "^_",
|
||||||
|
"argsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"class-methods-use-this": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"enforceForClassFields": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-promise-executor-return": "off",
|
||||||
|
"no-empty-function": "off",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"import/order": "off",
|
||||||
|
"import/prefer-default-export": "off",
|
||||||
|
"react/prop-types": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
|
"react/jsx-props-no-spreading": "off",
|
||||||
|
"react/jsx-boolean-value": "off",
|
||||||
|
"no-plusplus": "off",
|
||||||
|
"no-param-reassign": "off",
|
||||||
|
"default-case": "off",
|
||||||
|
"jsx-a11y/click-events-have-key-events": "off",
|
||||||
|
"jsx-a11y/anchor-has-content": "off"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
},
|
||||||
|
"import/resolver": {
|
||||||
|
"typescript": {
|
||||||
|
"extensions": [
|
||||||
|
".js",
|
||||||
|
".jsx",
|
||||||
|
".ts",
|
||||||
|
".tsx"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node": {
|
||||||
|
"extensions": [
|
||||||
|
".js",
|
||||||
|
".jsx",
|
||||||
|
".ts",
|
||||||
|
".tsx"
|
||||||
|
],
|
||||||
|
"moduleDirectory": [
|
||||||
|
"node_modules",
|
||||||
|
"extension/src/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"src/application/{**,*.*}"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": [
|
||||||
|
"@/plugins/*",
|
||||||
|
"@/pages/*",
|
||||||
|
"@dicetable/plugin-shell",
|
||||||
|
"@dicetable/plugin-shell/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"src/pages/{**,*.*}"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": [
|
||||||
|
"@/plugins/*",
|
||||||
|
"@dicetable/plugin-shell/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"src/shared/{**,*.*}"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": [
|
||||||
|
"@/plugins/*",
|
||||||
|
"@/pages/*",
|
||||||
|
"@/pluginShell/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"src/plugins/*/{**,*.*}"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": [
|
||||||
|
"@/models/*",
|
||||||
|
"@/pages/*",
|
||||||
|
"@/definitions/*",
|
||||||
|
"@/application/*",
|
||||||
|
"@/pluginShell/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"src/pluginShell/{**,*.*}"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": [
|
||||||
|
"@/models/*",
|
||||||
|
"@/pages/*",
|
||||||
|
"@/plugins/*",
|
||||||
|
"@dicetable/plugin-shell/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
### ApacheCordova ###
|
||||||
|
# Apache Cordova generated files and directories
|
||||||
|
.next/
|
||||||
|
|
||||||
|
bin/patchReactNativeDriver.sh
|
||||||
|
!/plugins
|
||||||
|
!/plugins/android.json
|
||||||
|
!/plugins/fetch.json
|
||||||
|
plugins/*
|
||||||
|
platforms/*
|
||||||
|
|
||||||
|
./tmp
|
||||||
|
test/drivers/*
|
||||||
|
|
||||||
|
/www/*
|
||||||
|
node_modules/*
|
||||||
|
/node_modules/*
|
||||||
|
www/index.js
|
||||||
|
js/**/*.js
|
||||||
|
js/**/*.js.map
|
||||||
|
.env
|
||||||
|
|
||||||
|
#idea-ide
|
||||||
|
/.idea/*
|
||||||
|
|
||||||
|
out
|
||||||
|
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
tsconfig.tsbuildinfo
|
||||||
|
public/localforage.js
|
||||||
|
public/sql-wasm.wasm
|
||||||
|
/pluginShell/dist/
|
||||||
|
|
||||||
|
electron/src/Actions.ts
|
||||||
|
electron/src/Bridge.ts
|
||||||
2
.npmignore
Normal file
2
.npmignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# OS X
|
||||||
|
.DS_Store
|
||||||
5
.prettierrc
Normal file
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
||||||
132
CHANGELOG.md
Normal file
132
CHANGELOG.md
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#### Bugfixes
|
||||||
|
|
||||||
|
- Die Userauswahl beim Login ist nur noch sichtbar, wenn es User gibt
|
||||||
|
- Fog of War wird sofort aufgedeckt bei den Spielern und nicht erst nach einem Bewegen der Karte
|
||||||
|
- Wenn eine Szene oder Ebene gelöscht wird, werden die betroffenen Tokens ebenfalls aus der Initiative entfernt
|
||||||
|
- Wenn ein Token per Pfeiltasten nach oben/unten und gleichzeitig zur Seite bewegt wird, bewegt dieser sich wieder
|
||||||
|
richtig
|
||||||
|
-
|
||||||
|
|
||||||
|
# Version 0.5.3 (29.12.2023)
|
||||||
|
|
||||||
|
#### Bugfixes
|
||||||
|
|
||||||
|
- Upload von SaveState löscht nicht mehr die Verbindung zwischen Szene und Layer
|
||||||
|
|
||||||
|
# Version 0.5.2 (29.12.2023)
|
||||||
|
|
||||||
|
### Bufixes
|
||||||
|
|
||||||
|
- Upload von SaveStates mit Plugins funktioniert wieder, auch wenn diese bereits installiert sind.
|
||||||
|
|
||||||
|
# Version 0.5.0 (27.12.2023)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Plugin System
|
||||||
|
- Visitors können nun als Bearbeiter zu Tokens hinzugefügt werden. Visitors können aber keine Tokens erstellen oder
|
||||||
|
löschen.
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- Wenn sich der Server ändert, ist danach die Initiative wieder benutzbar.
|
||||||
|
- Fog of War ist performanter
|
||||||
|
- Die Entfernungsmessungmethode wird wieder korrekt gespeichert.
|
||||||
|
|
||||||
|
# Version 0.4.0 (9.12.2023)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Chat und was dazu gehört
|
||||||
|
- Rollen von Würfeln durch Chat-Befehle, z.B. `/r 1d20+8`
|
||||||
|
- Flüstern durch `/w '<name>' <nachricht>` oder `/w gm <nachricht>`
|
||||||
|
- Markdown-Unterstützung im Chat
|
||||||
|
- Beyond20-Integration (dicetable.net muss im Plugin hinzugefügt werden)
|
||||||
|
- Spuranzeige berücksichtigt den aktuellen Zug
|
||||||
|
- Es kann jetzt eingestellt werden ob neue Nutzer akzeptiert werden und ob für diese automatisch ein Username
|
||||||
|
genereriert wird
|
||||||
|
|
||||||
|
### Feature-Änderungen
|
||||||
|
|
||||||
|
- Im Ebenenmenü, um Tokens zu verschieben oder die Ebene zu wechseln werden nur noch Ebenen angezeigt, die der User auch
|
||||||
|
sieht.
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- Usernames sind nun unabhängig von Groß/Kleinschreibung identisch.
|
||||||
|
- Toast-Benachrichtigungen werden nicht mehr von offenen Fenstern überlagert
|
||||||
|
|
||||||
|
# Version 0.3.6 (11.11.2023)
|
||||||
|
|
||||||
|
#### Bugfixes
|
||||||
|
|
||||||
|
- Spuren sind begrenzt auf 50 Stellen und Bewegungsanimationen werden maximal innerhalb von ein paar Sekunden
|
||||||
|
abgearbeitet
|
||||||
|
- Der Server fällt nicht mehr aus, wenn ein Spieler eine große Speicherdatei hochlädt
|
||||||
|
- Der native Browser-Zoom wird nicht mehr aktiviert, wenn man sich in einem Input-Feld befindet und `STRG` & `+`/`-`
|
||||||
|
drückt
|
||||||
|
- Status-Icons die nur für den Gamemaster sichtbar sind, werden nicht mehr für andere Spieler in der Initiative
|
||||||
|
angezeigt
|
||||||
|
- Die Schriftgröße von gezeichnetem Text muss jetzt mindestens 1 sein
|
||||||
|
- Fenster wackeln nicht mehr in ihrer Größe
|
||||||
|
|
||||||
|
# Version 0.3.4 (3.11.2023)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Textfarbe, Rahmenfarbe und Schriftgröße wird gespeichert
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- Der Changelog wächst nicht mehr über das Modal hinaus
|
||||||
|
- Beim partiellen Hochladen von Savestates wird wirklich nur noch das benötigte hochgeladen
|
||||||
|
|
||||||
|
# Version 0.3.0 (1.11.2023)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Touch-Support für Tablets (und Smartphones, wobei Smartphones nicht empfohlen sind. Das Verschieben von Fenstern
|
||||||
|
funktioniert noch nicht.)
|
||||||
|
- Text kann "gezeichnet" werden, inklusive Text- & Rahmenfarbe und Schriftgröße.
|
||||||
|
- Fenster können durch einen Button unten links oder `STRG+r` auf ihre initiale Position zurückgesetzt werden.
|
||||||
|
- Bugs können nun direkt aus dem VTT heraus gemeldet werden.
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- Der Color-Picker hat nicht mehr den falschen Kamera-Ausschnitt, wenn während der Auswahl gezoomt oder die Kamera
|
||||||
|
bewegt wird.
|
||||||
|
- Ein Bug, der die Dimension eines Objektes nicht verändert, wenn dieses markiert war und ein anderer User das
|
||||||
|
bearbeitet, wurde behoben.
|
||||||
|
- Ein Bug, wo ab und zu Hotkeys nicht wieder deaktiviert wurden, wurde behoben.
|
||||||
|
|
||||||
|
# Version 0.2.1 (11.10.2023)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Das X zum markieren eines besiegten Gegners wird nun in der Initiative groß dargestellt, wenn alle Tokens das X haben.
|
||||||
|
- Text im VTT ist generell lesbarer geworden.
|
||||||
|
- Das Bewegen mittels den Pfeiltasten hinterlässt jetzt eine Spur.
|
||||||
|
- Das Anzeigen der Spuren mittels Tab funktioniert nur noch für aktuell ausgewählte Tokens. Das sorgt für mehr
|
||||||
|
Übersichtlichkeit.
|
||||||
|
- Die Spuranzeige ist nun vor der Selektierungsbox.
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- Name, Lebensanzeige und Statussymbole beachten nun die Transparenz der Ebene
|
||||||
|
- Die Anzeige wer sonst online ist funktioniert nun auch wieder nachdem man den Spielstand exportiert hat.
|
||||||
|
- Wenn ein Polygon-Tool ausgewählt ist, wird durch ein Click nicht mehr ein Token selektiert, sondern direkt die
|
||||||
|
Polygonzeichnung begonnen.
|
||||||
|
- Die Spur von rotierten Tokens wird nun korrekt dargestellt.
|
||||||
|
- Name, Lebensanzeige und Statussymbole wandern nun mit, wenn ein Token mit den Pfeiltasten bewegt wird.
|
||||||
|
- Wenn ein Versions-Fehler auftritt, wird das entsprechende Objekt direkt neu geladen, sodass es nicht erneut vorkommen
|
||||||
|
sollte.
|
||||||
|
- Die Animation der Rotation/Skalierung wird nicht mehr erneut ausgelöst, wenn sich etwas anderes an dem Token ändert.
|
||||||
|
- Lebensanzeigen sollte jetzt für Tokens von 35px und Werte bis 999 nicht mehr aus der Lebensanzeige rauslaufen.
|
||||||
|
- Die Aktionen zur Initiative im Kontext-Menü sind nur noch möglich, wenn man GM ist oder die Initiative aktiviert ist.
|
||||||
|
- Bildänderungen an Tokens lassen das Bild nicht mehr verschwinden.
|
||||||
|
- Fenster lassen sich wieder in der Größe verändern.
|
||||||
|
- Lebensanzeige und Namen werden nicht mehr von unseleketierten Tokens verdeckt, wenn man den Token markiert hat. Das
|
||||||
|
ermöglicht die Inline-Bearbeitung.
|
||||||
|
- Ein Bug, der andere Tokens verschwinden lässt, wenn man einen Token bewegt, wurde behoben.
|
||||||
|
- Wenn man einen Token von einer Layer auf eine andere verschiebt, wird die Position nicht mehr verschoben.
|
||||||
|
- Das Kopieren und Einfügen von Tokens kopiert den Token wieder an die Position der Maus.
|
||||||
135
TODO.md
Normal file
135
TODO.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
ToDo:
|
||||||
|
|
||||||
|
- [ ] Translation of errors in server
|
||||||
|
|
||||||
|
- [ ] Users
|
||||||
|
- [ ] useSortedUsers include Visitors
|
||||||
|
- [x] User wechseln funktioniert nicht mehr
|
||||||
|
- [x] User wechseln übersetzen
|
||||||
|
- [x] User passwort Flow übersetzen
|
||||||
|
|
||||||
|
- [ ] Objekte
|
||||||
|
- [x] Löschen
|
||||||
|
- [x] Via entf/backspace
|
||||||
|
- [x] Via Window
|
||||||
|
- [x] Via Kontextmenü?
|
||||||
|
- [x] Locked-Layer beachten
|
||||||
|
- [x] Unselect nach/bei Löschung
|
||||||
|
- [ ] Kontextmenü
|
||||||
|
- [x] Auf Ebene...
|
||||||
|
- [x] Nach oben
|
||||||
|
- [x] Nach unten
|
||||||
|
- [ ] Bei Roll20/dnd.silas.link nach weiteren Actions schauen
|
||||||
|
- [x] Löschen
|
||||||
|
- [ ] Zur Initiaitve hinzufügen
|
||||||
|
- [x] Kamera zentrieren (?) => In ToolWindow hinzugefügt
|
||||||
|
- [ ] Floating/Quick-Actions (Health, Statussymbole)
|
||||||
|
- [x] Name
|
||||||
|
- [x] Healthbar
|
||||||
|
- [x] Statussymbole
|
||||||
|
- [ ] Armor-Class-Switch (?)
|
||||||
|
- [ ] Statussymbole
|
||||||
|
- [x] DM
|
||||||
|
- [ ] Bearbeiter (?)
|
||||||
|
- [x] Für alle
|
||||||
|
- [x] Multiple Drag and Drop einfügen (nicht alle auf die gleiche Position)
|
||||||
|
- Aus Dateiexplorer
|
||||||
|
|
||||||
|
|
||||||
|
- [x] LayerEditor
|
||||||
|
- [x] Layer reorder in window
|
||||||
|
- [x] New layer button nach oben und ein +
|
||||||
|
- [x] Vorschau wie bei Objekten bei Änderungen
|
||||||
|
- [x] Änderungen an Server übertragen
|
||||||
|
- [x] Renaming von Layern
|
||||||
|
- [x] Layer reordering via dragAndDrop
|
||||||
|
- [x] Drag von 2 zu 1 endet mit 1 und 1
|
||||||
|
- [x] Preview
|
||||||
|
- [x] Design von Opacity-Range auf Material und Flat Design
|
||||||
|
- [x] Locking von Layer
|
||||||
|
- [x] gerade bearbeitete Selektion anpassen
|
||||||
|
- [x] Anlegen von Objekten
|
||||||
|
- [x] Bearbeiten von Objekten
|
||||||
|
- [x] Sichtbarkeit einstellen
|
||||||
|
- [x] Beachten beim
|
||||||
|
- [x] Anzeigen von Objekten
|
||||||
|
- [x] Selektiertes Objekten
|
||||||
|
- [x] Hinzufügen von Objekten
|
||||||
|
- [x] Ändern der Sichtbarkeit von Layern
|
||||||
|
- [x] ActiveLayer change
|
||||||
|
- [x] Was, wenn keine aktive Layer gesetzt?
|
||||||
|
- [x] Element einbauen
|
||||||
|
- [x] Übersetzung
|
||||||
|
- [x] Löschen von einer Ebene
|
||||||
|
- [x] Checken, ob Layer wirklich gelöscht oder nur referenz zur Scene entfernt
|
||||||
|
- [x] order anpassen
|
||||||
|
- [x] Growing von Name und Sichtbarkeitssliders
|
||||||
|
- [x] Lagging beim Hinzufügen von Layern
|
||||||
|
- [x] Layer nur für aktuelle Szene laden
|
||||||
|
|
||||||
|
- Scenes
|
||||||
|
- [x] Aktive Szene im Fenster grau hinterlegen
|
||||||
|
- Wie bei Layer
|
||||||
|
- [x] New scene button nach unten und ein +
|
||||||
|
- [ ] Szene archivieren (?)
|
||||||
|
|
||||||
|
- Window-Management
|
||||||
|
- [ ] Resize to content: Input-Felder beachten
|
||||||
|
- [ ] Reset-Funktion
|
||||||
|
- [ ] Initiale Positionen
|
||||||
|
- [x] translate menu buttons
|
||||||
|
- [x] title for buttons
|
||||||
|
- [x] ResizeWindow erlaubt die Fenster aus dem Viewport zu schieben
|
||||||
|
- [x] Verkleinern bis minimum-größe erreicht
|
||||||
|
- [x] Wenn bei Resize außerhalb des Viewports, Fenster verschieben
|
||||||
|
- [x] Resize to content
|
||||||
|
- [x] Wenn sich Content ändert beachten
|
||||||
|
- [x] Pin Fenster
|
||||||
|
|
||||||
|
- [ ] Settings Window
|
||||||
|
- [ ] Optisch aufarbeiten
|
||||||
|
- [ ] Welche Settings machen wirklich Sinn?
|
||||||
|
|
||||||
|
- [ ] Tool selection and setting
|
||||||
|
- [x] RectangleTool
|
||||||
|
- [ ] PointerTool
|
||||||
|
- [x] Context-Menu
|
||||||
|
- [ ] Hotkeys
|
||||||
|
- [x] Move Map
|
||||||
|
- [x] PolygonTool
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Spezieller Modus für Kartenerstellung => Integriert in VTT
|
||||||
|
- [ ] Polygone nicht Selektierbar machen
|
||||||
|
- [ ] Wand hinzufügen
|
||||||
|
- [ ] Bearbeitbar von Wand
|
||||||
|
|
||||||
|
- [x] Speichern/Laden
|
||||||
|
- [ ] In allen Browsern testen
|
||||||
|
- [ ] Firefox
|
||||||
|
- [ ] Chrome
|
||||||
|
- [ ] Brave
|
||||||
|
- [ ] Safari
|
||||||
|
- [ ] Edge
|
||||||
|
|
||||||
|
- [ ] Fog of War
|
||||||
|
- [x] Rectangle
|
||||||
|
- [x] Circle
|
||||||
|
- [x] Polygon
|
||||||
|
- [x] Reset
|
||||||
|
- [x] Add/Remove fog
|
||||||
|
- [x] Healthbars
|
||||||
|
- [ ] Chat
|
||||||
|
- [ ] Schnelle Möglichkeit gleichzeitig mehreren zu schreiben
|
||||||
|
- [ ] Alles Mögliche als Befehl ausführen
|
||||||
|
- [ ] Klicken auf Dice-Rollers-Ergebnisse um Leben hinzuzufügen/abzuziehen
|
||||||
|
- [ ] Dice-Rollers
|
||||||
|
- [ ] Spielersicht/Simulation
|
||||||
|
- Anschauen, was der Spieler sieht
|
||||||
|
- [ ] Einloggen als der Spieler in einem neuen Tab (?)
|
||||||
|
|
||||||
|
- [ ] Achievements (vom DM erstellt, die er schnell verteilen kann) (?)
|
||||||
|
- [ ] Background-Music (?)
|
||||||
|
- https://www.reddit.com/r/dndnext/comments/11vt5ik/if_youre_looking_for_background_music_i_have_a/
|
||||||
|
- [ ] ~~Raycaster für Single Selektierung?~~
|
||||||
|
- Nicht sinnvoll für Layer, locked layers, ect
|
||||||
101
android/.gitignore
vendored
Normal file
101
android/.gitignore
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore
|
||||||
|
|
||||||
|
# Built application files
|
||||||
|
*.apk
|
||||||
|
*.aar
|
||||||
|
*.ap_
|
||||||
|
*.aab
|
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
out/
|
||||||
|
# Uncomment the following line in case you need and you don't have the release build type files in your app
|
||||||
|
# release/
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
proguard/
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio Navigation editor temp files
|
||||||
|
.navigation/
|
||||||
|
|
||||||
|
# Android Studio captures folder
|
||||||
|
captures/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/workspace.xml
|
||||||
|
.idea/tasks.xml
|
||||||
|
.idea/gradle.xml
|
||||||
|
.idea/assetWizardSettings.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
.idea/libraries
|
||||||
|
# Android Studio 3 in .gitignore file.
|
||||||
|
.idea/caches
|
||||||
|
.idea/modules.xml
|
||||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||||
|
.idea/navEditor.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
|
#*.jks
|
||||||
|
#*.keystore
|
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx/
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
# google-services.json
|
||||||
|
|
||||||
|
# Freeline
|
||||||
|
freeline.py
|
||||||
|
freeline/
|
||||||
|
freeline_project_description.json
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots
|
||||||
|
fastlane/test_output
|
||||||
|
fastlane/readme.md
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
vcs.xml
|
||||||
|
|
||||||
|
# lint
|
||||||
|
lint/intermediates/
|
||||||
|
lint/generated/
|
||||||
|
lint/outputs/
|
||||||
|
lint/tmp/
|
||||||
|
# lint/reports/
|
||||||
|
|
||||||
|
# Android Profiling
|
||||||
|
*.hprof
|
||||||
|
|
||||||
|
# Cordova plugins for Capacitor
|
||||||
|
capacitor-cordova-android-plugins
|
||||||
|
|
||||||
|
# Copied web assets
|
||||||
|
app/src/main/assets/public
|
||||||
|
|
||||||
|
# Generated Config files
|
||||||
|
app/src/main/assets/capacitor.config.json
|
||||||
|
app/src/main/assets/capacitor.plugins.json
|
||||||
|
app/src/main/res/xml/config.xml
|
||||||
0
android/app/.gitignore
vendored
Normal file
0
android/app/.gitignore
vendored
Normal file
0
android/app/build.gradle
Normal file
0
android/app/build.gradle
Normal file
0
android/app/capacitor.build.gradle
Normal file
0
android/app/capacitor.build.gradle
Normal file
0
android/app/proguard-rules.pro
vendored
Normal file
0
android/app/proguard-rules.pro
vendored
Normal file
0
android/app/src/main/AndroidManifest.xml
Normal file
0
android/app/src/main/AndroidManifest.xml
Normal file
0
android/app/src/main/res/drawable/splash.png
Normal file
0
android/app/src/main/res/drawable/splash.png
Normal file
0
android/app/src/main/res/layout/activity_main.xml
Normal file
0
android/app/src/main/res/layout/activity_main.xml
Normal file
0
android/app/src/main/res/values/strings.xml
Normal file
0
android/app/src/main/res/values/strings.xml
Normal file
0
android/app/src/main/res/values/styles.xml
Normal file
0
android/app/src/main/res/values/styles.xml
Normal file
0
android/app/src/main/res/xml/file_paths.xml
Normal file
0
android/app/src/main/res/xml/file_paths.xml
Normal file
0
android/build.gradle
Normal file
0
android/build.gradle
Normal file
0
android/capacitor.settings.gradle
Normal file
0
android/capacitor.settings.gradle
Normal file
0
android/gradle.properties
Normal file
0
android/gradle.properties
Normal file
0
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
0
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
0
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
0
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
0
android/gradlew
vendored
Normal file
0
android/gradlew
vendored
Normal file
0
android/gradlew.bat
vendored
Normal file
0
android/gradlew.bat
vendored
Normal file
0
android/settings.gradle
Normal file
0
android/settings.gradle
Normal file
0
android/variables.gradle
Normal file
0
android/variables.gradle
Normal file
5
bin/export.sh
Executable file
5
bin/export.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
mv next.config.js next.base.config.js
|
||||||
|
mv next.export.config.js next.config.js
|
||||||
|
next build
|
||||||
|
mv next.config.js next.export.config.js
|
||||||
|
mv next.base.config.js next.config.js
|
||||||
13
capacitor.config.ts
Normal file
13
capacitor.config.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { CapacitorElectronConfig } from "@capacitor-community/electron";
|
||||||
|
|
||||||
|
const config: CapacitorElectronConfig = {
|
||||||
|
appId: 'link.silas.yt',
|
||||||
|
appName: 'Easy Youtube Fullscreen',
|
||||||
|
webDir: 'out',
|
||||||
|
server: {
|
||||||
|
androidScheme: 'https'
|
||||||
|
},
|
||||||
|
electron: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
25
config.xml
Normal file
25
config.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<widget id="io.cordova.hellocordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||||
|
<name>HelloCordova</name>
|
||||||
|
<description>
|
||||||
|
A sample Apache Cordova application that responds to the deviceready event.
|
||||||
|
</description>
|
||||||
|
<author email="dev@cordova.apache.org" href="http://cordova.io">
|
||||||
|
Apache Cordova Team
|
||||||
|
</author>
|
||||||
|
<content src="index.html" />
|
||||||
|
<access origin="*" />
|
||||||
|
<allow-intent href="http://*/*" />
|
||||||
|
<allow-intent href="https://*/*" />
|
||||||
|
<allow-intent href="tel:*" />
|
||||||
|
<allow-intent href="sms:*" />
|
||||||
|
<allow-intent href="mailto:*" />
|
||||||
|
<allow-intent href="geo:*" />
|
||||||
|
<platform name="android">
|
||||||
|
<allow-intent href="market:*" />
|
||||||
|
</platform>
|
||||||
|
<platform name="ios">
|
||||||
|
<allow-intent href="itms:*" />
|
||||||
|
<allow-intent href="itms-apps:*" />
|
||||||
|
</platform>
|
||||||
|
</widget>
|
||||||
8
electron/.gitignore
vendored
Normal file
8
electron/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# NPM renames .gitignore to .npmignore
|
||||||
|
# In order to prevent that, we remove the initial "."
|
||||||
|
# And the CLI then renames it
|
||||||
|
app
|
||||||
|
node_modules
|
||||||
|
build
|
||||||
|
dist
|
||||||
|
logs
|
||||||
BIN
electron/assets/appIcon.ico
Normal file
BIN
electron/assets/appIcon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
BIN
electron/assets/appIcon.png
Normal file
BIN
electron/assets/appIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
BIN
electron/assets/splash.gif
Normal file
BIN
electron/assets/splash.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 159 KiB |
BIN
electron/assets/splash.png
Normal file
BIN
electron/assets/splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
13
electron/capacitor.config.ts
Normal file
13
electron/capacitor.config.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { CapacitorElectronConfig } from "@capacitor-community/electron";
|
||||||
|
|
||||||
|
const config: CapacitorElectronConfig = {
|
||||||
|
appId: 'link.silas.yt',
|
||||||
|
appName: 'Easy Youtube Fullscreen',
|
||||||
|
webDir: 'out',
|
||||||
|
server: {
|
||||||
|
androidScheme: 'https'
|
||||||
|
},
|
||||||
|
electron: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
28
electron/electron-builder.config.json
Normal file
28
electron/electron-builder.config.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"appId": "com.yourdoamnin.yourapp",
|
||||||
|
"directories": {
|
||||||
|
"buildResources": "resources"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"assets/**/*",
|
||||||
|
"build/**/*",
|
||||||
|
"capacitor.config.*",
|
||||||
|
"app/**/*"
|
||||||
|
],
|
||||||
|
"publish": {
|
||||||
|
"provider": "github"
|
||||||
|
},
|
||||||
|
"nsis": {
|
||||||
|
"allowElevation": true,
|
||||||
|
"oneClick": false,
|
||||||
|
"allowToChangeInstallationDirectory": true
|
||||||
|
},
|
||||||
|
"win": {
|
||||||
|
"target": "nsis",
|
||||||
|
"icon": "assets/appIcon.ico"
|
||||||
|
},
|
||||||
|
"mac": {
|
||||||
|
"category": "your.app.category.type",
|
||||||
|
"target": "dmg"
|
||||||
|
}
|
||||||
|
}
|
||||||
75
electron/live-runner.js
Normal file
75
electron/live-runner.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* eslint-disable no-undef */
|
||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
const cp = require('child_process');
|
||||||
|
const chokidar = require('chokidar');
|
||||||
|
const electron = require('electron');
|
||||||
|
|
||||||
|
let child = null;
|
||||||
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||||
|
const reloadWatcher = {
|
||||||
|
debouncer: null,
|
||||||
|
ready: false,
|
||||||
|
watcher: null,
|
||||||
|
restarting: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
///*
|
||||||
|
function runBuild() {
|
||||||
|
return new Promise((resolve, _reject) => {
|
||||||
|
let tempChild = cp.spawn(npmCmd, ['run', 'build']);
|
||||||
|
tempChild.once('exit', () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
tempChild.stdout.pipe(process.stdout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//*/
|
||||||
|
|
||||||
|
async function spawnElectron() {
|
||||||
|
if (child !== null) {
|
||||||
|
child.stdin.pause();
|
||||||
|
child.kill();
|
||||||
|
child = null;
|
||||||
|
await runBuild();
|
||||||
|
}
|
||||||
|
child = cp.spawn(electron, ['--inspect=5858', './']);
|
||||||
|
child.on('exit', () => {
|
||||||
|
if (!reloadWatcher.restarting) {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
child.stdout.pipe(process.stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupReloadWatcher() {
|
||||||
|
reloadWatcher.watcher = chokidar
|
||||||
|
.watch('./src/**/*', {
|
||||||
|
ignored: /[/\\]\./,
|
||||||
|
persistent: true,
|
||||||
|
})
|
||||||
|
.on('ready', () => {
|
||||||
|
reloadWatcher.ready = true;
|
||||||
|
})
|
||||||
|
.on('all', (_event, _path) => {
|
||||||
|
if (reloadWatcher.ready) {
|
||||||
|
clearTimeout(reloadWatcher.debouncer);
|
||||||
|
reloadWatcher.debouncer = setTimeout(async () => {
|
||||||
|
console.log('Restarting');
|
||||||
|
reloadWatcher.restarting = true;
|
||||||
|
await spawnElectron();
|
||||||
|
reloadWatcher.restarting = false;
|
||||||
|
reloadWatcher.ready = false;
|
||||||
|
clearTimeout(reloadWatcher.debouncer);
|
||||||
|
reloadWatcher.debouncer = null;
|
||||||
|
reloadWatcher.watcher = null;
|
||||||
|
setupReloadWatcher();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await runBuild();
|
||||||
|
await spawnElectron();
|
||||||
|
setupReloadWatcher();
|
||||||
|
})();
|
||||||
4758
electron/package-lock.json
generated
Normal file
4758
electron/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
41
electron/package.json
Normal file
41
electron/package.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "EasyYoutubeFullscreen",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "An Amazing Capacitor App",
|
||||||
|
"author": {
|
||||||
|
"name": "",
|
||||||
|
"email": ""
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": ""
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "build/src/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc && electron-rebuild",
|
||||||
|
"electron:start-live": "node ./live-runner.js",
|
||||||
|
"electron:start": "npm run build && electron --inspect=5858 ./",
|
||||||
|
"electron:pack": "npm run build && electron-builder build --dir -c ./electron-builder.config.json",
|
||||||
|
"electron:make": "npm run build && electron-builder build -c ./electron-builder.config.json -p always"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@capacitor-community/electron": "^5.0.0",
|
||||||
|
"chokidar": "~3.5.3",
|
||||||
|
"electron-is-dev": "~2.0.0",
|
||||||
|
"electron-serve": "~1.1.0",
|
||||||
|
"electron-unhandled": "~4.0.1",
|
||||||
|
"electron-updater": "^5.3.0",
|
||||||
|
"electron-window-state": "^5.0.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"electron": "^26.2.2",
|
||||||
|
"electron-builder": "~23.6.0",
|
||||||
|
"electron-rebuild": "^3.2.9",
|
||||||
|
"typescript": "^5.0.4"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"capacitor",
|
||||||
|
"electron"
|
||||||
|
]
|
||||||
|
}
|
||||||
10
electron/resources/electron-publisher-custom.js
Normal file
10
electron/resources/electron-publisher-custom.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* eslint-disable no-undef */
|
||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
const electronPublish = require('electron-publish');
|
||||||
|
|
||||||
|
class Publisher extends electronPublish.Publisher {
|
||||||
|
async upload(task) {
|
||||||
|
console.log('electron-publisher-custom', task.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = Publisher;
|
||||||
78
electron/src/index.ts
Normal file
78
electron/src/index.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import type { CapacitorElectronConfig } from '@capacitor-community/electron';
|
||||||
|
import { getCapacitorElectronConfig, setupElectronDeepLinking } from '@capacitor-community/electron';
|
||||||
|
import type { MenuItemConstructorOptions } from 'electron';
|
||||||
|
import { app, MenuItem } from 'electron';
|
||||||
|
import electronIsDev from 'electron-is-dev';
|
||||||
|
import unhandled from 'electron-unhandled';
|
||||||
|
import { autoUpdater } from 'electron-updater';
|
||||||
|
|
||||||
|
import { ElectronCapacitorApp, setupContentSecurityPolicy, setupReloadWatcher } from './setup';
|
||||||
|
|
||||||
|
// Graceful handling of unhandled errors.
|
||||||
|
unhandled();
|
||||||
|
|
||||||
|
// Define our menu templates (these are optional)
|
||||||
|
const trayMenuTemplate: (MenuItemConstructorOptions | MenuItem)[] = [new MenuItem({label: 'Quit App', role: 'quit'})];
|
||||||
|
const appMenuBarMenuTemplate: (MenuItemConstructorOptions | MenuItem)[] = [
|
||||||
|
{role: process.platform === 'darwin' ? 'appMenu' : 'fileMenu'},
|
||||||
|
{role: 'viewMenu'},
|
||||||
|
{
|
||||||
|
role: "editMenu", submenu: [
|
||||||
|
{role: 'copy', accelerator: "CmdOrCtrl+C", label: "Copy"},
|
||||||
|
{role: 'paste', accelerator: 'CmdOrCtrl+V', label: "Paste"},
|
||||||
|
{role: 'cut', accelerator: 'CmdOrCtrl+X', label: "Cut"},
|
||||||
|
{role: 'selectAll', accelerator: 'CmdOrCtrl+A', label: "Select All"},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Get Config options from capacitor.config
|
||||||
|
const capacitorFileConfig: CapacitorElectronConfig = getCapacitorElectronConfig();
|
||||||
|
|
||||||
|
// Initialize our app. You can pass menu templates into the app here.
|
||||||
|
// const myCapacitorApp = new ElectronCapacitorApp(capacitorFileConfig);
|
||||||
|
const myCapacitorApp = new ElectronCapacitorApp(capacitorFileConfig, trayMenuTemplate, appMenuBarMenuTemplate);
|
||||||
|
|
||||||
|
// If deeplinking is enabled then we will set it up here.
|
||||||
|
if (capacitorFileConfig.electron?.deepLinkingEnabled) {
|
||||||
|
setupElectronDeepLinking(myCapacitorApp, {
|
||||||
|
customProtocol: capacitorFileConfig.electron.deepLinkingCustomProtocol ?? 'mycapacitorapp',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are in Dev mode, use the file watcher components.
|
||||||
|
if (electronIsDev) {
|
||||||
|
setupReloadWatcher(myCapacitorApp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run Application
|
||||||
|
(async () => {
|
||||||
|
// Wait for electron app to be ready.
|
||||||
|
await app.whenReady();
|
||||||
|
// Security - Set Content-Security-Policy based on whether or not we are in dev mode.
|
||||||
|
setupContentSecurityPolicy(myCapacitorApp.getCustomURLScheme());
|
||||||
|
// Initialize our app, build windows, and load content.
|
||||||
|
await myCapacitorApp.init();
|
||||||
|
// Check for updates if we are in a packaged app.
|
||||||
|
autoUpdater.checkForUpdatesAndNotify();
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Handle when all of our windows are close (platforms have their own expectations).
|
||||||
|
app.on('window-all-closed', function () {
|
||||||
|
// On OS X it is common for applications and their menu bar
|
||||||
|
// to stay active until the user quits explicitly with Cmd + Q
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// When the dock icon is clicked.
|
||||||
|
app.on('activate', async function () {
|
||||||
|
// On OS X it's common to re-create a window in the app when the
|
||||||
|
// dock icon is clicked and there are no other windows open.
|
||||||
|
if (myCapacitorApp.getMainWindow().isDestroyed()) {
|
||||||
|
await myCapacitorApp.init();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Place all ipc or other electron api calls and custom functionality under this line
|
||||||
26
electron/src/preload.ts
Normal file
26
electron/src/preload.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { contextBridge, ipcRenderer } from "electron";
|
||||||
|
import { Actions } from "./Actions";
|
||||||
|
import { Bridge } from "./Bridge";
|
||||||
|
|
||||||
|
require('./rt/electron-rt');
|
||||||
|
//////////////////////////////
|
||||||
|
// User Defined Preload scripts below
|
||||||
|
console.log('User Preload!');
|
||||||
|
|
||||||
|
const preparedActions = Object.entries(Actions).reduce((acc, [key, value]) => {
|
||||||
|
if (typeof value !== "function") {
|
||||||
|
acc[key] = value;
|
||||||
|
} else {
|
||||||
|
acc[key] = (...args: any[]) => {
|
||||||
|
ipcRenderer.send("action", {prop: key, args});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {} as typeof Actions);
|
||||||
|
|
||||||
|
ipcRenderer.on("port", event => {
|
||||||
|
Bridge.setPort(event.ports[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('Actions', preparedActions);
|
||||||
|
contextBridge.exposeInMainWorld('Bridge', Bridge);
|
||||||
4
electron/src/rt/electron-plugins.js
Normal file
4
electron/src/rt/electron-plugins.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
}
|
||||||
88
electron/src/rt/electron-rt.ts
Normal file
88
electron/src/rt/electron-rt.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
import { ipcRenderer, contextBridge } from 'electron';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const plugins = require('./electron-plugins');
|
||||||
|
|
||||||
|
const randomId = (length = 5) => randomBytes(length).toString('hex');
|
||||||
|
|
||||||
|
const contextApi: {
|
||||||
|
[plugin: string]: { [functionName: string]: () => Promise<any> };
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
Object.keys(plugins).forEach((pluginKey) => {
|
||||||
|
Object.keys(plugins[pluginKey])
|
||||||
|
.filter((className) => className !== 'default')
|
||||||
|
.forEach((classKey) => {
|
||||||
|
const functionList = Object.getOwnPropertyNames(plugins[pluginKey][classKey].prototype).filter(
|
||||||
|
(v) => v !== 'constructor'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!contextApi[classKey]) {
|
||||||
|
contextApi[classKey] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
functionList.forEach((functionName) => {
|
||||||
|
if (!contextApi[classKey][functionName]) {
|
||||||
|
contextApi[classKey][functionName] = (...args) => ipcRenderer.invoke(`${classKey}-${functionName}`, ...args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Events
|
||||||
|
if (plugins[pluginKey][classKey].prototype instanceof EventEmitter) {
|
||||||
|
const listeners: { [key: string]: { type: string; listener: (...args: any[]) => void } } = {};
|
||||||
|
const listenersOfTypeExist = (type) =>
|
||||||
|
!!Object.values(listeners).find((listenerObj) => listenerObj.type === type);
|
||||||
|
|
||||||
|
Object.assign(contextApi[classKey], {
|
||||||
|
addListener(type: string, callback: (...args) => void) {
|
||||||
|
const id = randomId();
|
||||||
|
|
||||||
|
// Deduplicate events
|
||||||
|
if (!listenersOfTypeExist(type)) {
|
||||||
|
ipcRenderer.send(`event-add-${classKey}`, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventHandler = (_, ...args) => callback(...args);
|
||||||
|
|
||||||
|
ipcRenderer.addListener(`event-${classKey}-${type}`, eventHandler);
|
||||||
|
listeners[id] = { type, listener: eventHandler };
|
||||||
|
|
||||||
|
return id;
|
||||||
|
},
|
||||||
|
removeListener(id: string) {
|
||||||
|
if (!listeners[id]) {
|
||||||
|
throw new Error('Invalid id');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { type, listener } = listeners[id];
|
||||||
|
|
||||||
|
ipcRenderer.removeListener(`event-${classKey}-${type}`, listener);
|
||||||
|
|
||||||
|
delete listeners[id];
|
||||||
|
|
||||||
|
if (!listenersOfTypeExist(type)) {
|
||||||
|
ipcRenderer.send(`event-remove-${classKey}-${type}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeAllListeners(type: string) {
|
||||||
|
Object.entries(listeners).forEach(([id, listenerObj]) => {
|
||||||
|
if (!type || listenerObj.type === type) {
|
||||||
|
ipcRenderer.removeListener(`event-${classKey}-${listenerObj.type}`, listenerObj.listener);
|
||||||
|
ipcRenderer.send(`event-remove-${classKey}-${listenerObj.type}`);
|
||||||
|
delete listeners[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('CapacitorCustomPlatform', {
|
||||||
|
name: 'electron',
|
||||||
|
plugins: contextApi,
|
||||||
|
});
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
264
electron/src/setup.ts
Normal file
264
electron/src/setup.ts
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
import type { CapacitorElectronConfig } from '@capacitor-community/electron';
|
||||||
|
import {
|
||||||
|
CapacitorSplashScreen,
|
||||||
|
CapElectronEventEmitter,
|
||||||
|
setupCapacitorElectronPlugins,
|
||||||
|
} from '@capacitor-community/electron';
|
||||||
|
import chokidar from 'chokidar';
|
||||||
|
import {
|
||||||
|
app,
|
||||||
|
BrowserWindow,
|
||||||
|
ipcMain,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
MenuItemConstructorOptions,
|
||||||
|
MessageChannelMain,
|
||||||
|
nativeImage,
|
||||||
|
session,
|
||||||
|
Tray,
|
||||||
|
} from 'electron';
|
||||||
|
import electronIsDev from 'electron-is-dev';
|
||||||
|
import electronServe from 'electron-serve';
|
||||||
|
import windowStateKeeper from 'electron-window-state';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { Actions } from "./Actions";
|
||||||
|
|
||||||
|
// Define components for a watcher to detect when the webapp is changed so we can reload in Dev mode.
|
||||||
|
const reloadWatcher = {
|
||||||
|
debouncer: null,
|
||||||
|
ready: false,
|
||||||
|
watcher: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function setupReloadWatcher(electronCapacitorApp: ElectronCapacitorApp): void {
|
||||||
|
reloadWatcher.watcher = chokidar
|
||||||
|
.watch(join(app.getAppPath(), 'app'), {
|
||||||
|
ignored: /[/\\]\./,
|
||||||
|
persistent: true,
|
||||||
|
})
|
||||||
|
.on('ready', () => {
|
||||||
|
reloadWatcher.ready = true;
|
||||||
|
})
|
||||||
|
.on('all', (_event, _path) => {
|
||||||
|
if (reloadWatcher.ready) {
|
||||||
|
clearTimeout(reloadWatcher.debouncer);
|
||||||
|
reloadWatcher.debouncer = setTimeout(async () => {
|
||||||
|
electronCapacitorApp.getMainWindow().webContents.reload();
|
||||||
|
reloadWatcher.ready = false;
|
||||||
|
clearTimeout(reloadWatcher.debouncer);
|
||||||
|
reloadWatcher.debouncer = null;
|
||||||
|
reloadWatcher.watcher = null;
|
||||||
|
setupReloadWatcher(electronCapacitorApp);
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define our class to manage our app.
|
||||||
|
export class ElectronCapacitorApp {
|
||||||
|
private MainWindow: BrowserWindow | null = null;
|
||||||
|
private SplashScreen: CapacitorSplashScreen | null = null;
|
||||||
|
private TrayIcon: Tray | null = null;
|
||||||
|
private CapacitorFileConfig: CapacitorElectronConfig;
|
||||||
|
private TrayMenuTemplate: (MenuItem | MenuItemConstructorOptions)[] = [
|
||||||
|
new MenuItem({label: 'Quit App', role: 'quit'}),
|
||||||
|
];
|
||||||
|
private AppMenuBarMenuTemplate: (MenuItem | MenuItemConstructorOptions)[] = [
|
||||||
|
{role: process.platform === 'darwin' ? 'appMenu' : 'fileMenu'},
|
||||||
|
{role: 'viewMenu'},
|
||||||
|
];
|
||||||
|
private mainWindowState;
|
||||||
|
private loadWebApp;
|
||||||
|
private customScheme: string;
|
||||||
|
|
||||||
|
private channels = new MessageChannelMain();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
capacitorFileConfig: CapacitorElectronConfig,
|
||||||
|
trayMenuTemplate?: (MenuItemConstructorOptions | MenuItem)[],
|
||||||
|
appMenuBarMenuTemplate?: (MenuItemConstructorOptions | MenuItem)[]
|
||||||
|
) {
|
||||||
|
this.CapacitorFileConfig = capacitorFileConfig;
|
||||||
|
|
||||||
|
this.customScheme = this.CapacitorFileConfig.electron?.customUrlScheme ?? 'capacitor-electron';
|
||||||
|
|
||||||
|
if (trayMenuTemplate) {
|
||||||
|
this.TrayMenuTemplate = trayMenuTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appMenuBarMenuTemplate) {
|
||||||
|
this.AppMenuBarMenuTemplate = appMenuBarMenuTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup our web app loader, this lets us load apps like react, vue, and angular without changing their build chains.
|
||||||
|
this.loadWebApp = electronServe({
|
||||||
|
directory: join(app.getAppPath(), 'app'),
|
||||||
|
scheme: this.customScheme,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose the mainWindow ref for use outside of the class.
|
||||||
|
getMainWindow(): BrowserWindow {
|
||||||
|
return this.MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCustomURLScheme(): string {
|
||||||
|
return this.customScheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
async init(): Promise<void> {
|
||||||
|
const icon = nativeImage.createFromPath(
|
||||||
|
join(app.getAppPath(), 'assets', process.platform === 'win32' ? 'appIcon.ico' : 'appIcon.png')
|
||||||
|
);
|
||||||
|
this.mainWindowState = windowStateKeeper({
|
||||||
|
defaultWidth: 1000,
|
||||||
|
defaultHeight: 800,
|
||||||
|
});
|
||||||
|
// Setup preload script path and construct our main window.
|
||||||
|
const preloadPath = join(app.getAppPath(), 'build', 'src', 'preload.js');
|
||||||
|
this.MainWindow = new BrowserWindow({
|
||||||
|
icon,
|
||||||
|
show: false,
|
||||||
|
x: this.mainWindowState.x,
|
||||||
|
y: this.mainWindowState.y,
|
||||||
|
width: this.mainWindowState.width,
|
||||||
|
height: this.mainWindowState.height,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
contextIsolation: true,
|
||||||
|
// Use preload to inject the electron varriant overrides for capacitor plugins.
|
||||||
|
// preload: join(app.getAppPath(), "node_modules", "@capacitor-community", "electron", "dist", "runtime", "electron-rt.js"),
|
||||||
|
preload: preloadPath,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.mainWindowState.manage(this.MainWindow);
|
||||||
|
this.MainWindow.webContents.postMessage("port", null, [this.channels.port1]);
|
||||||
|
Actions.setVideoWindowPort(this.channels.port2);
|
||||||
|
|
||||||
|
if (this.CapacitorFileConfig.backgroundColor) {
|
||||||
|
this.MainWindow.setBackgroundColor(this.CapacitorFileConfig.electron.backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we close the main window with the splashscreen enabled we need to destory the ref.
|
||||||
|
this.MainWindow.on('closed', () => {
|
||||||
|
if (this.SplashScreen?.getSplashWindow() && !this.SplashScreen.getSplashWindow().isDestroyed()) {
|
||||||
|
this.SplashScreen.getSplashWindow().close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// When the tray icon is enabled, setup the options.
|
||||||
|
if (this.CapacitorFileConfig.electron?.trayIconAndMenuEnabled) {
|
||||||
|
this.TrayIcon = new Tray(icon);
|
||||||
|
this.TrayIcon.on('double-click', () => {
|
||||||
|
if (this.MainWindow) {
|
||||||
|
if (this.MainWindow.isVisible()) {
|
||||||
|
this.MainWindow.hide();
|
||||||
|
} else {
|
||||||
|
this.MainWindow.show();
|
||||||
|
this.MainWindow.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.TrayIcon.on('click', () => {
|
||||||
|
if (this.MainWindow) {
|
||||||
|
if (this.MainWindow.isVisible()) {
|
||||||
|
this.MainWindow.hide();
|
||||||
|
} else {
|
||||||
|
this.MainWindow.show();
|
||||||
|
this.MainWindow.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.TrayIcon.setToolTip(app.getName());
|
||||||
|
this.TrayIcon.setContextMenu(Menu.buildFromTemplate(this.TrayMenuTemplate));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the main manu bar at the top of our window.
|
||||||
|
Menu.setApplicationMenu(Menu.buildFromTemplate(this.AppMenuBarMenuTemplate));
|
||||||
|
|
||||||
|
// If the splashscreen is enabled, show it first while the main window loads then switch it out for the main window, or just load the main window from the start.
|
||||||
|
if (this.CapacitorFileConfig.electron?.splashScreenEnabled) {
|
||||||
|
this.SplashScreen = new CapacitorSplashScreen({
|
||||||
|
imageFilePath: join(
|
||||||
|
app.getAppPath(),
|
||||||
|
'assets',
|
||||||
|
this.CapacitorFileConfig.electron?.splashScreenImageName ?? 'splash.png'
|
||||||
|
),
|
||||||
|
windowWidth: 400,
|
||||||
|
windowHeight: 400,
|
||||||
|
});
|
||||||
|
this.SplashScreen.init(this.loadMainWindow, this);
|
||||||
|
} else {
|
||||||
|
this.loadMainWindow(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security
|
||||||
|
this.MainWindow.webContents.setWindowOpenHandler((details) => {
|
||||||
|
return {
|
||||||
|
action: 'allow', overrideBrowserWindowOptions: {}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
this.MainWindow.webContents.on('will-navigate', (event, _newURL) => {
|
||||||
|
if (!this.MainWindow.webContents.getURL().includes(this.customScheme)) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Link electron plugins into the system.
|
||||||
|
setupCapacitorElectronPlugins();
|
||||||
|
|
||||||
|
// When the web app is loaded we hide the splashscreen if needed and show the mainwindow.
|
||||||
|
this.MainWindow.webContents.on('dom-ready', () => {
|
||||||
|
if (this.CapacitorFileConfig.electron?.splashScreenEnabled) {
|
||||||
|
this.SplashScreen.getSplashWindow().hide();
|
||||||
|
}
|
||||||
|
if (!this.CapacitorFileConfig.electron?.hideMainWindowOnLaunch) {
|
||||||
|
this.MainWindow.show();
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
if (electronIsDev) {
|
||||||
|
this.MainWindow.webContents.openDevTools();
|
||||||
|
}
|
||||||
|
CapElectronEventEmitter.emit('CAPELECTRON_DeeplinkListenerInitialized', '');
|
||||||
|
}, 400);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to load in the app.
|
||||||
|
private async loadMainWindow(thisRef: any) {
|
||||||
|
await thisRef.loadWebApp(thisRef.MainWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a CSP up for our application based on the custom scheme
|
||||||
|
export function setupContentSecurityPolicy(customScheme: string): void {
|
||||||
|
const allowed = `default-src ${customScheme}://* https://* blob: 'unsafe-inline' data:`
|
||||||
|
|
||||||
|
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
||||||
|
callback({
|
||||||
|
responseHeaders: {
|
||||||
|
...details.responseHeaders,
|
||||||
|
'Content-Security-Policy': [
|
||||||
|
electronIsDev
|
||||||
|
? `${allowed} devtools://* 'unsafe-eval'`
|
||||||
|
: allowed,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcMain.on("action", (event, arg) => {
|
||||||
|
if (typeof arg === "object" && arg && "prop" in arg && "args" in arg) {
|
||||||
|
const {prop, args} = arg;
|
||||||
|
if (prop in Actions && typeof Actions[prop] === "function") {
|
||||||
|
Actions[prop](...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.on("redirect", (event, arg) => {
|
||||||
|
console.log("LOG-d redirect...", event, arg);
|
||||||
|
ipcMain.emit("redirected", arg);
|
||||||
|
})
|
||||||
|
Actions.setIsDev(electronIsDev);
|
||||||
22
electron/tsconfig.json
Normal file
22
electron/tsconfig.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": true,
|
||||||
|
"include": [
|
||||||
|
"./src/**/*",
|
||||||
|
"./capacitor.config.ts",
|
||||||
|
"./capacitor.config.js"
|
||||||
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./build",
|
||||||
|
"importHelpers": true,
|
||||||
|
"target": "ES2017",
|
||||||
|
"module": "CommonJS",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"rootDir": "."
|
||||||
|
}
|
||||||
|
}
|
||||||
13
ios/.gitignore
vendored
Normal file
13
ios/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
App/build
|
||||||
|
App/Pods
|
||||||
|
App/output
|
||||||
|
App/App/public
|
||||||
|
DerivedData
|
||||||
|
xcuserdata
|
||||||
|
|
||||||
|
# Cordova plugins for Capacitor
|
||||||
|
capacitor-cordova-ios-plugins
|
||||||
|
|
||||||
|
# Generated Config files
|
||||||
|
App/App/capacitor.config.json
|
||||||
|
App/App/config.xml
|
||||||
0
ios/App/App.xcodeproj/project.pbxproj
Normal file
0
ios/App/App.xcodeproj/project.pbxproj
Normal file
0
ios/App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
0
ios/App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
0
ios/App/App.xcworkspace/contents.xcworkspacedata
generated
Normal file
0
ios/App/App.xcworkspace/contents.xcworkspacedata
generated
Normal file
0
ios/App/App/AppDelegate.swift
Normal file
0
ios/App/App/AppDelegate.swift
Normal file
0
ios/App/App/Assets.xcassets/Contents.json
Normal file
0
ios/App/App/Assets.xcassets/Contents.json
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/Contents.json
vendored
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/Contents.json
vendored
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png
vendored
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png
vendored
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png
vendored
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png
vendored
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png
vendored
Normal file
0
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png
vendored
Normal file
0
ios/App/App/Base.lproj/LaunchScreen.storyboard
Normal file
0
ios/App/App/Base.lproj/LaunchScreen.storyboard
Normal file
0
ios/App/App/Base.lproj/Main.storyboard
Normal file
0
ios/App/App/Base.lproj/Main.storyboard
Normal file
0
ios/App/App/Info.plist
Normal file
0
ios/App/App/Info.plist
Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user