Rewrited with TypeScript, VueJS, ESLint, Babel, JavaScript, HTML, CSS, JSON

This commit is contained in:
Eugene Serb 2022-07-14 17:50:28 +03:00
parent de9277464a
commit c4dd4d3b0a
28 changed files with 1912 additions and 982 deletions

4
.browserslistrc Normal file
View File

@ -0,0 +1,4 @@
> 1%
last 2 versions
not dead
not ie 11

18
.eslintrc.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/typescript/recommended'
],
parserOptions: {
ecmaVersion: 2020
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}

View File

@ -15,4 +15,4 @@
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});</script><script defer="defer" src="/js/chunk-vendors.bef850cd.js"></script><script defer="defer" src="/js/app.098507b7.js"></script><link href="/css/app.a951805a.css" rel="stylesheet"></head><body><header class="header"><div class="header-wrapper container"><div class="logo-wrapper"><span class="logo-wrapper__logo">Wavelovers</span></div><nav class="menu-wrapper"><ul class="navigation"><li class="navigation__item"><a href="https://wavelovers.ru/" target="_self" class="navigation__link">Home</a></li><li class="navigation__item"><a href="https://wavelovers.ru/faq.html" target="_self" class="navigation__link">FAQ</a></li><li class="navigation__item"><a href="https://wavelovers.ru/about.html" target="_self" class="navigation__link">About</a></li><li class="navigation__item"><a href="https://wavelovers.ru/about.html#donate" target="_self" class="navigation__link">Donate</a></li></ul></nav></div></header><main class="page container"><h1 class="visually-hidden">Wavelovers</h1><div id="app" v-cloak></div></main><footer class="footer"><div class="footer-wrapper container"><div class="annotation"><span class="annotation__text">© 2022 Wavelovers. Content licensed under </span><a href="https://wavelovers.ru/LICENSE.md" target="_blank">GNU General Public License v3.0</a><br><span class="annotation__text">This site is open source. </span><a href="https://github.com/eugene-serb/wavelovers/" target="_blank">Improve this page.</a></div><div class="annotation created-by"><span class="annotation__text">Created by</span><a href="https://eugene-serb.github.io/" target="_blank">Eugene Serb</a></div></div></footer><noscript><div><img src="https://mc.yandex.ru/watch/89252711" style="position:absolute; left:-9999px;" alt=""/></div></noscript></body></html>
});</script><script defer="defer" src="/js/chunk-vendors.9c4f6371.js"></script><script defer="defer" src="/js/app.5de4fb60.js"></script><link href="/css/app.f87473b2.css" rel="stylesheet"></head><body><header class="header"><div class="header-wrapper container"><div class="logo-wrapper"><span class="logo-wrapper__logo">Wavelovers</span></div><nav class="menu-wrapper"><ul class="navigation"><li class="navigation__item"><a href="https://wavelovers.ru/" target="_self" class="navigation__link">Home</a></li><li class="navigation__item"><a href="https://wavelovers.ru/faq.html" target="_self" class="navigation__link">FAQ</a></li><li class="navigation__item"><a href="https://wavelovers.ru/about.html" target="_self" class="navigation__link">About</a></li><li class="navigation__item"><a href="https://wavelovers.ru/about.html#donate" target="_self" class="navigation__link">Donate</a></li></ul></nav></div></header><main class="page container"><h1 class="visually-hidden">Wavelovers</h1><div id="app" v-cloak></div></main><footer class="footer"><div class="footer-wrapper container"><div class="annotation"><span class="annotation__text">© 2022 Wavelovers. Content licensed under </span><a href="https://wavelovers.ru/LICENSE.md" target="_blank">GNU General Public License v3.0</a><br><span class="annotation__text">This site is open source. </span><a href="https://github.com/eugene-serb/wavelovers/" target="_blank">Improve this page.</a></div><div class="annotation created-by"><span class="annotation__text">Created by</span><a href="https://eugene-serb.github.io/" target="_blank">Eugene Serb</a></div></div></footer><noscript><div><img src="https://mc.yandex.ru/watch/89252711" style="position:absolute; left:-9999px;" alt=""/></div></noscript></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
docs/js/app.5de4fb60.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,19 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}

