mirror of
https://github.com/Aviortheking/games.git
synced 2025-04-23 03:12:09 +00:00
Initial Commit
Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
commit
f47ab40ffd
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = false
|
8
.eslintignore
Normal file
8
.eslintignore
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
node_modules
|
||||||
|
|
||||||
|
out
|
||||||
|
.next
|
||||||
|
|
||||||
|
next-env.d.ts
|
||||||
|
*.js
|
||||||
|
__tests__
|
191
.eslintrc.js
Normal file
191
.eslintrc.js
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es6: true,
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
|
globals: {
|
||||||
|
Atomics: "readonly",
|
||||||
|
SharedArrayBuffer: "readonly"
|
||||||
|
},
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
parserOptions: {
|
||||||
|
project: "tsconfig.json",
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: true
|
||||||
|
},
|
||||||
|
ecmaVersion: 2018,
|
||||||
|
sourceType: "module"
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: "detect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
"react",
|
||||||
|
"@typescript-eslint"
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
indent: [
|
||||||
|
"error",
|
||||||
|
"tab"
|
||||||
|
],
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
|
||||||
|
quotes: "off",
|
||||||
|
"@typescript-eslint/quotes": [
|
||||||
|
"error",
|
||||||
|
"single",
|
||||||
|
{ avoidEscape: true }
|
||||||
|
],
|
||||||
|
|
||||||
|
semi: "off",
|
||||||
|
"@typescript-eslint/semi": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
|
||||||
|
"no-unused-expressions": "off",
|
||||||
|
"@typescript-eslint/no-unused-expressions": ["error", { "allowTernary": true }],
|
||||||
|
|
||||||
|
"@typescript-eslint/adjacent-overload-signatures": "error",
|
||||||
|
"@typescript-eslint/array-type": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
default: 'generic'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
|
"@typescript-eslint/ban-types": "error",
|
||||||
|
"@typescript-eslint/consistent-type-assertions": "error",
|
||||||
|
"@typescript-eslint/consistent-type-definitions": "error",
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
accessibility: "explicit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/interface-name-prefix": "off",
|
||||||
|
"@typescript-eslint/member-delimiter-style": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
multiline: {
|
||||||
|
delimiter: "none",
|
||||||
|
requireLast: true
|
||||||
|
},
|
||||||
|
singleline: {
|
||||||
|
delimiter: "comma",
|
||||||
|
requireLast: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/member-ordering": "error",
|
||||||
|
"@typescript-eslint/no-empty-function": "error",
|
||||||
|
"@typescript-eslint/no-empty-interface": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
|
"@typescript-eslint/no-namespace": "error",
|
||||||
|
"@typescript-eslint/no-parameter-properties": "off",
|
||||||
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/prefer-for-of": "error",
|
||||||
|
"@typescript-eslint/prefer-function-type": "error",
|
||||||
|
"@typescript-eslint/prefer-namespace-keyword": "error",
|
||||||
|
|
||||||
|
"@typescript-eslint/triple-slash-reference": "error",
|
||||||
|
"@typescript-eslint/type-annotation-spacing": "error",
|
||||||
|
"@typescript-eslint/unified-signatures": "error",
|
||||||
|
"arrow-body-style": "error",
|
||||||
|
"arrow-parens": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
|
||||||
|
complexity: "off",
|
||||||
|
"constructor-super": "error",
|
||||||
|
curly: "error",
|
||||||
|
"dot-notation": "error",
|
||||||
|
"eol-last": "error",
|
||||||
|
eqeqeq: [
|
||||||
|
"error",
|
||||||
|
"smart"
|
||||||
|
],
|
||||||
|
"guard-for-in": "error",
|
||||||
|
"id-blacklist": [
|
||||||
|
"error",
|
||||||
|
"any",
|
||||||
|
"Number",
|
||||||
|
"number",
|
||||||
|
"String",
|
||||||
|
"string",
|
||||||
|
"Boolean",
|
||||||
|
"boolean",
|
||||||
|
"Undefined"
|
||||||
|
],
|
||||||
|
"id-match": "error",
|
||||||
|
"max-classes-per-file": [
|
||||||
|
"error",
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"max-len": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
code: 120
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"new-parens": "error",
|
||||||
|
"no-bitwise": "error",
|
||||||
|
"no-caller": "error",
|
||||||
|
"no-cond-assign": "error",
|
||||||
|
"no-debugger": "error",
|
||||||
|
"no-empty": "error",
|
||||||
|
"no-eval": "error",
|
||||||
|
"no-fallthrough": "off",
|
||||||
|
"no-invalid-this": "off",
|
||||||
|
"no-multiple-empty-lines": "error",
|
||||||
|
"no-new-wrappers": "error",
|
||||||
|
"no-shadow": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
hoist: "all"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-throw-literal": "error",
|
||||||
|
"no-trailing-spaces": "error",
|
||||||
|
"no-undef-init": "error",
|
||||||
|
"no-underscore-dangle": "error",
|
||||||
|
"no-unsafe-finally": "error",
|
||||||
|
"no-unused-labels": "error",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"no-var": "error",
|
||||||
|
"object-shorthand": "error",
|
||||||
|
"one-var": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"prefer-const": "error",
|
||||||
|
"quote-props": [
|
||||||
|
"error",
|
||||||
|
"consistent-as-needed"
|
||||||
|
],
|
||||||
|
"radix": "error",
|
||||||
|
|
||||||
|
"space-before-function-paren": "off",
|
||||||
|
"@typescript-eslint/space-before-function-paren": ["error", {
|
||||||
|
asyncArrow: "always",
|
||||||
|
anonymous: "never",
|
||||||
|
named: "never"
|
||||||
|
}],
|
||||||
|
"spaced-comment": "error",
|
||||||
|
"use-isnan": "error",
|
||||||
|
"valid-typeof": "off",
|
||||||
|
}
|
||||||
|
};
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
* text=auto eol=lf
|
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
dist/
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"typescript.tsdk": "node_modules\\typescript\\lib"
|
||||||
|
}
|
2
next-env.d.ts
vendored
Normal file
2
next-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/types/global" />
|
22
next.config.js
Normal file
22
next.config.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const stylus = require('@zeit/next-stylus')
|
||||||
|
const css = require('@zeit/next-css')
|
||||||
|
const withPlugins = require('next-compose-plugins')
|
||||||
|
const {PHASE_DEVELOPMENT_SERVER} = require('next/constants')
|
||||||
|
|
||||||
|
module.exports = withPlugins([
|
||||||
|
[stylus, {
|
||||||
|
cssModules: true,
|
||||||
|
cssLoaderOptions: {
|
||||||
|
localIdentName: "[hash:base64:6]",
|
||||||
|
},
|
||||||
|
[PHASE_DEVELOPMENT_SERVER]: {
|
||||||
|
cssLoaderOptions: {
|
||||||
|
localIdentName: "[path][name]__[local]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
[css, {
|
||||||
|
cssModules: false
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
)
|
40
package.json
Normal file
40
package.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "@dzeio/url-shortener",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"server": "next start",
|
||||||
|
"lint": "eslint . --ext .ts,.tsx",
|
||||||
|
"test": "jest --config jext.config.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@dzeio/components": "^0.2.1",
|
||||||
|
"@zeit/next-css": "^1.0.1",
|
||||||
|
"@zeit/next-stylus": "^1.0.1",
|
||||||
|
"easy-sitemap": "^1.0.0",
|
||||||
|
"next": "^10.0.3",
|
||||||
|
"next-compose-plugins": "^2.2.0",
|
||||||
|
"react": "^17.0.1",
|
||||||
|
"react-dom": "^17.0.1",
|
||||||
|
"react-feather": "^2.0.9",
|
||||||
|
"stylus": "^0.54.7",
|
||||||
|
"typescript": "^4.1.3",
|
||||||
|
"webpack": "^4.46.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.8.7",
|
||||||
|
"@types/favicons": "^6.2.0",
|
||||||
|
"@types/node": "^14.0.0",
|
||||||
|
"@types/react": "^17.0.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.14.1",
|
||||||
|
"@typescript-eslint/parser": "^4.14.1",
|
||||||
|
"babel-preset-react-app": "^10.0.0",
|
||||||
|
"eslint": "^7.1.0",
|
||||||
|
"eslint-plugin-react": "^7.18.3",
|
||||||
|
"favicons": "^6.2.0",
|
||||||
|
"ts-node": "^9.1.1",
|
||||||
|
"vercel": "^21.2.2"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/assets/fonts/aileron/Aileron-Black.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-Black.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Black.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-Black.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Black.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-Black.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Black.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-Black.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-BlackItalic.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Bold.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-Bold.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Bold.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-Bold.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Bold.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-Bold.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Bold.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-Bold.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Heavy.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-Heavy.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Heavy.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-Heavy.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Heavy.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-Heavy.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-HeavyItalic.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Italic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-Italic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Italic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-Italic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Italic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-Italic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Italic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-Italic.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Light.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-Light.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Light.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-Light.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Light.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-Light.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Light.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-Light.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-LightItalic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-LightItalic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-LightItalic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-LightItalic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-LightItalic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-LightItalic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-LightItalic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-LightItalic.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Regular.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-Regular.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Regular.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-Regular.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Regular.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-Regular.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Regular.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-Regular.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBold.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBold.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBold.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBold.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBold.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBold.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBold.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBold.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-SemiBoldItalic.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Thin.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-Thin.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Thin.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-Thin.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Thin.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-Thin.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-Thin.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-Thin.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-ThinItalic.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLight.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLight.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLight.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLight.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLight.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLight.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLight.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLight.woff2
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.eot
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.eot
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.ttf
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.ttf
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.woff
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.woff
Normal file
Binary file not shown.
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.woff2
Normal file
BIN
public/assets/fonts/aileron/Aileron-UltraLightItalic.woff2
Normal file
Binary file not shown.
BIN
public/assets/pokemon-shuffle/icons.png
Normal file
BIN
public/assets/pokemon-shuffle/icons.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 MiB |
4
src/client/styl/stylus.d.ts
vendored
Normal file
4
src/client/styl/stylus.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare module '*.styl' {
|
||||||
|
const content: any
|
||||||
|
export = content
|
||||||
|
}
|
13
src/pages/_app.tsx
Normal file
13
src/pages/_app.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import App from 'next/app'
|
||||||
|
|
||||||
|
import '@dzeio/components/style.css'
|
||||||
|
|
||||||
|
export default class CApp extends App {
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { Component, pageProps } = this.props
|
||||||
|
|
||||||
|
return(<Component {...pageProps} />)
|
||||||
|
}
|
||||||
|
}
|
19
src/pages/_document.tsx
Normal file
19
src/pages/_document.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
class MyDocument extends Document {
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyDocument
|
13
src/pages/index.tsx
Normal file
13
src/pages/index.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Link, Text } from '@dzeio/components'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export default class Index extends React.Component {
|
||||||
|
|
||||||
|
public render = () => (
|
||||||
|
<main>
|
||||||
|
<Text>
|
||||||
|
<Link href="/pokemon-shuffle">Pokémon Shuffle</Link>
|
||||||
|
</Text>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
292
src/pages/pokemon-shuffle/index.tsx
Normal file
292
src/pages/pokemon-shuffle/index.tsx
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
import { Button, Table, Text, Util } from '@dzeio/components'
|
||||||
|
import React from 'react'
|
||||||
|
import css from './pokemon-shuffle.styl'
|
||||||
|
|
||||||
|
interface Cell {
|
||||||
|
id: number
|
||||||
|
horizontalCombo?: true
|
||||||
|
verticalCombo?: true
|
||||||
|
justSpawned?: true
|
||||||
|
isFalling?: true
|
||||||
|
}
|
||||||
|
|
||||||
|
interface States {
|
||||||
|
items: Array<Array<Cell | undefined>>
|
||||||
|
loading?: true
|
||||||
|
movingItem?: {x: number, y: number, cell: Cell}
|
||||||
|
points: number
|
||||||
|
turn: number
|
||||||
|
combo: number
|
||||||
|
comboMax: number
|
||||||
|
cursorPos: {x: number, y: number}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ITEM_COUNT = 4
|
||||||
|
const BOARD_SIZE = 6
|
||||||
|
let n = BOARD_SIZE
|
||||||
|
|
||||||
|
export default class PokemonShuffle extends React.Component<unknown, States> {
|
||||||
|
|
||||||
|
public state: States = {
|
||||||
|
items: [[]],
|
||||||
|
points: 0,
|
||||||
|
turn: 0,
|
||||||
|
combo: 0,
|
||||||
|
comboMax: 0,
|
||||||
|
cursorPos: {x: 0, y: 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render = () => (
|
||||||
|
<main>
|
||||||
|
<ul>
|
||||||
|
<li><Text>Tour: {this.state.turn}</Text></li>
|
||||||
|
<li><Text>Combo: {this.state.combo}, Max: {this.state.comboMax}</Text></li>
|
||||||
|
<li><Text>Points: {this.state.points}</Text></li>
|
||||||
|
</ul>
|
||||||
|
<Table >
|
||||||
|
<tbody className={`${css.table} ${this.state.loading ? css.loading : ''}`}>
|
||||||
|
{this.state.items.map((row, y) => (
|
||||||
|
<tr key={y}>
|
||||||
|
{row.map((cell, x) => (
|
||||||
|
<td
|
||||||
|
key={cell?.isFalling ? n++ : x}
|
||||||
|
onClick={this.onCellClick(x, y)}
|
||||||
|
className={css.cellParent}
|
||||||
|
>
|
||||||
|
{cell && (
|
||||||
|
<Text className={Util.buildClassName(
|
||||||
|
css[`icon-${cell.id}`],
|
||||||
|
css.cell,
|
||||||
|
[css.isFalling, cell.isFalling],
|
||||||
|
[css.justSpawned, cell.justSpawned],
|
||||||
|
[css.explode, cell.horizontalCombo || cell.verticalCombo]
|
||||||
|
)}>
|
||||||
|
<div></div>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
<Button onClick={() => this.calculate()}>Calculate!</Button>
|
||||||
|
<Button onClick={() => this.start()}>Start!</Button>
|
||||||
|
{/* <Input block type="textarea" value={JSON.stringify(this.state.items)}/> */}
|
||||||
|
{this.state.movingItem && (
|
||||||
|
<div style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: this.state.cursorPos.x,
|
||||||
|
top: this.state.cursorPos.y,
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
pointerEvents: 'none'
|
||||||
|
}}>
|
||||||
|
<Text className={Util.buildClassName(css[`icon-${this.state.movingItem.cell?.id}`], css.cell)}>
|
||||||
|
<div></div>
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<Text>
|
||||||
|
TODO list:
|
||||||
|
</Text>
|
||||||
|
<ul>
|
||||||
|
<li><Text>Lancement Initial sans combo possible</Text></li>
|
||||||
|
<li><Text>Meilleurs Animation de destruction</Text></li>
|
||||||
|
<li><Text>Annuler le mouvement si rien n'est claim</Text></li>
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
|
||||||
|
private mouveMove = (ev: MouseEvent) => {
|
||||||
|
this.setState({cursorPos: {
|
||||||
|
x: ev.pageX,
|
||||||
|
y: ev.pageY
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
|
||||||
|
private start() {
|
||||||
|
if (this.state.loading) {return}
|
||||||
|
this.setState({
|
||||||
|
loading: true,
|
||||||
|
items: Array
|
||||||
|
.from(Array(BOARD_SIZE))
|
||||||
|
.map(
|
||||||
|
() => Array.from(Array(BOARD_SIZE))
|
||||||
|
.map(() => ({id: random(0, ITEM_COUNT)}))
|
||||||
|
)
|
||||||
|
}, () => this.calculate())
|
||||||
|
}
|
||||||
|
|
||||||
|
private onCellClick = (x: number, y: number) => async () => {
|
||||||
|
// console.log(x, y)
|
||||||
|
if (this.state.loading) {
|
||||||
|
return window.alert('Cant play while Calculating')
|
||||||
|
}
|
||||||
|
if (!this.state.movingItem) {
|
||||||
|
const cell = this.state.items[y][x]
|
||||||
|
if (!cell) {
|
||||||
|
return window.alert('Cant move nothing')
|
||||||
|
}
|
||||||
|
document.addEventListener('mousemove', this.mouveMove)
|
||||||
|
this.setState({movingItem: {x,y,cell}})
|
||||||
|
this.state.items[y][x] = undefined
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
document.removeEventListener('mousemove', this.mouveMove)
|
||||||
|
const items = this.state.items
|
||||||
|
const temp = items[y][x]
|
||||||
|
items[y][x] = this.state.movingItem.cell
|
||||||
|
items[this.state.movingItem.y][this.state.movingItem.x] = temp
|
||||||
|
this.setState({
|
||||||
|
movingItem: undefined,
|
||||||
|
loading: true,
|
||||||
|
items
|
||||||
|
}, () => this.calculate())
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private asyncSetState = (states: Partial<States>) => new Promise<void>(
|
||||||
|
(res) => this.setState(states as States, () => res())
|
||||||
|
)
|
||||||
|
|
||||||
|
private async calculate() {
|
||||||
|
const items = this.state.items.map((r) => r.map((c) => {
|
||||||
|
if (!c) {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
c.horizontalCombo = undefined
|
||||||
|
c.verticalCombo = undefined
|
||||||
|
return c
|
||||||
|
}))
|
||||||
|
|
||||||
|
let newPoints = 0
|
||||||
|
|
||||||
|
let checkupCount = 0
|
||||||
|
// Checkup horizontal
|
||||||
|
for (let y = 0; y < items.length; y++) {
|
||||||
|
const row = items[y]
|
||||||
|
for (let x = 0; x < row.length; x++) {
|
||||||
|
const cell = row[x]
|
||||||
|
if (!cell || cell.horizontalCombo) {continue}
|
||||||
|
const id = cell.id
|
||||||
|
let sameCount = 0
|
||||||
|
while((x + ++sameCount) < items.length) {
|
||||||
|
console.log(y + sameCount, x)
|
||||||
|
const tmp = row[x + sameCount]
|
||||||
|
if (!tmp || tmp.id !== id) {break}
|
||||||
|
}
|
||||||
|
if (sameCount >= 3) {
|
||||||
|
checkupCount += 1
|
||||||
|
for (let i = x; i < (x + sameCount); i++) {
|
||||||
|
const tmp = items[y][i]
|
||||||
|
if (!tmp) {continue}
|
||||||
|
tmp.horizontalCombo = true
|
||||||
|
newPoints++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check vertical
|
||||||
|
for (let y = 0; y < items.length; y++) {
|
||||||
|
const row = items[y]
|
||||||
|
for (let x = 0; x < row.length; x++) {
|
||||||
|
const cell = row[x]
|
||||||
|
if (!cell || cell.verticalCombo) {continue}
|
||||||
|
const id = cell.id
|
||||||
|
let sameCount = 0
|
||||||
|
while((y + ++sameCount) < items.length) {
|
||||||
|
// console.log(y + sameCount, x)
|
||||||
|
const tmp = items[y + sameCount][x]
|
||||||
|
if (!tmp || tmp.id !== id) {break}
|
||||||
|
}
|
||||||
|
// if ((y + sameCount) > items.length) {
|
||||||
|
// sameCount++
|
||||||
|
// }
|
||||||
|
if (sameCount >= 3) {
|
||||||
|
checkupCount += 1
|
||||||
|
for (let i = y; i < (y + sameCount); i++) {
|
||||||
|
const tmp = items[i][x]
|
||||||
|
if (!tmp) {continue}
|
||||||
|
tmp.verticalCombo = true
|
||||||
|
|
||||||
|
newPoints++
|
||||||
|
}
|
||||||
|
// console.log(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkupCount) {
|
||||||
|
await this.asyncSetState({
|
||||||
|
items,
|
||||||
|
points: this.state.points + newPoints,
|
||||||
|
combo: this.state.combo+checkupCount,
|
||||||
|
comboMax: Math.max(this.state.comboMax, this.state.combo+checkupCount)
|
||||||
|
})
|
||||||
|
await new Promise((res) => setTimeout(res, 500))
|
||||||
|
}
|
||||||
|
|
||||||
|
// return
|
||||||
|
|
||||||
|
// Clear items
|
||||||
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||||
|
for (let y = 0; y < items.length; y++) {
|
||||||
|
const row = items[y]
|
||||||
|
for (let x = 0; x < row.length; x++) {
|
||||||
|
const cell = row[x]
|
||||||
|
if (!cell || (!cell.horizontalCombo && !cell.verticalCombo)) {continue}
|
||||||
|
items[y][x] = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let itemHasFallen = false
|
||||||
|
let needNewTurn = false
|
||||||
|
do {
|
||||||
|
// Make items fall
|
||||||
|
itemHasFallen = false
|
||||||
|
for (let y = (items.length - 1); y >= 0; y--) {
|
||||||
|
const row = items[y]
|
||||||
|
for (let x = 0; x < row.length; x++) {
|
||||||
|
const cell = row[x]
|
||||||
|
if (cell) {
|
||||||
|
cell.justSpawned = undefined
|
||||||
|
cell.isFalling = undefined
|
||||||
|
}
|
||||||
|
if (cell && y+1 < row.length && !items[y+1][x]) {
|
||||||
|
cell.isFalling = true
|
||||||
|
needNewTurn = true
|
||||||
|
itemHasFallen = true
|
||||||
|
items[y+1][x] = cell
|
||||||
|
items[y][x] = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill to top lane
|
||||||
|
for (let x = 0; x < items[0].length; x++) {
|
||||||
|
const cell = items[0][x]
|
||||||
|
if (!cell) {
|
||||||
|
itemHasFallen = true
|
||||||
|
items[0][x] = {id: random(0, ITEM_COUNT), justSpawned: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itemHasFallen) {
|
||||||
|
await this.asyncSetState({items})
|
||||||
|
await new Promise((res) => setTimeout(res, 300))
|
||||||
|
}
|
||||||
|
} while (itemHasFallen)
|
||||||
|
|
||||||
|
// If an item has fallen re calculate
|
||||||
|
if (needNewTurn) {
|
||||||
|
this.setState({items}, () => this.calculate())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.setState({items, loading: undefined, turn: this.state.turn+1, combo: 0})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function random(min = 0, max = 100) {
|
||||||
|
return Math.floor(Math.random() * (max - min) + min)
|
||||||
|
}
|
129
src/pages/pokemon-shuffle/pokemon-shuffle.styl
Normal file
129
src/pages/pokemon-shuffle/pokemon-shuffle.styl
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
$iconSize = 121px
|
||||||
|
|
||||||
|
.table
|
||||||
|
position relative
|
||||||
|
transition filter .5s ease-in-out
|
||||||
|
|
||||||
|
&.loading .cell
|
||||||
|
filter brightness(0.5)
|
||||||
|
|
||||||
|
.cellParent
|
||||||
|
position relative
|
||||||
|
width $iconSize
|
||||||
|
padding 0 !important
|
||||||
|
height $iconSize
|
||||||
|
|
||||||
|
.cell
|
||||||
|
width $iconSize
|
||||||
|
transition filter .5s ease-in-out
|
||||||
|
height $iconSize
|
||||||
|
background-image url('/assets/pokemon-shuffle/icons.png')
|
||||||
|
animation idleAnimation ease-in-out 1s
|
||||||
|
animation-iteration-count infinite
|
||||||
|
transform-origin 50% 50%
|
||||||
|
&.icon-0
|
||||||
|
background-position (1*$iconSize) 0px
|
||||||
|
&.icon-1
|
||||||
|
background-position (2*$iconSize) 0px
|
||||||
|
&.icon-2
|
||||||
|
background-position (3*$iconSize) 0px
|
||||||
|
&.icon-3
|
||||||
|
background-position (4*$iconSize) 0px
|
||||||
|
&.icon-4
|
||||||
|
background-position (5*$iconSize) 0px
|
||||||
|
&.icon-5
|
||||||
|
background-position (6*$iconSize) 0px
|
||||||
|
&.icon-6
|
||||||
|
background-position (7*$iconSize) 0px
|
||||||
|
&.icon-7
|
||||||
|
background-position (8*$iconSize) 0px
|
||||||
|
&.icon-8
|
||||||
|
background-position (9*$iconSize) 0px
|
||||||
|
&.icon-9
|
||||||
|
background-position (10*$iconSize) 0px
|
||||||
|
&.icon-10
|
||||||
|
background-position (11*$iconSize) 0px
|
||||||
|
|
||||||
|
&.isFalling
|
||||||
|
position absolute
|
||||||
|
animation fallingAnimation linear .3s
|
||||||
|
animation-iteration-count 1
|
||||||
|
transform-origin 50% 50%
|
||||||
|
animation-fill-mode forwards
|
||||||
|
|
||||||
|
&.explode
|
||||||
|
animation destroyAnimation ease-in-out .5s
|
||||||
|
animation-iteration-count 1
|
||||||
|
transform-origin 50% 50%
|
||||||
|
animation-fill-mode forwards
|
||||||
|
|
||||||
|
&::before
|
||||||
|
content " "
|
||||||
|
position absolute
|
||||||
|
bottom 0
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
border white solid 4px
|
||||||
|
border-radius 100%
|
||||||
|
|
||||||
|
animation destroyCircleAnimation ease-in-out .3s
|
||||||
|
animation-iteration-count 1
|
||||||
|
transform-origin 50% 50%
|
||||||
|
animation-fill-mode forwards
|
||||||
|
|
||||||
|
&.justSpawned
|
||||||
|
animation spawnAnimation ease-in-out 0.5s
|
||||||
|
animation-iteration-count 1
|
||||||
|
transform-origin 50% 50%
|
||||||
|
|
||||||
|
@keyframes idleAnimation
|
||||||
|
0%
|
||||||
|
transform rotate(0)
|
||||||
|
20%
|
||||||
|
transform rotate(-10deg)
|
||||||
|
40%
|
||||||
|
transform rotate(10deg)
|
||||||
|
60%
|
||||||
|
transform rotate(-5deg)
|
||||||
|
80%
|
||||||
|
transform rotate(5deg)
|
||||||
|
100%
|
||||||
|
transform rotate(0)
|
||||||
|
|
||||||
|
@keyframes fallingAnimation
|
||||||
|
from
|
||||||
|
top -117px // revoir précisément
|
||||||
|
to
|
||||||
|
top 3px
|
||||||
|
|
||||||
|
@keyframes destroyCircleAnimation
|
||||||
|
0%
|
||||||
|
opacity 0
|
||||||
|
transform scale(0)
|
||||||
|
100%
|
||||||
|
opacity 1
|
||||||
|
transform scale(1.2)
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes destroyAnimation
|
||||||
|
0%
|
||||||
|
transform scale(1)
|
||||||
|
filter brightness(1)
|
||||||
|
|
||||||
|
20%
|
||||||
|
transform scale(1.3)
|
||||||
|
filter brightness(1.7)
|
||||||
|
|
||||||
|
100%
|
||||||
|
transform scale(0)
|
||||||
|
filter brightness(1.5)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes spawnAnimation
|
||||||
|
from
|
||||||
|
transform: scale(0)
|
||||||
|
|
||||||
|
to
|
||||||
|
transform: scale(1)
|
14
src/pages/sitemap.xml.ts
Normal file
14
src/pages/sitemap.xml.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { GetServerSideProps } from 'next'
|
||||||
|
import Sitemap from 'easy-sitemap'
|
||||||
|
|
||||||
|
export default class SitemapXml {}
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps = async ({res}) => {
|
||||||
|
const sitemap = new Sitemap('https://games.avior.me', {response: res})
|
||||||
|
sitemap.addEntry('/')
|
||||||
|
sitemap.addEntry('/pokemon-shuffle')
|
||||||
|
sitemap.build()
|
||||||
|
return {
|
||||||
|
notFound: true
|
||||||
|
}
|
||||||
|
}
|
38
tsconfig.json
Normal file
38
tsconfig.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"baseUrl": "./src",
|
||||||
|
"paths": {
|
||||||
|
"@styl/*": ["client/styl/*"],
|
||||||
|
"@cp/*": ["client/components/*"],
|
||||||
|
"@smd/*": ["client/styl/modules/*"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"out",
|
||||||
|
"__tests__"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"src/client/styl/stylus.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx"
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user