mirror of
https://github.com/jellyfin/jellyfin-chromecast.git
synced 2024-11-27 00:00:28 +00:00
Switch to npm
This commit is contained in:
parent
c7c67dee9e
commit
b85fc6753f
@ -34,22 +34,22 @@ jobs:
|
||||
- task: Cache@2
|
||||
displayName: 'Check Cache'
|
||||
inputs:
|
||||
key: 'yarn | yarn.lock'
|
||||
key: 'npm | package-lock.json'
|
||||
path: 'node_modules'
|
||||
cacheHitVar: CACHE_RESTORED
|
||||
|
||||
- script: 'yarn install --frozen-lockfile'
|
||||
- script: 'npm ci --no-audit'
|
||||
displayName: 'Install Dependencies'
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
|
||||
- script: 'sh ./scripts/updateversion.sh'
|
||||
displayName: 'Update version in package.json'
|
||||
|
||||
- script: 'yarn build:development'
|
||||
- script: 'npm run build:development'
|
||||
displayName: 'Build Development'
|
||||
condition: eq(variables['BuildConfiguration'], 'development')
|
||||
|
||||
- script: 'yarn build:production'
|
||||
- script: 'npm run build:production'
|
||||
displayName: 'Build Bundle'
|
||||
condition: eq(variables['BuildConfiguration'], 'production')
|
||||
|
||||
|
@ -19,3 +19,12 @@ updates:
|
||||
prefix: fix
|
||||
prefix-development: chore
|
||||
include: scope
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: daily
|
||||
time: '00:00'
|
||||
open-pull-requests-limit: 10
|
||||
commit-message:
|
||||
prefix: actions
|
94
.github/workflows/lint.yaml
vendored
94
.github/workflows/lint.yaml
vendored
@ -1,74 +1,42 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
lint-js:
|
||||
name: Lint JS/TS
|
||||
runs-on: ubuntu-latest
|
||||
lint:
|
||||
name: Lint TS and CSS
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node env
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: 14
|
||||
- name: Setup node env
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: Get npm cache directory path
|
||||
id: npm-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(npm config get cache)"
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
id: npm-cache
|
||||
with:
|
||||
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Install dependencies
|
||||
run: npm ci --no-audit
|
||||
|
||||
- name: Run ESLint
|
||||
run: yarn run lint:code
|
||||
|
||||
lint-css:
|
||||
name: Lint CSS
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node env
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Run stylelint
|
||||
run: yarn run lint:css
|
||||
- name: Run ESLint
|
||||
run: npm run lint
|
||||
|
62
.github/workflows/test.yaml
vendored
62
.github/workflows/test.yaml
vendored
@ -1,42 +1,42 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
jest:
|
||||
name: Jest
|
||||
runs-on: ubuntu-latest
|
||||
jest:
|
||||
name: Jest
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node env
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: 14
|
||||
- name: Setup node env
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: Get npm cache directory path
|
||||
id: npm-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(npm config get cache)"
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
id: npm-cache
|
||||
with:
|
||||
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Install dependencies
|
||||
run: npm ci --no-audit
|
||||
|
||||
- name: Run tests
|
||||
run: yarn run test
|
||||
- name: Run tests
|
||||
run: npm run test
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
### Development Environment
|
||||
|
||||
The development environment is setup with editorconfig, Code style is enforced by prettier and eslint for Javascipt/Typescript linting
|
||||
The development environment is setup with editorconfig. Code style is enforced by prettier and eslint for Javascript/Typescript linting
|
||||
|
||||
- [editorconfig](https://editorconfig.org/)
|
||||
- [prettier](https://prettier.io/)
|
||||
@ -14,13 +14,13 @@ The development environment is setup with editorconfig, Code style is enforced b
|
||||
|
||||
| name | required | description | default if not set |
|
||||
| ------------- | -------- | ---------------------------------------------------------- | ------------------ |
|
||||
| RECEIVER_PORT | No | The port used for the dev server when `yarn serve` is used | 9000 |
|
||||
| RECEIVER_PORT | No | The port used for the dev server when `npm start` is used | 9000 |
|
||||
|
||||
### Building/Using
|
||||
|
||||
`yarn build:development` - Build a development version
|
||||
`yarn serve` / `yarn start` - Build a development version and start a dev server
|
||||
`yarn build:production` - Build a production version
|
||||
`npm run build:development` - Build a development version
|
||||
`npm start` - Build a development version and start a dev server
|
||||
`npm run build:production` - Build a production version
|
||||
|
||||
## Pull Requests
|
||||
|
||||
|
12410
package-lock.json
generated
Normal file
12410
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
158
package.json
158
package.json
@ -1,81 +1,83 @@
|
||||
{
|
||||
"name": "jellyfin-chromecast",
|
||||
"description": "Cast receiver for Jellyfin",
|
||||
"version": "3.0.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jellyfin/jellyfin-chromecast/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chromecast-caf-receiver": "^5.0.12",
|
||||
"@types/jest": "^26.0.19",
|
||||
"@types/node": "^14.14.14",
|
||||
"@types/webpack": "^4.41.25",
|
||||
"@types/webpack-dev-server": "^3.11.1",
|
||||
"@types/webpack-merge": "^4.1.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.6.0",
|
||||
"@typescript-eslint/parser": "^4.6.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^5.0.1",
|
||||
"eslint": "^7.16.0",
|
||||
"eslint-config-prettier": "^7.1.0",
|
||||
"eslint-import-resolver-typescript": "^2.3.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsdoc": "^30.7.9",
|
||||
"eslint-plugin-prettier": "^3.3.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"fixpack": "^3.0.6",
|
||||
"html-loader": "^1.3.2",
|
||||
"html-webpack-plugin": "^4.5.0",
|
||||
"husky": "^4.3.0",
|
||||
"image-minimizer-webpack-plugin": "^2.1.0",
|
||||
"imagemin-svgo": "^8.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"prettier": "^2.2.1",
|
||||
"pretty-quick": "^3.1.0",
|
||||
"source-map-loader": "^1.1.2",
|
||||
"style-loader": "^2.0.0",
|
||||
"stylelint": "^13.8.0",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"ts-jest": "^26.4.4",
|
||||
"ts-loader": "^8.0.13",
|
||||
"ts-node": "^9.1.1",
|
||||
"tsconfig-paths": "^3.9.0",
|
||||
"typescript": "^4.1.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.10.3",
|
||||
"webpack-cli": "^4.2.0",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-merge": "^5.4.1"
|
||||
},
|
||||
"homepage": "https://jellyfin.org/",
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "pretty-quick --staged"
|
||||
}
|
||||
},
|
||||
"license": "GPL-2.0-or-later",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/jellyfin/jellyfin-chromecast.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build:development": "cross-env TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack --config webpack.config.ts --mode=development",
|
||||
"build:production": "cross-env TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack --config webpack.config.ts --mode=production",
|
||||
"lint": "yarn lint:code && yarn lint:css",
|
||||
"lint:code": "eslint --ext .ts,.js .",
|
||||
"lint:css": "stylelint ./src/css/*.css",
|
||||
"postinstall": "fixpack",
|
||||
"prepare": "yarn build:production",
|
||||
"pretest": "fixpack && yarn lint && yarn prettier",
|
||||
"prettier": "prettier --check .",
|
||||
"serve": "cross-env TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack serve --config webpack.config.ts",
|
||||
"test": "jest --passWithNoTests",
|
||||
"watch": "cross-env TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack --config webpack.config.ts --watch"
|
||||
"name": "jellyfin-chromecast",
|
||||
"description": "Cast receiver for Jellyfin",
|
||||
"version": "3.0.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jellyfin/jellyfin-chromecast/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chromecast-caf-receiver": "^5.0.12",
|
||||
"@types/jest": "^26.0.19",
|
||||
"@types/node": "^14.14.14",
|
||||
"@types/webpack": "^4.41.25",
|
||||
"@types/webpack-dev-server": "^3.11.1",
|
||||
"@types/webpack-merge": "^4.1.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.6.0",
|
||||
"@typescript-eslint/parser": "^4.6.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^5.0.1",
|
||||
"eslint": "^7.16.0",
|
||||
"eslint-config-prettier": "^7.1.0",
|
||||
"eslint-import-resolver-typescript": "^2.3.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsdoc": "^30.7.9",
|
||||
"eslint-plugin-prettier": "^3.3.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"fixpack": "^3.0.6",
|
||||
"html-loader": "^1.3.2",
|
||||
"html-webpack-plugin": "^4.5.0",
|
||||
"husky": "^4.3.0",
|
||||
"image-minimizer-webpack-plugin": "^2.1.0",
|
||||
"imagemin-svgo": "^8.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"prettier": "^2.2.1",
|
||||
"pretty-quick": "^3.1.0",
|
||||
"source-map-loader": "^1.1.2",
|
||||
"style-loader": "^2.0.0",
|
||||
"stylelint": "^13.8.0",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"ts-jest": "^26.4.4",
|
||||
"ts-loader": "^8.0.13",
|
||||
"ts-node": "^9.1.1",
|
||||
"tsconfig-paths": "^3.9.0",
|
||||
"typescript": "^4.1.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.10.3",
|
||||
"webpack-cli": "^4.2.0",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-merge": "^5.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"yarn": "YARN NO LONGER USED - use npm instead."
|
||||
},
|
||||
"homepage": "https://jellyfin.org/",
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "pretty-quick --staged"
|
||||
}
|
||||
},
|
||||
"license": "GPL-2.0-or-later",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/jellyfin/jellyfin-chromecast.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build:development": "TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack --config webpack.config.ts --mode=development",
|
||||
"build:production": "TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack --config webpack.config.ts --mode=production",
|
||||
"lint": "npm run lint:code && npm run lint:css && npm run prettier",
|
||||
"lint:code": "eslint --ext .ts,.js .",
|
||||
"lint:css": "stylelint ./src/css/*.css",
|
||||
"postinstall": "fixpack",
|
||||
"prepare": "npm run build:production",
|
||||
"prettier": "prettier --check .",
|
||||
"start": "TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack serve --config webpack.config.ts",
|
||||
"test": "jest --passWithNoTests",
|
||||
"watch": "TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack --config webpack.config.ts --watch"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,2 @@
|
||||
cat package.json \
|
||||
| jq --indent 4 '.version = .version + "_'$BUILD_BUILDNUMBER'"' \
|
||||
> package.json.tmp \
|
||||
&& mv package.json.tmp package.json
|
||||
package_json="$(cat package.json | jq '.version = .version + "-'$BUILD_BUILDNUMBER'"')"
|
||||
echo "$package_json" > package.json
|
||||
|
@ -24,7 +24,7 @@ import { playbackManager } from './playbackManager';
|
||||
import { DocumentManager } from './documentManager';
|
||||
|
||||
export abstract class CommandHandler {
|
||||
private static playerManager: cast.framework.PlayerManager;
|
||||
private static playerManager: framework.PlayerManager;
|
||||
private static playbackManager: playbackManager;
|
||||
private static supportedCommands: SupportedCommands = {
|
||||
PlayNext: CommandHandler.playNextHandler,
|
||||
@ -53,7 +53,7 @@ export abstract class CommandHandler {
|
||||
};
|
||||
|
||||
static configure(
|
||||
playerManager: cast.framework.PlayerManager,
|
||||
playerManager: framework.PlayerManager,
|
||||
playbackManager: playbackManager
|
||||
): void {
|
||||
this.playerManager = playerManager;
|
||||
|
@ -82,10 +82,8 @@ export function onMediaElementPlaying(): void {
|
||||
reportEvent('playstatechange', true);
|
||||
}
|
||||
|
||||
function onMediaElementVolumeChange(event: cast.framework.system.Event): void {
|
||||
window.volume = (<cast.framework.system.SystemVolumeChangedEvent>(
|
||||
event
|
||||
)).data;
|
||||
function onMediaElementVolumeChange(event: framework.system.Event): void {
|
||||
window.volume = (<framework.system.SystemVolumeChangedEvent>event).data;
|
||||
console.log('Received volume update: ' + window.volume.level);
|
||||
if (JellyfinApi.serverAddress !== null) reportEvent('volumechange', true);
|
||||
}
|
||||
@ -628,13 +626,10 @@ export function setTextTrack(index: number | null): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const tracks: Array<cast.framework.messages.Track> = textTracksManager.getTracks();
|
||||
const subtitleTrack:
|
||||
| cast.framework.messages.Track
|
||||
| undefined = tracks.find(function (
|
||||
track: cast.framework.messages.Track
|
||||
) {
|
||||
return track.trackId === index;
|
||||
const tracks: Array<framework.messages.Track> = textTracksManager.getTracks();
|
||||
const subtitleTrack: framework.messages.Track | undefined = tracks.find(
|
||||
(track: framework.messages.Track) => {
|
||||
return track.trackId === index;
|
||||
});
|
||||
if (subtitleTrack && subtitleTrack.trackId !== undefined) {
|
||||
textTracksManager.setActiveByIds([subtitleTrack.trackId]);
|
||||
@ -696,7 +691,7 @@ export function createMediaInformation(
|
||||
playSessionId: string,
|
||||
item: BaseItemDto,
|
||||
streamInfo: any
|
||||
): cast.framework.messages.MediaInformation {
|
||||
): framework.messages.MediaInformation {
|
||||
const mediaInfo = new cast.framework.messages.MediaInformation();
|
||||
mediaInfo.contentId = streamInfo.url;
|
||||
mediaInfo.contentType = streamInfo.contentType;
|
||||
@ -764,7 +759,7 @@ if (!PRODUCTION) {
|
||||
|
||||
window.mediaManager.addEventListener(
|
||||
cast.framework.events.category.CORE,
|
||||
(event: cast.framework.events.Event) => {
|
||||
(event: framework.events.Event) => {
|
||||
console.log('Core event: ' + event.type);
|
||||
console.log(event);
|
||||
}
|
||||
|
@ -31,12 +31,12 @@ import { BaseItemDto } from '~/api/generated/models/base-item-dto';
|
||||
import { MediaSourceInfo } from '~/api/generated/models/media-source-info';
|
||||
|
||||
export class playbackManager {
|
||||
private playerManager: cast.framework.PlayerManager;
|
||||
private playerManager: framework.PlayerManager;
|
||||
// TODO remove any
|
||||
private activePlaylist: Array<BaseItemDto>;
|
||||
private activePlaylistIndex: number;
|
||||
|
||||
constructor(playerManager: cast.framework.PlayerManager) {
|
||||
constructor(playerManager: framework.PlayerManager) {
|
||||
// Parameters
|
||||
this.playerManager = playerManager;
|
||||
|
||||
|
12
src/types/global.d.ts
vendored
12
src/types/global.d.ts
vendored
@ -1,3 +1,9 @@
|
||||
import { cast } from 'chromecast-caf-receiver';
|
||||
import {
|
||||
CastReceiverContext,
|
||||
PlayerManager
|
||||
} from 'chromecast-caf-receiver/cast.framework';
|
||||
import { SystemVolumeData } from 'chromecast-caf-receiver/cast.framework.system';
|
||||
import { RepeatMode } from '../api/generated/models/repeat-mode';
|
||||
import { BaseItemDto } from '../api/generated/models/base-item-dto';
|
||||
|
||||
@ -98,8 +104,8 @@ declare global {
|
||||
export interface Window {
|
||||
deviceInfo: DeviceInfo;
|
||||
mediaElement: HTMLElement | null;
|
||||
mediaManager: cast.framework.PlayerManager;
|
||||
castReceiverContext: cast.framework.CastReceiverContext;
|
||||
mediaManager: PlayerManager;
|
||||
castReceiverContext: CastReceiverContext;
|
||||
playlist: Array<any>;
|
||||
currentPlaylistIndex: number;
|
||||
repeatMode: RepeatMode;
|
||||
@ -107,6 +113,6 @@ declare global {
|
||||
subtitleAppearance: any;
|
||||
MaxBitrate: number | undefined;
|
||||
senderId: string | undefined;
|
||||
volume: cast.framework.system.SystemVolumeData;
|
||||
volume: SystemVolumeData;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user