new version

This commit is contained in:
silas
2020-10-17 16:42:59 +02:00
parent 0d70067fe4
commit db76378425
388 changed files with 47326 additions and 19804 deletions

8
src/client/globals.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
declare var require: {
<T>(path: string): T;
(paths: string[], callback: (...modules: any[]) => void): void;
ensure: (
paths: string[],
callback: (require: <T>(path: string) => T) => void
) => void;
};

View File

@@ -0,0 +1,57 @@
<div class='max-height fill-me'>
<div class='grid-x max-width grow flex-center'>
<div class='columns small-centered small-12 smedium-11 medium-9 large-7'>
<label class="switch grid-x setting-row">
<span class='columns small-6 translation'>sound</span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="play-sound" name='play-sound' value="1"
data-default="1">
<span class="slider"></span>
</span>
</label>
<label class="switch grid-x setting-row">
<span class='columns small-6 translation' >music</span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="play-music" name='play-music' value="1"
data-default="1">
<span class="slider"></span>
</span>
</label>
<div class='grid-x setting-row' id='credits-button'>
<span class='columns small-6 translation' >credits</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' id='privacy-policy-button'>
<span class='columns small-6 translation'>privacy-policy</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' id='impressum-button'>
<span class='columns small-6 translation' >impressum</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' id='contact-button'>
<span class='columns small-6 translation'>contact</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<label class="switch grid-x setting-row">
<span class='columns small-6 translation'>track</span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="track-switch" name='matomoShouldTrack' value="1"
data-default="1" data-raw="1">
<span class="slider"></span>
</span>
</label>
<div class='grid-x setting-row hidden' >
<span class = "column small-10" id='storage-info'></span>
<span class='columns small-2 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' >
<span class = "column small-6 translation">version-label</span>
<span class = "column small-6 text-right" id='version-info'></span>
</div>
<button id='reset-levels' class="button hidden">reset-levels</button>
</div>
</div>
</div>

View File

@@ -0,0 +1,21 @@
<h1 class = "translation">contact</h1>
<p id = "contactText">
</p>
<form class="grid-x" id = "contact-form">
<label class="small-12 medium-6 right">
<input type="checkbox" value="1" required name="policy">
<span>
<a class = "link translation" href="/?s=privacyPolicy">privacy-policy</a>
<span class = "translation">privacy policy accepted</span>
</span>
</label>
<label class = "small-12 medium-6">
<input type="email" required name="email">
<span class="translation">e-mail</span>
</label>
<label class="small-12">
<textarea required name="message"></textarea>
<span class="translation">message</span>
</label>
<button class="small-12 button translation">send</button>
</form>

View File

@@ -0,0 +1,5 @@
<div>
<p class="translation" data-translation="credits-sister-text"></p>
<p class="translation" data-translation="credits-coin-text" data-translation-args='["https://www.freesfx.co.uk/"]'></p>
<p class="translation" data-translation="credits-music-text" data-translation-args='["https://audeeyah.de", "http://creativecommons.org/licenses/by/4.0/"]'></p>
</div>

View File

@@ -0,0 +1,3 @@
<div class = 'max-height flex-center'>
<div data-translation="game-ended" class = 'center translation'></div>
</div>

View File

@@ -6,6 +6,6 @@
Deutschland
</p>
<p>E-Mail: <a href="mailto:wordRotator@silas.link">wordRotator@silas.link</a><br />
<a href = "contactMe" class = "link" target="_blank">Kontaktformular</a>
<a href = "?s=contact" class = "link" target="_blank">Kontaktformular</a>
</p>
</div>

View File

@@ -19,24 +19,24 @@
<div id = 'tutorial-pointer'></div>
<!-- Site Content -->
<div class='max-height fill-me'>
<div class="text-right max-width">
<button class="button show-while-playing" id='help-button'>
<img src = "img/help.png"/>
</button>
</div>
<!-- <div class="text-right max-width">-->
<!-- <button class="button show-while-playing" id='help-button'>-->
<!-- <img src = "../../img/help.png"/>-->
<!-- </button>-->
<!-- </div>-->
<div class = 'height-20 no-transition tutorial-text center flex-center hidden'>
<div class = 'step-1 hidden' data-translation="tutorial-step-1"></div>
<div class = 'step-2 hidden' data-translation="tutorial-step-2"></div>
<div class = 'step-3 hidden' data-translation="tutorial-step-3"></div>
<div class = 'step-4 hidden' data-translation="tutorial-step-4"></div>
<div class = 'step-1 hidden translation' data-translation="tutorial-step-1"></div>
<div class = 'step-2 hidden translation' data-translation="tutorial-step-2"></div>
<div class = 'step-3 hidden translation' data-translation="tutorial-step-3"></div>
<div class = 'step-4 hidden translation' data-translation="tutorial-step-4"></div>
</div>
<div class='height-20 show-when-won center flex-center fill-me' style = 'min-height: 45px'>
<div class = 'grow max-width'>
<b data-translation="won" id="won-text"></b>
<b class="translation" data-translation="won" id="won-text"></b>
</div>
<div id='coin-container'>
<div id='coin-template' class='coin' style="opacity: 0">
<img src='img/coin.png'/>
<img src='../../img/coin.png'/>
</div>
</div>
</div>
@@ -45,7 +45,7 @@
</div>
</div>
<div class='show-when-won flex-center height-20'>
<button class='button max-width' id='continue-button' data-translation="continue"></button>
<button class='button max-width translation' id='continue-button' data-translation="continue"></button>
</div>
</div>

View File

@@ -21,16 +21,16 @@
</span>
</div>
<div class='height-30 flex-center fill-me'>
<button class='button grow text-center' id='play-button'><span data-translation="play"></span></button>
<button class='button grow text-center' id='play-button'><span class="translation" data-translation="play"></span></button>
<div class='max-width line-height-1 fill-me vertical'>
<label class="switch">
<div data-view="img/speaker.svg"></div>
<div data-view="../../img/speaker.svg"></div>
<input type="checkbox" class="setting" id="play-sound">
<span class="slider"></span>
</label>
<div class="grow center" id = "share-button"><span data-view="img/share.svg"></span></div>
<div class="grow center" id = "share-button"><span data-view="../../img/share.svg"></span></div>
<label class="switch right">
<div data-view="img/music.svg"></div>
<div data-view="../../img/music.svg"></div>
<input type="checkbox" class="setting" id="play-music">
<span class="slider"></span>
</label>

View File

@@ -16,7 +16,7 @@ Mariabrunnstraße 48<br>
Deutschland<br>
<br>
E-Mailadresse: wordRotator@silas.link<br>
Link zum Impressum: https://wordrotator.silas.link/impressum</span></p>
Link zum Impressum: <a class = "link" href = "https://wordrotator.silas.link/impressum">https://wordrotator.silas.link/impressum</a></span></p>
<h3 id="dsg-general-datatype">Arten der verarbeiteten Daten</h3>
<p>
- Bestandsdaten (z.B., Personen-Stammdaten, Namen oder Adressen).<br>
@@ -116,15 +116,15 @@ Link zum Impressum: https://wordrotator.silas.link/impressum</span></p>
</p>
<!--<h3 id="dsg-general-thirdparty">Übermittlungen in Drittländer</h3>-->
<!--<p>Sofern wir Daten in einem Drittland (d.h. außerhalb der Europäischen Union (EU), des Europäischen-->
<!--Wirtschaftsraums (EWR) oder der Schweizer Eidgenossenschaft) verarbeiten oder dies im Rahmen der Inanspruchnahme-->
<!--von Diensten Dritter oder Offenlegung, bzw. Übermittlung von Daten an andere Personen oder Unternehmen-->
<!--geschieht, erfolgt dies nur, wenn es zur Erfüllung unserer (vor)vertraglichen Pflichten, auf Grundlage Ihrer-->
<!--Einwilligung, aufgrund einer rechtlichen Verpflichtung oder auf Grundlage unserer berechtigten Interessen-->
<!--geschieht. Vorbehaltlich gesetzlicher oder vertraglicher Erlaubnisse, verarbeiten oder lassen wir die Daten in-->
<!--einem Drittland nur beim Vorliegen der gesetzlichen Voraussetzungen. D.h. die Verarbeitung erfolgt z.B. auf-->
<!--Grundlage besonderer Garantien, wie der offiziell anerkannten Feststellung eines der EU entsprechenden-->
<!--Datenschutzniveaus (z.B. für die USA durch das „Privacy Shield“) oder Beachtung offiziell anerkannter spezieller-->
<!--vertraglicher Verpflichtungen.</p>-->
<!--Wirtschaftsraums (EWR) oder der Schweizer Eidgenossenschaft) verarbeiten oder dies im Rahmen der Inanspruchnahme-->
<!--von Diensten Dritter oder Offenlegung, bzw. Übermittlung von Daten an andere Personen oder Unternehmen-->
<!--geschieht, erfolgt dies nur, wenn es zur Erfüllung unserer (vor)vertraglichen Pflichten, auf Grundlage Ihrer-->
<!--Einwilligung, aufgrund einer rechtlichen Verpflichtung oder auf Grundlage unserer berechtigten Interessen-->
<!--geschieht. Vorbehaltlich gesetzlicher oder vertraglicher Erlaubnisse, verarbeiten oder lassen wir die Daten in-->
<!--einem Drittland nur beim Vorliegen der gesetzlichen Voraussetzungen. D.h. die Verarbeitung erfolgt z.B. auf-->
<!--Grundlage besonderer Garantien, wie der offiziell anerkannten Feststellung eines der EU entsprechenden-->
<!--Datenschutzniveaus (z.B. für die USA durch das „Privacy Shield“) oder Beachtung offiziell anerkannter spezieller-->
<!--vertraglicher Verpflichtungen.</p>-->
<h3 id="dsg-general-rightssubject">Rechte der betroffenen Personen</h3>
<p>Sie haben das Recht, eine Bestätigung darüber zu verlangen, ob betreffende Daten verarbeitet werden und auf
Auskunft über diese Daten sowie auf weitere Informationen und Kopie der Daten entsprechend den gesetzlichen
@@ -220,7 +220,7 @@ Die Logs mit den Daten der Nutzer werden nach spätestens einem Jahr gelöscht.<
<br></span>
</p>
<label class="switch row setting-row">
<span class='columns small-6' data-translation="track"></span>
<span class='columns small-6 translation' data-translation="track"></span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="track-switch" name='matomoShouldTrack' value="1"
data-default="1" data-raw="1">

View File

@@ -0,0 +1,17 @@
<div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<div id = "wordRotatorSettings"></div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

BIN
src/client/img/coin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
src/client/img/help.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

BIN
src/client/img/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
src/client/img/icon1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
src/client/img/icon1.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
src/client/img/icon10.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
src/client/img/icon11.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon12,.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
src/client/img/icon13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
src/client/img/icon13.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
src/client/img/icon14.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon2.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon3.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon4.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon5.xcf Normal file

Binary file not shown.

Binary file not shown.

