mirror of
https://github.com/eugene-serb/wavelovers.git
synced 2023-09-09 23:41:16 +03:00
Rewrited with TypeScript, VueJS, ESLint, Babel, JavaScript, HTML, CSS, JSON
This commit is contained in:
parent
de9277464a
commit
c4dd4d3b0a
4
.browserslistrc
Normal file
4
.browserslistrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
18
.eslintrc.js
Normal file
18
.eslintrc.js
Normal 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'
|
||||
}
|
||||
}
|
|
@ -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
2
docs/js/app.5de4fb60.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/js/app.5de4fb60.js.map
Normal file
1
docs/js/app.5de4fb60.js.map
Normal file
File diff suppressed because one or more lines are too long
2
docs/js/chunk-vendors.9c4f6371.js
Normal file
2
docs/js/chunk-vendors.9c4f6371.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/js/chunk-vendors.9c4f6371.js.map
Normal file
1
docs/js/chunk-vendors.9c4f6371.js.map
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
|
@ -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
2486
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
31
package.json
31
package.json
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
19
src/App.vue
19
src/App.vue
|
@ -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>
|
||||
|
||||
|
|
|
@ -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));
|
||||
};
|
||||
};
|
||||
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
1
src/components/Vibrator.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
declare module 'Vibrator'
|
79
src/components/Vibrator.ts
Normal file
79
src/components/Vibrator.ts
Normal 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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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
6
src/shims-vue.d.ts
vendored
Normal 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
40
tsconfig.json
Normal 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"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user