2486
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,32 +12,15 @@
"vue": "^3.2.13"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-typescript": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"@vue/eslint-config-typescript": "^9.1.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
"eslint-plugin-vue": "^8.0.3",
"typescript": "~4.5.5"
}
}

View File

@ -2,16 +2,17 @@
<Wavelovers />
</template>
<script>
<script lang="ts">
import { defineComponent } from 'vue';
import WaveloversApp from '@/components/WaveloversApp.vue';
export default {
name: 'App',
components: {
Wavelovers: WaveloversApp,
},
};
export default defineComponent({
name: 'App',
components: {
Wavelovers: WaveloversApp,
},
});
</script>
<style>
</style>
<style></style>

View File

@ -1,39 +0,0 @@
module.exports = class Gamepad {
constructor(gamepad) {
this.unit = gamepad;
this.init();
}
init = () => {
this.id = Date.now();
this.canVibrate = (this.unit.vibrationActuator) ? true : false;
this.isVibrating = false;
this.pattern = [];
};
update = () => {
let gamepads = navigator.getGamepads();
this.unit = gamepads[this.unit.index];
};
reset = () => {
this.isVibrating = false;
this.unit.vibrationActuator.reset();
};
vibrate = async (pattern) => {
this.isVibrating = true;
this.pattern = pattern;
while (this.isVibrating === true) {
for (let i = 0; i < this.pattern.length; i++) {
if (this.isVibrating === true) {
this.unit.vibrationActuator.playEffect('dual-rumble', this.pattern[i]);
await this.sleep(this.pattern[i].startDelay + this.pattern[i].duration + 100);
} else {
return;
}
}
}
};
sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
};
};

View File

@ -2,11 +2,12 @@
<div class="list-item"></div>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'GamepadItem',
components: {},
};
});
</script>
<style>
@ -30,3 +31,4 @@
color: var(--color-white);
}
</style>

View File

@ -6,10 +6,11 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent } from 'vue';
import GamepadItem from '@/components/GamepadItem.vue';
export default {
export default defineComponent({
name: 'GamepadList',
props: {
gamepads: {
@ -19,8 +20,8 @@
components: {
GamepadItem: GamepadItem,
},
};
</script>
});
</script>
<style>
.device-list {
@ -34,3 +35,4 @@
gap: 16px;
}
</style>

View File

@ -6,11 +6,12 @@
</div>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'MessageItem',
components: {},
};
});
</script>
<style>
@ -33,3 +34,4 @@
}
}
</style>

View File

@ -11,8 +11,10 @@
</div>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'PatternItem',
props: {
pattern: {
@ -28,13 +30,12 @@
type: Boolean,
},
},
components: {},
methods: {
change(index) {
change(index: number): void {
this.$emit('change', index);
},
},
};
});
</script>
<style>
@ -68,14 +69,15 @@
background: var(--color-b);
}
.pattern-item__icon {
font-size: 24px;
}
.pattern-item__icon {
font-size: 24px;
}
.pattern-item__name {
font-size: 14px;
white-space: nowrap;
overflow: hidden;
color: var(--color-pattern-text);
}
.pattern-item__name {
font-size: 14px;
white-space: nowrap;
overflow: hidden;
color: var(--color-pattern-text);
}
</style>

View File