BIN
src/client/img/icon6.xcf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="img/icons/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2425 5114 c-435 -33 -824 -153 -1173 -361 -336 -200 -675 -539 -875
-875 -242 -405 -360 -838 -360 -1313 0 -475 118 -908 360 -1313 200 -336 539
-675 875 -875 405 -242 838 -360 1313 -360 399 0 739 75 1093 244 274 130 484
279 708 503 410 410 652 900 730 1477 21 150 23 470 5 614 -75 595 -337 1126
-757 1535 -400 389 -892 628 -1449 704 -113 15 -381 27 -470 20z m-1410 -1566
c3 -13 10 -32 15 -43 9 -22 55 -233 66 -302 4 -24 11 -43 16 -43 6 0 8 -9 5
-20 -3 -10 -2 -20 2 -22 7 -3 71 -293 71 -321 0 -10 4 -17 9 -17 5 0 11 -12
13 -27 17 -100 63 -299 71 -304 6 -4 7 -14 4 -23 -4 -9 -3 -16 1 -16 5 0 16
-45 27 -100 16 -92 35 -140 35 -91 0 11 4 22 9 25 5 3 7 15 4 26 -3 11 -1 20
5 20 5 0 12 17 15 38 8 54 47 235 54 252 3 8 5 21 4 29 -1 8 2 17 7 20 5 3 24
81 42 174 19 92 37 167 41 167 4 0 5 9 2 21 -3 12 -1 24 4 28 9 5 44 155 61
254 2 15 8 27 12 27 5 0 6 9 3 20 -3 11 -1 26 5 33 5 6 17 48 26 92 9 44 19
90 22 103 l4 22 260 0 c143 0 260 -1 260 -3 0 -23 24 -125 32 -134 6 -7 8 -20
4 -28 -3 -8 -2 -15 2 -15 5 0 21 -64 36 -142 16 -79 33 -149 38 -155 6 -7 8
-19 5 -27 -3 -8 -2 -16 2 -18 7 -3 59 -233 69 -305 2 -18 8 -33 14 -33 5 0 8
-8 6 -17 -1 -10 0 -22 4 -28 3 -5 20 -80 38 -165 18 -85 35 -157 39 -160 4 -3
13 -39 21 -80 14 -82 23 -77 36 20 4 27 10 50 15 50 5 0 6 7 2 16 -3 9 -1 19
4 23 5 3 25 78 43 166 18 88 36 162 39 165 7 6 71 297 71 323 0 10 4 17 10 17
5 0 7 7 4 15 -4 8 -2 21 4 28 5 6 24 82 42 167 18 85 36 160 41 166 5 6 6 14
3 17 -3 3 -2 12 2 19 5 7 14 36 19 63 l10 50 250 0 c470 0 718 -10 843 -35 61
-13 112 -27 112 -31 0 -5 5 -9 11 -9 5 0 40 -14 77 -32 79 -37 174 -135 193
-199 7 -21 16 -39 22 -39 5 0 7 -6 4 -14 -3 -8 -1 -16 6 -19 18 -6 17 -339 -1
-345 -6 -2 -10 -7 -7 -11 2 -5 -7 -31 -20 -60 -14 -28 -25 -55 -25 -60 0 -6
-10 -17 -22 -25 -12 -9 -19 -16 -16 -16 4 0 -10 -18 -32 -40 -22 -22 -43 -40
-48 -40 -4 0 -18 -9 -30 -20 -12 -12 -22 -17 -22 -13 0 4 -4 3 -8 -3 -4 -5
-34 -21 -67 -35 -45 -18 -54 -25 -37 -27 12 -2 22 -7 22 -10 0 -4 17 -16 38
-27 46 -24 124 -101 146 -143 8 -16 22 -36 29 -44 7 -7 29 -44 47 -83 19 -38
38 -72 42 -73 5 -2 6 -8 2 -13 -3 -5 0 -9 5 -9 6 0 11 -6 11 -14 0 -19 60
-150 71 -154 5 -2 9 -9 9 -15 0 -7 8 -28 18 -47 11 -19 22 -47 25 -62 4 -15
15 -34 25 -44 9 -10 16 -19 14 -21 -1 -2 4 -16 12 -32 13 -24 56 -131 56 -138
0 -2 -122 -3 -271 -3 l-270 0 -21 50 c-11 27 -25 50 -30 50 -5 0 -6 5 -3 10 3
6 1 10 -4 10 -6 0 -11 8 -11 17 0 15 -40 100 -177 380 -56 113 -130 203 -168
203 -8 0 -15 5 -15 11 0 5 -4 7 -10 4 -5 -3 -10 -2 -10 3 0 17 -53 22 -301 28
l-247 6 -16 -74 c-8 -40 -23 -111 -32 -158 -10 -47 -20 -87 -24 -90 -4 -3 -22
-79 -41 -170 -18 -91 -36 -166 -40 -168 -4 -2 -5 -12 -2 -22 3 -11 0 -20 -6
-20 -6 0 -11 -11 -11 -25 l0 -25 -308 0 -308 0 -24 115 c-13 63 -28 115 -33
115 -5 0 -7 10 -6 23 2 12 1 27 -3 32 -3 6 -20 80 -38 165 -18 85 -37 158 -43
161 -5 4 -7 16 -4 27 2 12 1 22 -3 24 -4 2 -20 64 -35 138 -15 74 -32 138 -37
141 -6 4 -8 16 -5 28 3 12 2 21 -2 21 -4 0 -11 24 -17 53 -41 205 -59 283 -67
288 -6 4 -7 14 -4 23 4 9 3 16 -2 16 -5 0 -12 19 -16 43 -8 42 -8 41 -27 -53
-11 -52 -23 -97 -27 -100 -4 -3 -22 -79 -41 -170 -19 -91 -37 -166 -41 -168
-4 -2 -4 -12 -2 -24 3 -11 1 -23 -4 -27 -9 -5 -50 -179 -61 -258 -2 -18 -8
-33 -12 -33 -5 0 -6 -9 -3 -21 3 -12 1 -24 -4 -28 -9 -6 -83 -330 -83 -364 0
-8 -4 -17 -8 -19 -5 -1 -15 -34 -23 -73 l-15 -70 -306 -3 -306 -2 -13 65 c-7
36 -17 65 -22 65 -5 0 -7 9 -4 20 3 11 2 20 -3 20 -4 0 -10 15 -12 33 -10 67
-61 302 -68 307 -6 4 -54 221 -68 303 -2 15 -8 27 -13 27 -5 0 -9 7 -9 16 0
30 -70 348 -81 371 -6 11 -9 26 -5 31 3 6 2 12 -2 14 -4 1 -21 65 -37 141 -15
75 -32 137 -38 137 -5 0 -7 14 -5 30 3 17 2 30 -2 30 -3 0 -21 74 -40 165 -19
91 -38 165 -42 165 -4 0 -8 11 -8 25 l0 25 254 0 255 0 6 -22z"/>
<path d="M3315 3192 c-43 -4 -55 -14 -55 -49 0 -13 -4 -23 -9 -23 -5 0 -7 -9
-4 -20 3 -11 1 -26 -5 -33 -6 -7 -23 -73 -38 -147 -15 -74 -31 -136 -35 -138
-4 -2 -5 -12 -2 -22 3 -11 0 -20 -6 -20 -6 0 -11 -8 -11 -18 0 -17 13 -19 158
-25 363 -15 426 -7 493 63 21 22 35 40 31 40 -4 0 0 4 8 10 17 11 27 191 12
230 -5 14 -9 27 -9 30 0 3 -11 18 -26 34 -15 16 -27 33 -27 38 0 5 -4 6 -10 3
-5 -3 -10 -1 -10 4 0 6 -3 10 -7 9 -5 -1 -21 4 -37 11 -16 6 -48 14 -70 16
-57 7 -293 11 -341 7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
src/client/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

2
src/client/img/music.svg Normal file
View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" x="0px" y="0px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve" id="svg2" inkscape:version="0.48.4 r9939" sodipodi:docname="music.svg"><defs id="defs13"/><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview11" showgrid="false" inkscape:zoom="7.375" inkscape:cx="16" inkscape:cy="16" inkscape:window-x="53" inkscape:window-y="31" inkscape:window-maximized="0" inkscape:current-layer="svg2"/><metadata id="metadata3"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title>PICOL Icon</dc:title><dc:date>2009-03-15</dc:date><dc:creator><cc:Agent><dc:title>Melih Bilgil</dc:title></cc:Agent></dc:creator><dc:rights><cc:Agent><dc:title>Creative Commons BY-SA</dc:title></cc:Agent></dc:rights><dc:publisher><cc:Agent><dc:title>PICOL - Pictorial Communication Language</dc:title></cc:Agent></dc:publisher><dc:identifier>http://blog.picol.org</dc:identifier><dc:source>http://blog.picol.org</dc:source><dc:language>en</dc:language><dc:subject><rdf:Bag><rdf:li>PICOL</rdf:li><rdf:li>icon</rdf:li><rdf:li>icons</rdf:li><rdf:li>sign</rdf:li><rdf:li>GUI</rdf:li><rdf:li>vector</rdf:li><rdf:li>interface</rdf:li></rdf:Bag></dc:subject><dc:description>This is one icon out of all PICOL icons</dc:description><dc:contributor><cc:Agent><dc:title>Melih Bilgil (www.lonja.de), Christopher Adjei (www.boffer.net)</dc:title></cc:Agent></dc:contributor><cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/"/></cc:Work><cc:License rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"><cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/><cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/><cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/><cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/><cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/><cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/></cc:License></rdf:RDF></metadata><g id="background"><rect fill="none" width="32" height="32" id="rect6"/></g><path id="path9" d="M 8,0 V 16.35 C 7.373,16.127 6.702,16 6,16 c -3.316,0 -6,2.691 -6,6 0,3.314 2.684,6 6,6 3.311,0 6,-2.686 6,-6 V 6 L 24,8 V 20.35 C 23.373,20.127 22.703,20 22,20 c -3.316,0 -6,2.691 -6,6 0,3.314 2.684,6 6,6 3.309,0 6,-2.686 6,-6 V 4 L 8,0 z"/></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src/client/img/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

4
src/client/img/share.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<!--<path d="M0 0h48v48h-48z" fill="none" />-->
<path class="fill-color" d="M36 32.17c-1.52 0-2.89.59-3.93 1.54l-14.25-8.31c.11-.45.18-.92.18-1.4s-.07-.95-.18-1.4l14.1-8.23c1.07 1 2.5 1.62 4.08 1.62 3.31 0 6-2.69 6-6s-2.69-6-6-6-6 2.69-6 6c0 .48.07.95.18 1.4l-14.1 8.23c-1.07-1-2.5-1.62-4.08-1.62-3.31 0-6 2.69-6 6s2.69 6 6 6c1.58 0 3.01-.62 4.08-1.62l14.25 8.31c-.1.42-.16.86-.16 1.31 0 3.22 2.61 5.83 5.83 5.83s5.83-2.61 5.83-5.83-2.61-5.83-5.83-5.83z"/>
</svg>

After

Width:  |  Height:  |  Size: 533 B

52
src/client/img/sms.svg Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 596.02863 624.86049"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="sms.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
/>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-96.271606,-161.35864)">
<path class="fill-color"
d="m 226.78571,717.53552 0,-68.68386 -4.88516,-4.70867 c -6.42608,-6.19391 -9.23116,-6.71523 -36.9412,-6.86548 -24.78746,-0.1344 -32.98397,-1.22152 -43.95079,-5.82929 -15.56012,-6.53766 -29.88171,-19.84926 -37.02898,-34.4176 -8.389993,-17.10139 -7.693873,0.8413 -7.693873,-198.31128 l 0,-177.00001 3.30919,-9.5 c 4.257043,-12.22109 10.306203,-21.86381 18.862433,-30.06785 11.61523,-11.1371 24.97171,-17.63265 40.92353,-19.90201 5.72478,-0.81442 72.02563,-1.03614 240.40485,-0.80395 261.45563,0.36054 235.55345,-0.46199 253,8.03402 7.01459,3.41591 10.16895,5.80822 18.05026,13.68953 7.8784,7.8784 10.27528,11.03826 13.69183,18.05026 8.46606,17.37539 7.75791,-0.69816 7.75791,198.00001 0,198.69816 0.70815,180.62461 -7.75791,198 -3.41655,7.012 -5.81343,10.17186 -13.69183,18.05026 -7.88131,7.88131 -11.03567,10.27362 -18.05026,13.68953 -16.96959,8.26374 -5.62767,7.61008 -142.59678,8.21816 -105.14414,0.46679 -122.36103,0.74554 -124,2.00762 -3.09839,2.3859 -36.06645,33.0732 -145.876,135.78421 -6.61497,6.1873 -12.36472,11.2498 -12.77722,11.25 -0.4125,10e-5 -0.75,-30.9075 -0.75,-68.6836 z"
id="path3353"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" version="1.0" id="layer1" viewBox="0 0 75 75"><metadata id="metadata1"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
<g id="g1"><polygon id="polygon1" points="39.389,13.769 22.235,28.606 6,28.606 6,47.699 21.989,47.699 39.389,62.75 39.389,13.769" style="stroke:currentColor;stroke-width:5;stroke-linejoin:round;fill:currentColor;"/><path id="path1" d="M 48.128,49.03 C 50.057,45.934 51.19,42.291 51.19,38.377 C 51.19,34.399 50.026,30.703 48.043,27.577" style="fill:none;stroke:currentColor;stroke-width:5;stroke-linecap:round"/>
<path id="path2" d="M 55.082,20.537 C 58.777,25.523 60.966,31.694 60.966,38.377 C 60.966,44.998 58.815,51.115 55.178,56.076" style="fill:none;stroke:currentColor;stroke-width:5;stroke-linecap:round"/>
<path id="path1" d="M 61.71,62.611 C 66.977,55.945 70.128,47.531 70.128,38.378 C 70.128,29.161 66.936,20.696 61.609,14.01" style="fill:none;stroke:currentColor;stroke-width:5;stroke-linecap:round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 240 240">
<defs>
<linearGradient id="b" x1="0.6667" y1="0.1667" x2="0.4167" y2="0.75">
<stop stop-color="#000" offset="0"/>
<stop stop-color="#000" offset="1"/>
</linearGradient>
<linearGradient id="w" x1="0.6597" y1="0.4369" x2="0.8512" y2="0.8024">
<stop stop-color="#fff" offset="0"/>
<stop stop-color="#fff" offset="1"/>
</linearGradient>
</defs>
<circle cx="120" cy="120" r="120" class = "fill-color"/>
<path class = "fill-background" fill-opacity="0.5" d="m98 175c-3.8876 0-3.227-1.4679-4.5678-5.1695L82 132.2059 170 80"/>
<path class = "fill-background" fill-opacity="0.5" d="m98 175c3 0 4.3255-1.372 6-3l16-15.558-19.958-12.035"/>
<path class = "fill-background" d="m100.04 144.41 48.36 35.729c5.5185 3.0449 9.5014 1.4684 10.876-5.1235l19.685-92.763c2.0154-8.0802-3.0801-11.745-8.3594-9.3482l-115.59 44.571c-7.8901 3.1647-7.8441 7.5666-1.4382 9.528l29.663 9.2583 68.673-43.325c3.2419-1.9659 6.2173-0.90899 3.7752 1.2584"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 194.9763 194.49711"
enable-background="new 0 0 405.661 316.98"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="whatsapp.svg"><metadata
id="metadata3422"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs3420" /><sodipodi:namedview
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview3418"
showgrid="false"
inkscape:zoom="2.8992364"
inkscape:cx="90.564335"
inkscape:cy="48.01468"
inkscape:window-x="1985"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><rect
y="-12.951568"
width="203.44708"
height="209.61963"
id="rect3408"
x="-3.27195"
style="fill:#ffffff00" /><g
id="g3410"
transform="translate(-112.956,-10.627894)"><path
d="m 112.956,205.125 c 5.281,-17.05 11.402,-33.26 16.998,-49.994 -37.095,-64.878 8.812,-137.915 70.991,-143.982 58.707,-5.729 106.841,36.439 106.987,93.988 0.153,60.723 -58.74,111.713 -124.985,90.988 -4.997,-1.563 -11.18,-6.657 -16.998,-6.999 -8.131,-0.479 -18.787,5.359 -26.997,7.999 -8.999,2.895 -16.824,5.796 -25.996,8 z m 54.993,-33.996 c 53.495,32.466 117.551,-3.949 122.985,-56.993 4.918,-48.019 -33.424,-90.745 -84.99,-86.989 -58.87,4.287 -94.232,74.559 -57.993,125.984 -3.208,8.791 -6.21,17.788 -8.999,26.997 9.822,-2.844 18.876,-6.455 28.997,-8.999 z"
id="path3412"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill-rule:evenodd" /><!--<path--><!--d="m 138.953,180.128 c 2.789,-9.209 5.791,-18.206 8.999,-26.997 -36.24,-51.425 -0.877,-121.697 57.993,-125.984 51.566,-3.756 89.908,38.97 84.99,86.989 -5.434,53.043 -69.49,89.458 -122.985,56.993 -10.122,2.544 -19.176,6.155 -28.997,8.999 z M 165.95,95.139 c 8.578,24.126 44.126,56.803 69.991,57.993 12.26,0.564 26.755,-5.796 25.996,-22.997 -7.382,-5.283 -15.892,-9.438 -24.996,-12.998 -4.358,4.307 -7.783,9.548 -12.999,12.998 -15.685,-6.979 -27.717,-17.61 -34.995,-32.996 14.331,-7.816 5.627,-25.226 0,-36.996 -22.233,-6.699 -28.087,20.681 -22.997,34.996 z"--><!--id="path3414"--><!--inkscape:connector-curvature="0"--><!--style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd" />--><path
d="m 188.947,60.143 c 5.627,11.77 14.331,29.179 0,36.996 7.278,15.386 19.311,26.017 34.995,32.996 5.216,-3.45 8.641,-8.691 12.999,-12.998 9.104,3.561 17.614,7.715 24.996,12.998 0.759,17.201 -13.736,23.562 -25.996,22.997 -25.865,-1.19 -61.414,-33.867 -69.991,-57.993 -5.09,-14.315 0.764,-41.695 22.997,-34.996 z"
id="path3416"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill-rule:evenodd" /></g></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

42
src/client/index.html Normal file
View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<link rel="icon" type="image/png" href="img/logo.png">
<meta charset="utf-8"/>
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' data: gap: cdvfile: * 'unsafe-eval';
style-src 'self' 'unsafe-inline';
media-src *; img-src 'self' * data: cdvfile: content:;
script-src 'self' data: 'unsafe-eval'" ;>
<!--Element, mit dem Foundation die ViewQueries mitteilt-->
<meta class='foundation-mq'>
<link rel="stylesheet" type="text/css" href="index.css">
<title>WordRotator</title>
<script src="scripts/sql-wasm.js"></script>
<script src="scripts/localforage.js"></script>
</head>
<body class="default">
<div id="toast-container">
<div class='toast toast-template' style="opacity: 0">
<span class='message'></span>
</div>
</div>
<div id='site'>
<div class="loader overlay">
<svg viewBox="0 0 32 32" width="32" height="32">
<circle class="spinner" cx="16" cy="16" r="14" fill="none" style="stroke: black;"></circle>
</svg>
</div>
</div>
<!--<script src='https://vjs.zencdn.net/7.4.1/video.js'></script>-->
<script type="text/javascript" src="cordova.js"></script>
</body>
</html>

View File

@@ -0,0 +1,32 @@
// import {Dialog, Helper, ThemeManager, Translator, ViewInflater} from "../../../../../js/lib/pwa-lib";
//
// export class ChooseThemeDialog extends Dialog {
//
// constructor() {
// let viewPromise = ViewInflater.inflate("html/application/Dialog/chooseTheme.html").then(view => {
//
// let template = view.querySelector("#choose-theme-template");
// template.remove();
// template.id = null;
//
// let themeTemplateContainer = view.querySelector("#theme-choose-container");
//
// for (let i = 0; i < ThemeManager.themes.length; i++) {
// let themeElem = template.cloneNode(true);
// let theme = ThemeManager.themes[i];
// themeElem.querySelector(".name").appendChild(Translator.makePersistentTranslation(theme._name));
// themeElem["dataset"]["theme"] = theme._name;
//
// themeElem.addEventListener("click", () => {
// this.result = themeElem["dataset"]["theme"];
// this.close()
// });
// themeTemplateContainer.appendChild(themeElem);
// }
//
// return view;
// });
//
// super(viewPromise, "choose-theme-Dialog-title");
// }
// }

View File

@@ -0,0 +1,7 @@
// import {ConfirmDialog, Dialog, Helper, ThemeManager, Translator, ViewInflater} from "../../../../../js/lib/pwa-lib";
//
// export class PersistDialog extends ConfirmDialog{
// constructor() {
// super(Helper.isChrome()?"persist-storage-Dialog-message":"persist-storage-Dialog-message-firefox", "persist-storage-Dialog-title");
// }
// }

View File