@ -10,11 +10,12 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent } from 'vue';
import PatternItem from '@/components/PatternItem.vue';
export default {
name: 'PatternList',
export default defineComponent({
name: 'PatternList',
props: {
patterns: {
type: Array,
@ -30,15 +31,15 @@
PatternItem: PatternItem,
},
methods: {
change(index) {
change(index: number): void {
this.$emit('change', index);
},
},
};
});
</script>
<style>
.pattern-list {
.pattern-list {
margin-bottom: 16px;
padding: 32px;
border-radius: var(--number-border-radius);
@ -50,3 +51,4 @@
gap: 32px;
}
</style>

1
src/components/Vibrator.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module 'Vibrator'

View File

@ -0,0 +1,79 @@
interface IPatternUnit {
startDelay: number,
duration: number,
weakMagnitude: number,
strongMagnitude: number,
}
interface IVibrationActuator {
type: string;
reset(): void;
playEffect(mode: string, pattern: IPatternUnit): void;
}
interface IGamepad {
id: string;
index: number;
timestamp: number;
connected: boolean;
vibrationActuator: IVibrationActuator;
}
interface IVibrator {
readonly id: number,
readonly canVibrate: boolean;
isVibrating: boolean;
unit: IGamepad;
pattern: IPatternUnit[];
update(): void;
reset(): void;
vibrate(pattern: IPatternUnit[]): void;
sleep(ms: number): Promise<number>;
}
export default class Vibrator implements IVibrator {
readonly id: number;
readonly canVibrate: boolean;
isVibrating: boolean;
unit: IGamepad;
pattern: IPatternUnit[];
constructor(unit: IGamepad) {
this.unit = unit;
this.id = Date.now();
this.canVibrate = (this.unit.vibrationActuator) ? true : false;
this.isVibrating = false;
this.pattern = [];
}
update(): void {
const gamepads = navigator.getGamepads();
this.unit = <IGamepad><any>gamepads[this.unit.index];
}
reset(): void {
this.isVibrating = false;
this.unit.vibrationActuator.reset();
}
async vibrate(pattern: IPatternUnit[]) {
this.isVibrating = true;
this.pattern = pattern;
while (this.isVibrating === true) {
for (let i = 0; i < this.pattern.length; i++) {
if (this.isVibrating === true) {
this.unit.vibrationActuator.playEffect('dual-rumble', this.pattern[i]);
await this.sleep(this.pattern[i].startDelay + this.pattern[i].duration + 100);
} else {
return;
}
}
}
}
sleep(ms: number): Promise<number> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}

View File

@ -12,13 +12,50 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent } from 'vue';
import PatternList from '@/components/PatternList.vue';
import GamepadList from '@/components/GamepadList.vue';
import Gamepad from '@/components/Gamepad.js';
import MessageItem from '@/components/MessageItem.vue';
import Vibrator from '@/components/Vibrator';
export default {
interface IVibrationActuator {
type: string;
reset(): void;
playEffect(mode: string, pattern: IPatternUnit): void;
}
interface IGamepad {
id: string;
index: number;
timestamp: number;
connected: boolean;
vibrationActuator: IVibrationActuator;
}
interface Event {
gamepad: IGamepad | any;
}
interface IPattern {
pattern: IPatternUnit[];
}
interface IPatternUnit {
startDelay: number,
duration: number,
weakMagnitude: number,
strongMagnitude: number,
}
interface IVibrator {
unit: IGamepad;
update(): void;
reset(): void;
vibrate(pattern: IPatternUnit[]): void;
}
export default defineComponent({
name: 'WaveloversApp',
components: {
PatternList: PatternList,
@ -27,8 +64,8 @@
},
data: () => {
return {
gamepads: [],
patterns: [],
gamepads: [] as IVibrator[],
patterns: [] as IPattern[],
isActive: false,
mode: 0,
};
@ -48,25 +85,25 @@
console.log('[error]', error);
}
},
addEventListeners() {
window.addEventListener('gamepadconnected', () => this.addGamepad(event));
window.addEventListener('gamepaddisconnected', () => this.deleteGamepad(event));
addEventListeners(): void {
window.addEventListener('gamepadconnected', (event: Event) => this.addGamepad(event));
window.addEventListener('gamepaddisconnected', (event: Event) => this.deleteGamepad(event));
},
addGamepad(event) {
addGamepad(event: Event) {
if (this.gamepads.length >= 1) {
return;
} else {
this.gamepads.push(new Gamepad(event.gamepad));
this.gamepads.push(new Vibrator(event.gamepad));
}
},
deleteGamepad(event) {
deleteGamepad(event: Event) {
this.gamepads.forEach((gamepad, index) => {
if (gamepad.unit.id === event.gamepad.id) {
this.gamepads.splice(index, 1);
}
});
},
change(index) {
change(index: number) {
if (this.mode === index) {
this.isActive = !this.isActive;
this.reset();
@ -94,7 +131,7 @@
this.loadPatterns();
this.addEventListeners();
},
};
});
</script>
<style>
@ -111,3 +148,4 @@
}
}
</style>

6
src/shims-vue.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

40
tsconfig.json Normal file
View File

@ -0,0 +1,40 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"useDefineForClassFields": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}