@@ -1,8 +1,12 @@
import {Dialog, Helper, ShareManager, ThemeManager, Translator, ViewInflater} from "../../../../../js/lib/pwa-lib";
import {Dialog} from "cordova-sites/dist/client/js/Dialog/Dialog";
import {Helper} from "js-helper/dist/shared/Helper";
import {ViewInflater} from "cordova-sites/dist/client/js/ViewInflater";
export class ShareDialog extends Dialog{
constructor() {
let viewPromise = ViewInflater.inflate("html/application/dialog/share.html").then(view => {
let viewPromise = ViewInflater.getInstance().load("html/application/Dialog/share.html").then(view => {
//TODO [MIG] ShareManager
view.appendChild(ShareManager.generateDefaultShareElement(window.location.hostname + Helper.basePath("")));
let closeListener = () => {
this.close();
@@ -14,6 +18,6 @@ export class ShareDialog extends Dialog{
return view;
});
super(viewPromise, "share-dialog");
super(viewPromise, "share-Dialog");
}
}

View File

@@ -0,0 +1,91 @@
import {CreditsSite} from "../Sites/CreditsSite";
import {PrivacyPolicySite} from "../Sites/PrivacyPolicySite";
import {ImpressumSite} from "../Sites/ImpressumSite";
import {NativeStoragePromise} from "cordova-sites/dist/client/js/NativeStoragePromise";
import {AbstractFragment} from "cordova-sites/dist/client/js/Context/AbstractFragment";
import view from "../../html/fragment/settings.html";
import {LevelData} from "../../../shared/model/LevelData";
import {LastSyncDates} from "cordova-sites-easy-sync/dist/client/LastSyncDates";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
import {Toast} from "cordova-sites/dist/client/js/Toast/Toast";
import {Matomo} from "cordova-sites/dist/client/js/Legacy/Matomo";
import {LevelPlayed} from "../model/LevelPlayed";
import {ContactSite} from "../Sites/ContactSite";
export class WordRotatorSettingFragment extends AbstractFragment {
constructor(site) {
super(site, view);
}
async onViewLoaded() {
let res = super.onViewLoaded();
this.findBy("#reset-levels").addEventListener("click", async () => {
await NativeStoragePromise.remove("currentLevel");
await NativeStoragePromise.remove("levelCounter");
await NativeStoragePromise.remove("tutorial-step");
await LevelPlayed.clear();
await LevelData.clear();
await LastSyncDates.clear();
});
if (location.hostname.includes("beta") || location.hostname.includes("127.0.0.1") || location.hostname.includes("localhost")) {
this.findBy("#reset-levels").classList.remove("hidden");
}
let playMusicButton = this.findBy("#play-music");
playMusicButton.checked = (await NativeStoragePromise.getItem("play-music", "1") === "1")
playMusicButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-music", (playMusicButton.checked) ? "1" : "0");
let soundManager = SoundManager.getInstance();
soundManager.set({muted: !playMusicButton.checked}, SoundManager.CHANNELS.MUSIC);
if (playMusicButton.checked) {
await soundManager.play(SoundManager.CHANNELS.MUSIC);
}
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlayMusic", "Play Music", (playMusicButton.checked) ? 1 : 0]);
});
let playSoundButton = this.findBy("#play-sound");
playSoundButton.checked = (await NativeStoragePromise.getItem("play-sound", "1") === "1");
playSoundButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-sound", (playSoundButton.checked) ? "1" : "0");
let soundManager = SoundManager.getInstance();
soundManager.set({muted: !playSoundButton.checked}, SoundManager.CHANNELS.SOUND);
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlaySound", "Play Sound", (playSoundButton.checked) ? 1 : 0]);
});
this.findBy("#track-switch").addEventListener("change", function (e) {
Matomo.setTrack(this.checked === true);
e.stopPropagation();
e.preventDefault();
});
this.findBy("#credits-button").addEventListener("click", () => {
this.getSite().startSite(CreditsSite);
});
this.findBy("#privacy-policy-button").addEventListener("click", () => {
this.getSite().startSite(PrivacyPolicySite);
});
this.findBy("#contact-button").addEventListener("click", () => {
// new Toast("contact site").show();
this.getSite().startSite(ContactSite);
});
this.findBy("#impressum-button").addEventListener("click", () => {
this.getSite().startSite(ImpressumSite);
});
this.findBy("#version-info").innerText = window["version"];
return res;
}
onStart() {
Matomo.update("Settings Sites");
super.onStart();
}
}

View File

@@ -0,0 +1,41 @@
import view from "../../html/sites/contactSite.html"
import {App} from "cordova-sites/dist/client/js/App";
import {Form} from "cordova-sites/dist/client/js/Form";
import {DataManager} from "cordova-sites/dist/client/js/DataManager";
import {Toast} from "cordova-sites/dist/client/js/Toast/Toast";
import {Translator} from "cordova-sites/dist/client/js/Translator";
import {MenuSite} from "cordova-sites/dist/client/js/Context/MenuSite";
export class ContactSite extends MenuSite {
constructor(siteManager) {
super(siteManager, view);
}
onViewLoaded() {
let res = super.onViewLoaded();
this.findBy("#contactText").appendChild(Translator.makePersistentTranslation("contact text", [__CONTACT_EMAIL__]))
new Form(this.findBy("#contact-form"), async values => {
let result = await DataManager.send("contact", values);
if (result.success) {
new Toast("the message was sent").show();
this.finish();
} else {
if (result) {
new Toast(result.message).show();
} else {
new Toast("Es ist ein Fehler aufgetreten...").show();
}
}
});
return res;
}
}
App.addInitialization((app) => {
app.addDeepLink("contact", ContactSite);
});

View File

@@ -0,0 +1,19 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import view from "../../html/sites/credits.html"
import {App} from "cordova-sites/dist/client/js/App";
export class CreditsSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, view);
}
onStart(args) {
// Matomo.update("Credits Sites");
return super.onStart(args);
}
}
App.addInitialization(app => {
app.addDeepLink("credits", CreditsSite);
});

View File

@@ -1,10 +1,16 @@
import {UserAction, UserSite} from "../../../../../js/lib/pwa-user-management";
import {Helper, InitPromise} from "../../../../../js/lib/pwa-lib";
import {DataManager} from "../../../../../js/lib/pwa-core";
import {UserMenuAction, UserSite} from "cordova-sites-user-management/dist/client";
export class DeleteWordsSite extends UserSite {
import view from "../../html/sites/deleteLevels.html"
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {App} from "cordova-sites/dist/client/js/App";
import {NavbarFragment} from "cordova-sites/dist/client/js/Context/Menu/NavbarFragment";
import {DataManager} from "cordova-sites/dist/client/js/DataManager";
export class DeleteWordsSite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager, "version/2/html/deleteLevels.html", null, "admin");
super(siteManager, view);
this.addDelegate(new UserSite(this, "admin"))
}
async onConstruct(args) {
@@ -13,9 +19,8 @@ export class DeleteWordsSite extends UserSite {
return res;
}
onFirstStart() {
super.onFirstStart();
onViewLoaded() {
super.onViewLoaded();
let levelTemplate = this.findBy("#level-template");
let wordTemplate = this.findBy("#word-template");
@@ -28,19 +33,19 @@ export class DeleteWordsSite extends UserSite {
wordTemplate.remove();
for (let k in this.words) {
let wordElem = Helper.cloneNode(wordTemplate);
let wordElem = wordTemplate.cloneNode(true);
wordElem.querySelector(".name").appendChild(document.createTextNode(k));
let levelContainer = wordElem.querySelector(".level-container");
for (let j = 0; j < this.words[k].length; j++) {
let level = this.words[k][j];
let levelElem = Helper.cloneNode(levelTemplate);
let levelElem = levelTemplate.cloneNode(true);
levelElem.querySelector(".id").appendChild(document.createTextNode(level["id"]));
levelElem.querySelector(".words").appendChild(document.createTextNode(level["words"]));
levelElem.querySelector(".positions").appendChild(document.createTextNode(level["rotations"]));
levelElem.querySelector(".delete-button").addEventListener("click", async () => {
let res = await DataManager.send("deleteLevel", {"levelId": level["id"]});
if (res["success"]){
if (res["success"]) {
levelElem.remove();
}
});
@@ -52,8 +57,8 @@ export class DeleteWordsSite extends UserSite {
}
}
InitPromise.addPromise(app => {
app.addDefaultAction(new UserAction("delete-levels", () => {
App.addInitialization(app => {
NavbarFragment.defaultActions.push(new UserMenuAction("delete-levels", "admin", () => {
app.startSite(DeleteWordsSite);
},null, null, "admin"))
}));
});

View File

@@ -1,13 +1,14 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {Matomo} from "../../../../../js/lib/pwa-assets";
import view from "../../html/sites/end.html"
export class EndSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, "html/application/end.html");
super(siteManager, view);
}
onStart(args) {
Matomo.update("End Site");
// Matomo.update("End Sites");
return super.onStart(args);
}
}

View File

@@ -1,12 +1,14 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {InitPromise} from "../../../../../js/lib/pwa-lib";
import view from "../../html/sites/impressum.html"
import {App} from "cordova-sites/dist/client/js/App";
export class ImpressumSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, "html/application/impressum.html", "impressum");
super(siteManager, view);
}
}
InitPromise.addPromise(app => {
App.addInitialization(app => {
app.addDeepLink("impressum", ImpressumSite);
});

View File

@@ -1,33 +1,64 @@
import {FlashMessenger, Helper, Menu, MenuAction, SystemSettings} from "../../../../../js/lib/pwa-lib";
import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer";
import {LevelHelper} from "../wordrotator/Level/LevelHelper";
import {WordRotatorDb} from "../WordRotatorDb";
import {Matomo, ScaleHelper, SoundManager} from "../../../../../js/lib/pwa-assets";
import {EndSite} from "./EndSite";
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {SettingsManager} from "../../../../../js/lib/pwa-core";
import {SimpleFourWordsLevel} from "../wordrotator/Level/SimpleFourWordsLevel";
import helpIcon from "../../img/help.png";
import {
MenuAction,
Toast,
ScaleHelper,
Matomo,
NativeStoragePromise,
} from "cordova-sites/dist/client";
import view from "../../html/sites/level.html"
import {Helper} from "js-helper/dist/shared/Helper";
import {LevelData} from "../../../shared/model/LevelData";
import {LevelPlayed} from "../model/LevelPlayed";
import {ViewHelper} from "js-helper/dist/client/ViewHelper";
import coinSound from "../../sound/single_coin_fall_on_concrete_.mp3";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
export class LevelSite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager, "html/application/level.html");
super(siteManager, view);
this._navbarFragment.setBackgroundImage(null);
}
createActionBarMenu(menu) {
menu = super.createActionBarMenu(menu);
async onCreateMenu(navbar) {
super.onCreateMenu(navbar);
let coinAction = new MenuAction(Helper.nonNull(localStorage.getItem("coins"), "0"), () => {
let coinAction = new MenuAction(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"), () => {
}, MenuAction.SHOW_ALWAYS, 900);
coinAction.setShouldTranslate(false);
coinAction._shouldTranslate = false;
coinAction._liClass = "coin-counter";
menu.addAction(coinAction);
navbar.addAction(coinAction);
this.coinAction = coinAction;
return menu;
let levelCounterAction = new MenuAction(Helper.nonNull(this.levelCounter, "1"), () => {
}, MenuAction.SHOW_ALWAYS, 900);
levelCounterAction._shouldTranslate = false;
levelCounterAction.setLiClass("level-counter");
navbar.addAction(levelCounterAction);
this.levelCounterAction = levelCounterAction;
let helpAction = new MenuAction("", () => {
this.help();
}, MenuAction.SHOW_ALWAYS, 900);
helpAction._shouldTranslate = false;
helpAction._icon = helpIcon;
helpAction.setLiClass("help-action show-while-playing");
navbar.addAction(helpAction);
return navbar;
}
onConstruct(args) {
this.levelCounter = Helper.nonNull(localStorage.getItem("levelCounter"), 1);
async onConstruct(args) {
this.levelCounter = Helper.nonNull(await NativeStoragePromise.getItem("levelCounter"), 1);
// this.levelCounter = 987;
this.levelScaler = () => {
};
this.wonParams = {
@@ -36,11 +67,10 @@ export class LevelSite extends WordRotatorBaseSite {
};
this.coinPromise = Promise.resolve();
let settingsManager = SettingsManager.getInstance();
let soundManager = SoundManager.getInstance();
soundManager.set({
audio: "sound/single_coin_fall_on_concrete_.mp3",
muted: (settingsManager.getSetting("play-sound", "1") !== "1"),
audio: coinSound,
muted: (NativeStoragePromise.getItem("play-sound", "1") !== "1"),
volume: 0.7
}, SoundManager.CHANNELS.SOUND);
@@ -49,8 +79,8 @@ export class LevelSite extends WordRotatorBaseSite {
return super.onConstruct(args);
}
async onFirstStart() {
super.onFirstStart();
async onViewLoaded() {
let res = super.onViewLoaded();
let leafSegmentTemplate = this.findBy("#segment-leaf-template");
let parentSegmentTemplate = this.findBy("#segment-parent-template");
let rowSegmentTemplate = this.findBy("#segment-row-template");
@@ -82,45 +112,39 @@ export class LevelSite extends WordRotatorBaseSite {
this.wonText = wonText;
this.wonText.style.fontSize = "0";
//Benutze Document, da Element außerhalb von Seite (eigentlich unschön!)
this.levelCounterActionContainer = document.getElementById("level-number-container");
this.levelCounterAction = document.getElementById("level-number");
this.levelCounterAction.innerText = this.levelCounter;
this.levelNumberScaler = await scaleHelper.scaleToFull(this.levelCounterAction, this.levelCounterActionContainer, false, false, 4);
this.levelCounterActionContainer.classList.add("visible");
this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate, columnTemplate);
this.coinTemplate = this.findBy("#coin-template");
this.coinContainer = this.findBy("#coin-container");
this.coinTemplate.id = null;
this.coinContainer.removeAllChildren();
ViewHelper.removeAllChildren(this.coinContainer);
this.findBy("#help-button").addEventListener("click", () => {
this.help();
});
// this.findBy("#help-button").addEventListener("click", () => {
// this.help();
// });
await this.loadLastLevel();
return res;
}
async loadLastLevel() {
try {
let currentLevelInfo = localStorage.getItem("currentLevel");
let currentLevelInfo = await NativeStoragePromise.getItem("currentLevel");
if (Helper.isNotNull(currentLevelInfo)) {
currentLevelInfo = JSON.parse(currentLevelInfo);
const db = await WordRotatorDb.getInstance();
const levelJson = await db.loadLevel(currentLevelInfo["id"]);
let levelData = await LevelData.findById(currentLevelInfo["id"]);
if (levelJson === null) {
if (Helper.isNull(levelData)) {
return this.nextLevel();
}
let level = LevelHelper.inflateLevel(levelJson, this.templateContainer);
let level = LevelHelper.inflateLevel(levelData, this.templateContainer);
level.setStartRotations(currentLevelInfo["rotations"]);
const self = this;
level.getWonPromise().then(() => {
self.levelWon(level);
this.levelWon(level);
});
level.createSegments();
@@ -130,15 +154,15 @@ export class LevelSite extends WordRotatorBaseSite {
level.saveAsCurrentLevel();
let levelSegment = this.findBy("#level");
levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement());
ViewHelper.removeAllChildren(levelSegment).appendChild(level.getRootSegment().getElement());
let scaleHelper = new ScaleHelper();
this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);
this.level = level;
let res = this.tutorial();
// let res = this.tutorial();
Matomo.push(["trackEvent", "LevelSite", "LoadLastLevel"]);
this.level.checkHasWon();
return res;
return;
}
} catch (e) {
console.error(e);
@@ -151,27 +175,38 @@ export class LevelSite extends WordRotatorBaseSite {
this.finish();
}
async nextLevel(loadingElement) {
loadingElement = Helper.nonNull(loadingElement, Helper.createLoadingSymbol());
this._siteContent.replaceWith(loadingElement);
updateLevelCounter() {
this.levelCounterAction.setName(this.levelCounter);
if (this.levelCounter >= 10 && this.levelCounter <= 99) {
this.levelCounterAction.setLiClass("num-10 level-counter");
} else if (this.levelCounter >= 100 && this.levelCounter <= 999) {
this.levelCounterAction.setLiClass("num-100 level-counter");
} else if (this.levelCounter >= 1000) {
this.levelCounterAction.setLiClass("num-1000 level-counter");
} else {
this.levelCounterAction.setLiClass("level-counter");
}
}
async nextLevel() {
this.showLoadingSymbol();
try {
const db = await WordRotatorDb.getInstance();
const nextLevelJson = await db.loadNextLevel(LevelSite.RENDERER_TYPES);
let levelData = await LevelPlayed.getNextLevelData(LevelSite.RENDERER_TYPES);
console.log("nextLevelJson", nextLevelJson);
if (nextLevelJson === null) {
if (Helper.isNull(levelData)) {
this.startEndSite();
return;
}
const level = LevelHelper.inflateLevel(nextLevelJson, this.templateContainer);
const level = LevelHelper.inflateLevel(levelData, this.templateContainer);
//Waiting for Level to be done
if (this.level && level.id === this.level.id) {
console.log("Level is the same as before! reload!");
await new Promise((resolve) => setTimeout(resolve, 50));
// return;
return this.nextLevel(loadingElement);
debugger;
return this.nextLevel();
}
level.getWonPromise().then(() => {
@@ -184,21 +219,20 @@ export class LevelSite extends WordRotatorBaseSite {
level.saveAsCurrentLevel();
let levelSegment = this.findBy("#level");
levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement());
ViewHelper.removeAllChildren(levelSegment).appendChild(level.getRootSegment().getElement());
this._siteContent.classList.remove('won');
this._view.classList.remove('won');
this.wonText.style.fontSize = "0";
loadingElement.replaceWith(this._siteContent);
this.removeLoadingSymbol();
let scaleHelper = new ScaleHelper();
this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);
this.level = level;
this.levelCounterAction.innerText = this.levelCounter;
this.levelNumberScaler();
this.updateLevelCounter();
this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0"));
this.coinAction.redraw();
this.coinAction.setName(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
// this.coinAction.redraw();
this.wonParams.aborted = true;
clearTimeout(this.wonParams.coinCounterTimer);
@@ -209,96 +243,94 @@ export class LevelSite extends WordRotatorBaseSite {
return this.tutorial();
} catch (e) {
// loadingElement.replaceWith(this._siteContent);
console.log("Fehler!");
console.error(e);
this.startEndSite();
}
}
onStart(args) {
Matomo.update("Level Site");
async onStart(args) {
Matomo.update("Level Sites");
let res = super.onStart(args);
if (this.levelCounterAction) {
this.levelCounterAction.innerText = this.levelCounter;
this.levelCounterActionContainer.classList.add("visible");
this.updateLevelCounter();
}
this.levelScaler();
let settingsManager = SettingsManager.getInstance();
//TODO Sound
let soundManager = SoundManager.getInstance();
soundManager.set({
audio: "sound/single_coin_fall_on_concrete_.mp3",
muted: (settingsManager.getSetting("play-sound", "1") !== "1"),
audio: coinSound,
muted: (await NativeStoragePromise.getItem("play-sound", "1") !== "1"),
volume: 0.7
}, SoundManager.CHANNELS.SOUND);
await this.tutorial();
return res;
}
onPause(args) {
super.onPause(args);
this.levelCounterActionContainer.classList.remove("visible");
}
async levelWon(level) {
try {
const db = await WordRotatorDb.getInstance();
const savePromise = db.saveLevelPlayed(level.getId());
const savePromise = LevelPlayed.setPlayed(level.getLevelData());
savePromise.then((r) => console.log("levelSaved!", r)).then(() => {
return db.loadLevel(level.id);
}).then(level => console.log("saved level", level));
savePromise.then((r) => console.log("levelSaved!", r));
this.levelCounter++;
localStorage.setItem("levelCounter", this.levelCounter);
await NativeStoragePromise.setItem("levelCounter", this.levelCounter);
this._siteContent.classList.add('won');
localStorage.removeItem("currentLevel");
//Todo richtiges Element aufrufen?
this._view.classList.add('won');
await NativeStoragePromise.remove("currentLevel");
let continueButton = this.findBy("#continue-button");
continueButton.style.transition = "none";
continueButton.style.opacity = 0;
this.coinContainer.removeAllChildren();
let coinsPerLevel = SystemSettings.get("coinsPerLevel", 5);
ViewHelper.removeAllChildren(this.coinContainer);
let coinsPerLevel = await NativeStoragePromise.getItem("coinsPerLevel", 5);
let coinsBefore = 0;
let soundManager = SoundManager.getInstance();
let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND);
this.coinPromise = this.coinPromise.then(() => {
coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"));
localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel));
}).then(() => {
this.coinPromise = this.coinPromise.then(async () => {
coinsBefore = parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
await NativeStoragePromise.setItem("coins", coinsBefore + parseInt(coinsPerLevel));
}).then(async () => {
return Promise.all([new Promise((r) => {
setTimeout(() => {
r(continueButton.fadeIn());
//TODO animationen einbauen
continueButton.style.opacity = 1;
r();
}, 500)
}), audioOptions.loadedPromise.catch(e => {
console.error(e)
})]);
}),
audioOptions.loadedPromise.catch(e => {
console.error(e)
})
]);
});
this.wonParams.aborted = false;
for (let i = 0; i < coinsPerLevel; i++) {
let coinElem = Helper.cloneNode(this.coinTemplate);
let coinElem = this.coinTemplate.cloneNode(true);
this.coinContainer.appendChild(coinElem);
this.coinPromise = this.coinPromise.then(() => {
return new Promise(r => {
let timeout = 350;
if (!this.wonParams.aborted) {
coinElem.fadeIn(timeout / 1000);
//TODO animationen einbauen
coinElem.style.opacity = 1;
// coinElem.fadeIn(timeout / 1000);
soundManager.play(SoundManager.CHANNELS.SOUND);
this.wonParams.coinCounterTimer = setTimeout(() => {
if (!this.wonParams.aborted) {
this.coinAction.setTitle(++coinsBefore);
this.coinAction.redraw();
this.coinAction.setName(++coinsBefore);
// this.coinAction.redraw();
}
}, timeout / 2);
} else {
@@ -318,7 +350,14 @@ export class LevelSite extends WordRotatorBaseSite {
this.continueButtonScaler();
this.levelScaler();
Matomo.push(["trackEvent", "LevelSite", "LevelWon", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
Matomo.push(["trackEvent", "LevelSite", "LevelWon", "Coins", parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"))]);
let leafs = level.getLeafSegments();
leafs.forEach((leaf, i) => {
let elem = leaf.getElement();
elem.style.animationDelay = i*50+"ms";
elem.classList.add("jump-animation");
})
await savePromise;
} catch (e) {
@@ -326,15 +365,14 @@ export class LevelSite extends WordRotatorBaseSite {
}
}
help() {
let cost = SystemSettings.get("costForHelp", 25);
let currentCoins = parseInt(Helper.nonNull(localStorage.getItem("coins"), 0));
async help() {
let cost = await NativeStoragePromise.getItem("costForHelp", 25);
let currentCoins = parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), 0));
if (currentCoins >= cost) {
currentCoins -= cost;
localStorage.setItem("coins", currentCoins);
this.coinAction.title = currentCoins;
this.coinAction.redraw();
await NativeStoragePromise.setItem("coins", currentCoins);
this.coinAction.setName(currentCoins);
let rotatables = this.level.getRotatableSegments();
rotatables = rotatables.filter((segment) => {
@@ -350,26 +388,26 @@ export class LevelSite extends WordRotatorBaseSite {
segmentToHelp.setIsRotatable(false);
this.level.saveAsCurrentLevel();
Matomo.push(["trackEvent", "LevelSite", "Help", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
// Matomo.push(["trackEvent", "LevelSite", "Help", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
} else {
FlashMessenger.addMessage("not-enough-coins");
Matomo.push(["trackEvent", "LevelSite", "Help", "Not enough Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
new Toast("not-enough-coins").show();
// Matomo.push(["trackEvent", "LevelSite", "Help", "Not enough Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
}
}
async tutorial() {
if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) {
let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "1");
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "1");
let scaleHelper = new ScaleHelper();
this._siteContent.classList.add("tutorial");
this._siteContent.classList.add("step-" + currentStep);
this._view.classList.add("tutorial");
this._view.classList.add("step-" + currentStep);
switch (currentStep) {
case "1": {
this.level.setSegmentClickedListener(() => {
this._siteContent.classList.remove("step-1");
localStorage.setItem("tutorial-step", "2");
this.level.setSegmentClickedListener(async () => {
this._view.classList.remove("step-1");
await NativeStoragePromise.setItem("tutorial-step", "2");
this.tutorial();
});
@@ -383,15 +421,15 @@ export class LevelSite extends WordRotatorBaseSite {
case "2": {
this.level.setSegmentClickedListener(() => {
});
this.level.getWonPromise().then(() => {
this._siteContent.classList.remove("tutorial");
this._siteContent.classList.remove("step-2");
localStorage.removeItem("tutorial-step");
this.coinPromise = this.coinPromise.then(() => {
FlashMessenger.addMessage("extra-coins-after-first-level");
localStorage.setItem("coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")) + 50);
this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0"));
this.coinAction.redraw();
this.level.getWonPromise().then(async () => {
this._view.classList.remove("tutorial");
this._view.classList.remove("step-2");
await NativeStoragePromise.remove("tutorial-step");
this.coinPromise = this.coinPromise.then(async () => {
new Toast("extra-coins-after-first-level").show();
await NativeStoragePromise.setItem("coins", parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0")) + 50);
this.coinAction.setName(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
// this.coinAction.redraw();
});
// this.levelScaler();
});
@@ -404,27 +442,27 @@ export class LevelSite extends WordRotatorBaseSite {
break;
}
default: {
this._siteContent.classList.remove("tutorial");
this._view.classList.remove("tutorial");
}
}
} else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) {
let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "3");
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "3");
switch (currentStep) {
case "3": {
let scaleHelper = new ScaleHelper();
this._siteContent.classList.add("tutorial");
this._siteContent.classList.add("step-" + currentStep);
this._view.classList.add("tutorial");
this._view.classList.add("step-" + currentStep);
let eventListener = () => {
this._siteContent.classList.remove("tutorial");
this._siteContent.classList.remove("step-3");
localStorage.setItem("tutorial-step", "4");
this.findBy("#help-button").removeEventListener("click", eventListener);
let eventListener = async () => {
this._view.classList.remove("tutorial");
this._view.classList.remove("step-3");
await NativeStoragePromise.setItem("tutorial-step", "4");
// this.findBy("#help-button").removeEventListener("click", eventListener);
this.levelScaler();
};
this.findBy("#help-button").addEventListener("click", eventListener);
this.findBy(".help-action").addEventListener("click", eventListener);
let textElem = this.findBy(".tutorial-text .step-3");
@@ -433,33 +471,31 @@ export class LevelSite extends WordRotatorBaseSite {
break;
}
default: {
this._siteContent.classList.remove("tutorial");
this._view.classList.remove("tutorial");
}
}
} else if (this.level.id === LevelSite.TUTORIAL.BIG_SEGMENT_LEVEL) {
let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "4");
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "4");
switch (currentStep) {
case "4": {
let scaleHelper = new ScaleHelper();
this._siteContent.classList.add("tutorial");
this._siteContent.classList.add("step-" + currentStep);
this._view.classList.add("tutorial");
this._view.classList.add("step-" + currentStep);
let rotatableSegments = this.level.getRotatableSegments();
let firstSegment = rotatableSegments[2];
console.log(firstSegment);
let pointer = this.findBy("#tutorial-pointer");
pointer.remove();
firstSegment.element.appendChild(pointer);
this.level.setSegmentClickedListener((segment) => {
console.log("clicked Segment", segment);
this.level.setSegmentClickedListener(async (segment) => {
if (firstSegment === segment) {
this._siteContent.classList.remove("tutorial");
this._siteContent.classList.remove("step-4");
localStorage.setItem("tutorial-step", "5");
this._view.classList.remove("tutorial");
this._view.classList.remove("step-4");
await NativeStoragePromise.setItem("tutorial-step", "5");
this.levelScaler();
}
});
@@ -472,7 +508,7 @@ export class LevelSite extends WordRotatorBaseSite {
break;
}
default: {
this._siteContent.classList.remove("tutorial");
this._view.classList.remove("tutorial");
}
}
}
@@ -480,6 +516,7 @@ export class LevelSite extends WordRotatorBaseSite {
}
LevelSite.RENDERER_TYPES = [20, 40, 60, 80, 81, 82, 83, 100, 110, 111, 112, 120, 140, 160];
// LevelSite.RENDERER_TYPES = [120, 140, 160];
LevelSite.TUTORIAL = {
FIRST_LEVEL: 67,
SECOND_LEVEL: 15,

View File

@@ -1,22 +1,43 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {App, Toast, DataManager, ScaleHelper} from "cordova-sites/dist/client";
import {Helper} from "js-helper/dist/shared";
import {LevelSite} from "./LevelSite";
import {Matomo, ScaleHelper, SoundManager} from "../../../../../js/lib/pwa-assets";
import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer";
import {MainMenuLevel} from "../wordrotator/Level/MainMenuLevel";
import {FlashMessenger, Helper, InitPromise, ShareManager} from "../../../../../js/lib/pwa-lib";
import {DataManager, SettingsManager} from "../../../../../js/lib/pwa-core";
import {WordRotatorDb} from "../WordRotatorDb";
import {ShareDialog} from "../dialog/ShareDialog";
import view from "../../html/sites/menu.html"
import {NativeStoragePromise} from "cordova-sites/dist/client";
import {ViewHelper} from "js-helper/dist/client/ViewHelper";
import {LevelPlayed} from "../model/LevelPlayed";
import {SyncJob} from "cordova-sites-easy-sync/dist/client/SyncJob";
import {LevelData} from "../../../shared/model/LevelData";
import {ShareManager} from "cordova-sites/dist/client/js/ShareManager/ShareManager";
import {Translator} from "cordova-sites/dist/client/js/Translator";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
import {Matomo} from "cordova-sites/dist/client/js/Legacy/Matomo";
import {MenuAction} from "cordova-sites/dist/client/js/Context/Menu/MenuAction/MenuAction";
import {SettingsSite} from "./SettingsSite";
export class MenuSite extends WordRotatorBaseSite {
import settingsIcon from "../../img/settings.png";
export class MainMenuSite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager, "html/application/menu.html");
this.loadLevelPromise = this.loadLevels();
super(siteManager, view);
this.loadLevelPromise = new SyncJob().sync([LevelData]).catch(e => console.error(e));
this.listener = null;
this._navbarFragment.setCanGoBack(false);
}
onStart(args) {
Matomo.update("Menu Site");
onCreateMenu(navbar) {
super.onCreateMenu(navbar);
let settingsAction = new MenuAction("", () => {
this.startSite(SettingsSite);
}, MenuAction.SHOW_ALWAYS, null, settingsIcon);
navbar.addAction(settingsAction);
return navbar;
}
async onStart(args) {
// Matomo.update("Menu Sites");
let res = super.onStart(args);
let level = new MainMenuLevel(this.templateContainer);
@@ -24,7 +45,7 @@ export class MenuSite extends WordRotatorBaseSite {
level.createSegments();
level.getWonPromise().then(() => {
Matomo.push(["trackEvent", "MainMenu", "levelSolved"]);
// Matomo.push(["trackEvent", "MainMenu", "levelSolved"]);
this.startLevelSite();
});
@@ -32,7 +53,7 @@ export class MenuSite extends WordRotatorBaseSite {
segment._updateElement();
let levelSegment = this.findBy("#level");
levelSegment.removeAllChildren().appendChild(segment.getElement());
ViewHelper.removeAllChildren(levelSegment).appendChild(segment.getElement());
let rotationsSegments = level.getRotatableSegments();
@@ -67,14 +88,13 @@ export class MenuSite extends WordRotatorBaseSite {
this.listener = async () => {
let playButton = this.findBy("#play-button");
let levelNumber = this.findBy("#level-number");
levelNumber.innerText = Helper.nonNull(localStorage.getItem("levelCounter"), 1);
levelNumber.innerText = Helper.nonNull(await NativeStoragePromise.getItem("levelCounter"), 1);
let levelSegment = this.findBy("#level");
let scaleHelper = new ScaleHelper();
await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 2, 8, null, false);
// debugger;
let levelStyle = getComputedStyle(levelSegment);
playButton.style.width = levelStyle.getPropertyValue("width");
scaleHelper.scaleToFull(playButton.children[0], playButton, null, null, null, 4, null, false);
@@ -83,25 +103,26 @@ export class MenuSite extends WordRotatorBaseSite {
scaleHelper.scaleToFull(levelNumber, levelNumber.parentElement, false, false, 8, null, null, false);
};
this.listener();
// this.listener();
window.addEventListener("resize", this.listener);
setTimeout(this.listener, 50);
//Musikbuttons update, falls in den Einstellungen umgestellt
let settingsManager = SettingsManager.getInstance();
// let settingsManager = SettingsManager.getInstance();
let playSoundButton = this.findBy("#play-sound");
playSoundButton.checked = (settingsManager.getSetting("play-sound", "1") === "1");
playSoundButton.checked = (await NativeStoragePromise.getItem("play-sound", "1") === "1");
let playMusicButton = this.findBy("#play-music");
playMusicButton.checked = (settingsManager.getSetting("play-music", "1") === "1");
playMusicButton.checked = (await NativeStoragePromise.getItem("play-music", "1") === "1");
return res;
}
async startLevelSite() {
SoundManager.getInstance().resumeContext();
this.startSite(LevelSite, Promise.race([this.loadLevelPromise, new Promise(async resolve => {
const db = await WordRotatorDb.getInstance();
let level = await db.loadNextLevel(LevelSite.RENDERER_TYPES);
if (level !== null) {
let levelData = await LevelPlayed.getNextLevelData(LevelSite.RENDERER_TYPES);
if (levelData !== null) {
resolve();
}
})]));
@@ -112,7 +133,7 @@ export class MenuSite extends WordRotatorBaseSite {
let playButton = this.findBy("#play-button");
playButton.addEventListener("click", () => {
Matomo.push(["trackEvent", "MainMenu", "startButton"]);
// Matomo.push(["trackEvent", "MainMenu", "startButton"]);
this.startLevelSite();
});
@@ -133,38 +154,41 @@ export class MenuSite extends WordRotatorBaseSite {
this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate);
if (Helper.nonNull(MenuSite.app._cookieClosePromise)) {
MenuSite.app._cookieClosePromise.then(() => {
if (Helper.nonNull(MainMenuSite.app._cookieClosePromise)) {
MainMenuSite.app._cookieClosePromise.then(() => {
if (this.listener) {
this.listener();
}
});
}
let settingsManager = SettingsManager.getInstance();
let soundManager = SoundManager.getInstance();
let playMusicButton = this.findBy("#play-music");
playMusicButton.checked = (settingsManager.getSetting("play-music", "1") === "1");
playMusicButton.addEventListener("change", () => {
settingsManager.setSetting("play-music", (playMusicButton.checked) ? "1" : "0");
playMusicButton.checked = (await NativeStoragePromise.getItem("play-music", "1") === "1");
playMusicButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-music", (playMusicButton.checked) ? "1" : "0");
soundManager.set({muted: !playMusicButton.checked}, SoundManager.CHANNELS.MUSIC);
if (playMusicButton.checked) {
soundManager.play(SoundManager.CHANNELS.MUSIC);
}
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlayMusic", "Play Music", (playMusicButton.checked) ? 1 : 0]);
});
let playSoundButton = this.findBy("#play-sound");
playSoundButton.checked = (settingsManager.getSetting("play-sound", "1") === "1");
playSoundButton.addEventListener("change", () => {
settingsManager.setSetting("play-sound", (playSoundButton.checked) ? "1" : "0");
playSoundButton.checked = (await NativeStoragePromise.getItem("play-sound", "1") === "1");
playSoundButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-sound", (playSoundButton.checked) ? "1" : "0");
soundManager.set({muted: !playSoundButton.checked}, SoundManager.CHANNELS.SOUND);
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlaySound", "Play Sound", (playSoundButton.checked) ? 1 : 0]);
});
this.findBy("#share-button").addEventListener("click", () => {
new ShareDialog().show();
new ShareManager().share(Translator.getInstance().translate("share-text", [window.location]));
});
// this.findBy("#share-buttons").appendChild(ShareManager.generateDefaultShareElement("https://wordrotator.silas.link"));
}
@@ -172,7 +196,7 @@ export class MenuSite extends WordRotatorBaseSite {
onPause(args) {
clearTimeout(this.randomRotateTimeout);
window.removeEventListener("resize", this.listener);
super.onPause(args);
return super.onPause(args);
}
async loadLevels() {
@@ -192,7 +216,7 @@ export class MenuSite extends WordRotatorBaseSite {
}));
if (!res["success"]) {
if (await db.loadNextLevel(LevelSite.RENDERER_TYPES) === null) {
FlashMessenger.addMessage("sync-error", null, 6000);
new Toast("sync-error", 6000).show();
}
newLastSync = null;
break;
@@ -214,20 +238,20 @@ export class MenuSite extends WordRotatorBaseSite {
await db.saveManyLevels(levels);
if (newLastSync != null && newLastSync !== "null") {
localStorage.setItem("date-last-sync", newLastSync);
await NativeStoragePromise.setItem("date-last-sync", newLastSync);
db.saveDateLastSync(newLastSync);
}
}
catch(e){
// if (await db.loadNextLevel(LevelSite.RENDERER_TYPES) === null) {
FlashMessenger.addMessage("sync-error", null, 6000);
new Toast("sync-error", 6000);
// }
console.error(e);
}
}
}
MenuSite.app = null;
InitPromise.addPromise(app => {
MenuSite.app = app;
MainMenuSite.app = null;
App.addInitialization(app => {
MainMenuSite.app = app;
});

View File

@@ -1,13 +1,15 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {Helper, InitPromise} from "../../../../../js/lib/pwa-lib";
import {Matomo} from "../../../../../js/lib/pwa-assets";
import view from "../../html/sites/privacyPolicy.html"
import {App} from "cordova-sites/dist/client/js/App";
import {Matomo} from "cordova-sites/dist/client/js/Legacy/Matomo";
export class PrivacyPolicySite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager, "html/application/privacyPolicy.html", "privacyPolicy");
super(siteManager,view);
}
onFirstStart() {
async onViewLoaded() {
let trackSwitch =this.findBy("#track-switch");
trackSwitch.addEventListener("change", function (e) {
@@ -15,19 +17,18 @@ export class PrivacyPolicySite extends WordRotatorBaseSite {
e.stopPropagation();
e.preventDefault();
});
super.onFirstStart();
return super.onViewLoaded();
}
onStart(args) {
async onStart(args) {
let trackSwitch =this.findBy("#track-switch");
let shouldTrack = (Helper.nonNull(localStorage.getItem("matomoShouldTrack"), "1") === "1");
trackSwitch.checked = shouldTrack;
trackSwitch.checked = ((await Matomo.getTrackingPromise()) === "1");
Matomo.update("Privacy Policy Site");
// Matomo.update("Privacy Policy Sites");
return super.onStart(args);
}
}
InitPromise.addPromise(app => {
App.addInitialization(app => {
app.addDeepLink("privacyPolicy", PrivacyPolicySite);
});

View File

@@ -1,11 +1,17 @@
import {Helper, InitPromise} from "../../../../../js/lib/pwa-lib";
import {UserAction, UserSite} from "../../../../../js/lib/pwa-user-management";
import {DataManager} from "../../../../../js/lib/pwa-core";
export class SelectWordsSite extends UserSite{
import view from "../../html/sites/selectWords.html"
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {UserMenuAction, UserSite} from "cordova-sites-user-management/dist/client";
import {NavbarFragment} from "cordova-sites/dist/client/js/Context/Menu/NavbarFragment";
import {App} from "cordova-sites/dist/client/js/App";
import {DataManager} from "cordova-sites/dist/dist/client/js/DataManager";
import {ViewHelper} from "js-helper/dist/client/ViewHelper";
export class SelectWordsSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, "version/2/html/selectWords.html", null, "select-words");
super(siteManager, view);
this.addDelegate(new UserSite("select-words"))
}
async onConstruct(args) {
@@ -16,8 +22,8 @@ export class SelectWordsSite extends UserSite{
return res;
}
onFirstStart() {
super.onFirstStart();
async onViewLoaded() {
let res = super.onViewLoaded();
this.findBy("#not-checked").appendChild(document.createTextNode(this.stats["wordsNotChecked"]));
this.findBy("#checked").appendChild(document.createTextNode(this.stats["wordsChecked"]));
this.findBy("#not-sure").appendChild(document.createTextNode(this.stats["wordsUnsure"]));
@@ -32,7 +38,7 @@ export class SelectWordsSite extends UserSite{
let numWords = this.words.length;
for (let i = 0; i < numWords; i++) {
let wordElement = Helper.cloneNode(template);
let wordElement = template.cloneNode(true);
wordElement.dataset["id"] = -1;
this.setWord(wordElement, this.words[i]);
container.appendChild(wordElement);
@@ -61,16 +67,17 @@ export class SelectWordsSite extends UserSite{
this.setWord(wordElement, newWord[0]);
});
}
return res;
}
setWord(wordElement, word){
wordElement.querySelector(".word").removeAllChildren().appendChild(document.createTextNode(word["word"]));
ViewHelper.removeAllChildren(wordElement.querySelector(".word")).appendChild(document.createTextNode(word["word"]));
wordElement.dataset["id"] = word["id"];
}
}
InitPromise.addPromise(app => {
app.addDefaultAction(new UserAction("select-words", () => {
App.addInitialization(app => {
NavbarFragment.defaultActions.push(new UserMenuAction("select-words", "select-words", () => {
app.startSite(SelectWordsSite);
}, null, null, "select-words"));
}));
});

View File

@@ -0,0 +1,17 @@
import view from "../../html/sites/settingsSite.html"
import {MenuSite} from "cordova-sites/dist/client/js/Context/MenuSite";
import {WordRotatorSettingFragment} from "../Fragment/WordRotatorSettingFragment";
import {App} from "cordova-sites/dist/client/js/App";
export class SettingsSite extends MenuSite {
constructor(siteManager) {
super(siteManager, view);
this.addFragment("#wordRotatorSettings", new WordRotatorSettingFragment(this));
}
}
App.addInitialization((app) => {
app.addDeepLink("settings", SettingsSite);
});

View File

@@ -0,0 +1,12 @@
import {MenuSite} from "cordova-sites/dist/client";
export class WordRotatorBaseSite extends MenuSite {
async onViewLoaded() {
let res = super.onViewLoaded();
await this.onFirstStart();
return res;
}
async onFirstStart(){}
}

View File

View File

@@ -0,0 +1,78 @@
import {BaseModel} from "cordova-sites-database/dist/BaseModel";
import {BaseDatabase} from "cordova-sites-database/dist/cordova-sites-database";
import {LevelData} from "../../../shared/model/LevelData";
import {Helper} from "js-helper/dist/shared/Helper";
export class LevelPlayed extends BaseModel {
levelData: LevelData;
played: boolean;
static getColumnDefinitions() {
let columns = super.getColumnDefinitions();
columns["played"] = {type: BaseDatabase.TYPES.BOOLEAN, default: true};
return columns;
}
static getRelationDefinitions() {
let relations = super.getRelationDefinitions();
relations["levelData"] = {
target: LevelData.getSchemaName(),
type: "one-to-one",
joinColumn: true,
cascade: true,
};
return relations;
}
static async setPlayed(levelData, played?){
played = Helper.nonNull(played, true);
let levelPlayed = new LevelPlayed();
levelPlayed.levelData = levelData;
levelPlayed.played = played;
return await levelPlayed.save();
}
static async getNextLevelData(renderer){
let qb = await this._database.createQueryBuilder(LevelData);
qb = qb.select("COUNT(*) as count, difficulty")
.leftJoin(LevelPlayed, "levelPlayed", "levelPlayed.levelData = LevelData.id")
.where("(deleted = 0 OR deleted = 'false')")
.andWhere("renderer IN ("+renderer.join(",")+")")
.andWhere("(levelPlayed.id IS NULL OR levelPlayed.played = 0)")
.groupBy("difficulty")
.orderBy("difficulty, LevelData.id");
let countRes = await qb.getRawMany();
let difficulty = null;
let offset = null;
if (!countRes.some(res => {
if (res["count"] > 0){
difficulty = res["difficulty"];
offset = Math.floor(Math.random() * Math.floor(res["count"]));
return true;
}
return false;
})){
return null;
}
qb = await this._database.createQueryBuilder(LevelData);
qb = qb
.leftJoin(LevelPlayed, "levelPlayed", "levelPlayed.levelData = LevelData.id")
.where("(deleted = 0 OR deleted = 'false')")
.andWhere("difficulty = "+difficulty)
.andWhere("renderer IN ("+renderer.join(",")+")")
.andWhere("(levelPlayed.id IS NULL OR levelPlayed.played = 0)")
.orderBy("LevelData.id")
.limit(1)
.offset(offset);
return await qb.getOne();
}
}
BaseDatabase.addModel(LevelPlayed);

View File

@@ -0,0 +1,14 @@
import {MigrationInterface, QueryRunner, Table} from "typeorm";
import {MigrationHelper} from "js-helper/dist/shared";
import {LevelPlayed} from "../LevelPlayed";
export class ClientSetup1000000002001 implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<any> {
await MigrationHelper.addTableFromModelClass(LevelPlayed, queryRunner);
}
down(queryRunner: QueryRunner): Promise<any> {
return undefined;
}
}

View File

109
src/client/js/script.js Normal file
View File

@@ -0,0 +1,109 @@
import translationGerman from '../translations/de.json';
import translationEn from '../translations/en.json';
import {App, Translator, DataManager, Toast} from "cordova-sites/dist/client";
import "cordova-sites-user-management/dist/client/js/translationInit"
import "cordova-sites/dist/client/js/translationInit"
import {LoginSite, RegistrationSite, UserManager} from "cordova-sites-user-management/dist/client";
import {BaseDatabase} from "cordova-sites-database/dist/cordova-sites-database";
import {DeleteUserManagement1000000000000} from "cordova-sites-user-management/dist/shared//migrations/DeleteUserManagement";
import {SetupUserManagement1000000001000} from "cordova-sites-user-management/dist/shared/migrations/SetupUserManagement";
import {Setup1000000002000} from "../../shared/model/migration/shared/Setup";
import {SetupEasySync1000000000500} from "cordova-sites-easy-sync/dist/client";
import {MainMenuSite} from "./Sites/MainMenuSite";
import {ClientSetup1000000002001} from "./model/migration/ClientSetup";
import {EasySyncClientDb} from "cordova-sites-easy-sync/dist/client/EasySyncClientDb";
import {NavbarFragment} from "cordova-sites/dist/client/js/Context/Menu/NavbarFragment";
import {NativeStoragePromise} from "cordova-sites/dist/client/js/NativeStoragePromise";
import music from "../sound/brightAndBeautifull__.mp3";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
window["JSObject"] = Object;
//Disable Google Analytics for VideoJS
window["HELP_IMPROVE_VIDEOJS"] = false;
LoginSite.ADD_LOGIN_ACTION = false;
RegistrationSite.ADD_REGISTRATION_ACTION = false;
App.addInitialization(async () => {
Translator.init({
translations: {
"de": translationGerman,
"en": translationEn
},
fallbackLanguage: "de",
// markTranslations: true,
markUntranslatedTranslations: true,
});
//Setting Title
NavbarFragment.title = "WordRotator";
let soundManager = SoundManager.getInstance();
soundManager.play(SoundManager.CHANNELS.MUSIC, {
audio: music,
loop: true,
volume: 0.6,
muted: (await NativeStoragePromise.getItem("play-music", "1") !== "1")
}).catch(e => console.error(e));
await UserManager.getInstance().getMe().catch(e => console.error(e));
UserManager.getInstance().addLoginChangeCallback(async (isLoggedIn) => {
if (isLoggedIn) {
// await new SyncJob().sync([UserManager.syncParamFor(Definition), UserManager.syncParamFor(ExerciseProgress), UserManager.syncParamFor(WrongAnswer)]).catch(e => console.error(e));
}
});
});
DataManager._basePath = __HOST_ADDRESS__;
DataManager.onlineCallback = isOnline => {
if (!isOnline){
new Toast("not online!").show();
}
};
Object.assign(BaseDatabase.CONNECTION_OPTIONS, {
logging: ["error",],
synchronize: false,
migrationsRun: true,
migrations: [
DeleteUserManagement1000000000000,
SetupEasySync1000000000500,
SetupUserManagement1000000001000,
Setup1000000002000,
ClientSetup1000000002001,
]
});
let app = new App();
app.start(MainMenuSite).catch(e => console.error(e)).then(async () => {
window["queryDb"] = async (sql) => {
// SELECT name FROM my_db.sqlite_master WHERE type='table';
// console.log("DB", EasySyncClientDb.getInstance());
let res = await EasySyncClientDb.getInstance().rawQuery(sql);
console.log(res);
return res;
}
});
app.ready(() => {
console.log("initialisation over", new Date());
if (device.platform === "browser"){
// Check that service workers are supported
if ('serviceWorker' in navigator) {
// Use the window load event to keep the page load performant
window.addEventListener('load', () => {
navigator.serviceWorker.register('service-worker.js');
});
}
}
});

5
src/client/js/sw.js Normal file
View File

@@ -0,0 +1,5 @@
import {precacheAndRoute} from "workbox-precaching";
const precacheManifest = self.__WB_MANIFEST;
precacheAndRoute(precacheManifest || []);

View File

@@ -1,6 +1,5 @@
import {Level} from "./Level";
import {RowSegment} from "../Segment/RowSegment";
import {TriangleSegment} from "../Segment/TriangleSegment";
import {ParentSegment} from "../Segment/ParentSegment";
export class FourWordsLevel extends Level {

View File

@@ -0,0 +1,218 @@
import {LeafSegment} from "../Segment/LeafSegment";
import {ParentSegment} from "../Segment/ParentSegment";
import {Helper} from "js-helper/dist/shared/Helper";
import {NativeStoragePromise} from "cordova-sites/dist/client";
import {Random} from "js-helper";
export class Level {
constructor(templateContainer) {
this.rootSegment = null;
this.words = [];
this.startRotations = [];
this.templateContainer = templateContainer;
this.levelData = null;
this.hasWon = false;
this.id = null;
this.wonResolver = null;
this.giveUpResolver = null;
this._shakeLeafs = true;
this._shakeLeafsTimeout = null;
this._lastRotation = 0;
this.wonPromise = new Promise((resolve, reject) => {
this.wonResolver = resolve;
this.giveUpResolver = reject;
});
this.segmentClickedListener = () => {
console.log("clicked")
};
}
getLevelData() {
return this.levelData;
}
setLevelData(levelData) {
this.levelData = levelData;
}
async saveAsCurrentLevel() {
let rotations = this.getCurrentRotations();
let locked = this.getCurrentLocked();
await NativeStoragePromise.setItem("currentLevel", JSON.stringify({
"id": this.id,
"rotations": rotations,
"locks": locked
}));
}
getCurrentLocked() {
if (this.rootSegment !== null) {
return this.rootSegment.getCurrentLocked([]);
}
return [];
}
getCurrentRotations() {
if (this.rootSegment !== null) {
return this.rootSegment.getCurrentRotations([]);
}
return [];
}
setLocks(locks) {
if (this.rootSegment !== null) {
this.rootSegment.applyLocks(locks);
}
}
setId(id) {
this.id = id;
}
getId() {
return this.id;
}
getLevel() {
return this;
}
setRootSegment(rootSegment) {
this.rootSegment = rootSegment;
this.rootSegment.setParent(this);
if (this.startRotations) {
this.applyRotations();
}
}
setWords(words) {
this.words = [];
for (let i = 0, n = words.length; i < n; i++) {
this.words.push(words[i].replace(/ß/g, "ẞ").toUpperCase());
}
}
setStartRotations(rotations) {
this.startRotations = rotations;
}
applyRotations(rotations) {
if (this.rootSegment) {
rotations = Helper.nonNull(rotations, this.startRotations);
this.rootSegment.applyRotations(rotations);
}
}
getHasWon() {
return this.hasWon;
}
checkHasWon(delayPromise) {
if (this.rootSegment.isSolved()) {
this.hasWon = true;
const self = this;
Promise.resolve(delayPromise).then(() => {
self.wonResolver(true);
});
return true;
}
this.saveAsCurrentLevel();
return false;
}
getWonPromise() {
return this.wonPromise;
}
getRootSegment() {
return this.rootSegment;
}
createSegments() {
};
getRotatableSegments() {
return Level._getRotatableSegmentsFrom(this.rootSegment);
}
segmentClicked(segment) {
if (this.segmentClickedListener) {
this.segmentClickedListener(segment);
}
this._lastRotation = new Date().getTime();
clearTimeout(this._shakeLeafsTimeout);
if (this._shakeLeafs) {
this._shakeLeafsTimeout = setTimeout(() => {
this.shakeLeafs();
}, Random.getIntRandom(5000) + 25000);
}
}
setSegmentClickedListener(listener) {
this.segmentClickedListener = listener;
}
getLeafSegments() {
return Level._getLeafSegmentsFrom(this.rootSegment);
}
static _getRotatableSegmentsFrom(segment) {
let rotatable = [];
if (segment.canRotate()) {
rotatable.push(segment);
}
if (segment instanceof ParentSegment) {
for (let i = 0; i < segment.children.length; i++) {
rotatable.push.apply(rotatable, Level._getRotatableSegmentsFrom(segment.children[i]));
}
}
return rotatable;
}
shakeLeafs() {
clearTimeout(this._shakeLeafsTimeout);
if (this._shakeLeafs && !this.hasWon) {
const leafs = this.getLeafSegments();
if (leafs.length > 0) {
const index = Random.getIntRandom(leafs.length-1);
const leaf = leafs[index];
leaf.getElement().classList.add("shake");
setTimeout(() => {
leaf.getElement().classList.remove("shake");
}, Random.getIntRandom(350)+650);
}
this._shakeLeafsTimeout = setTimeout(() => {
this.shakeLeafs();
}, Random.getIntRandom(2000) + 5000);
}
}
static _createLeafsForWord(word, leafSegmentTemplate) {
let leafSegments = [];
for (let i = 0, n = word.length; i < n; i++) {
leafSegments.push(new LeafSegment(leafSegmentTemplate.cloneNode(true), word.charAt(i)));
}
return leafSegments;
}
static _getLeafSegmentsFrom(segment) {
let leafs = [];
if (segment instanceof LeafSegment) {
leafs.push(segment);
} else if (segment instanceof ParentSegment) {
for (let i = 0; i < segment.children.length; i++) {
leafs.push(...Level._getLeafSegmentsFrom(segment.children[i]));
}
}
return leafs;
}
}

View File

@@ -22,18 +22,20 @@ export class LevelHelper {
return LevelHelper.types[type];
}
static inflateLevel(jsonLevel, templateContainer) {
let level = new (LevelHelper.types[jsonLevel["rendererType"]])(templateContainer);
level.setWords(jsonLevel["words"]);
level.setId(jsonLevel["id"]);
static inflateLevel(levelData, templateContainer) {
let level = new (LevelHelper.types[levelData["renderer"]])(templateContainer);
level.setWords(JSON.parse(levelData["words"].replace(/&quot;/g, '"')));
level.setId(levelData["id"]);
level.setLevelData(levelData);
for (let i = 0, n = jsonLevel["rotations"].length; i < n; i++) {
if (jsonLevel["rotations"][i] <= 4) {
jsonLevel["rotations"][i] = 90 * jsonLevel["rotations"][i];
levelData["positions"] = JSON.parse(levelData["positions"]);
for (let i = 0, n = levelData["positions"].length; i < n; i++) {
if (levelData["positions"][i] <= 4) {
levelData["positions"][i] = 90 * levelData["positions"][i];
}
}
level.setStartRotations(jsonLevel["rotations"]);
level.setStartRotations(levelData["positions"]);
return level;
}
}

Some files were not shown because too many files have changed in this diff Show More