This commit is contained in:
Miroslav Šedivý 2024-03-17 00:00:14 +01:00
parent 37f93eae6b
commit 27d88cee08
70 changed files with 6271 additions and 13595 deletions

View File

@ -1,3 +0,0 @@
{
"presets": ["@vue/cli-plugin-babel/preset"]
}

View File

@ -1,19 +0,0 @@
{
"root": true,
"env": {
"node": true
},
"extends": ["plugin:vue/essential", "@vue/prettier", "@vue/typescript"],
"parserOptions": {
"parser": "@typescript-eslint/parser"
},
"rules": {
"vue/multi-word-component-names": "off",
"vue/valid-v-for": "off",
"no-case-declarations": "off",
"no-dupe-class-members": "off",
"no-console": "off",
"no-empty": "off"
},
"ignorePatterns": ["**/*.js"]
}

26
.eslintrc.cjs Normal file
View File

@ -0,0 +1,26 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
overrides: [
{
files: [
'e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'
],
'extends': [
'plugin:playwright/recommended'
]
}
],
parserOptions: {
ecmaVersion: 'latest'
},
ignorePatterns: ["**/*.js"]
}

37
.gitignore vendored
View File

@ -1,6 +1,33 @@
.env.local
node_modules
dist
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
/src/page/plugins/*
!/src/page/plugins/.gitkeep
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo
test-results/
playwright-report/

View File

@ -1,8 +0,0 @@
{
"semi": false,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 2,
"vueIndentScriptAndStyle": true
}

8
.prettierrc.json Normal file
View File

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

15
.vscode/settings.json vendored
View File

@ -2,22 +2,9 @@
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.detectIndentation": false,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.encoding": "utf8",
"files.eol": "\n",
"typescript.tsdk": "./node_modules/typescript/lib",
"todo-tree.filtering.excludeGlobs": ["**/node_modules/**"],
"eslint.validate": [
"vue",
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
],
"vetur.validation.template": true,
"vetur.useWorkspaceDependencies": true,
"remote.extensionKind": {
"ms-azuretools.vscode-docker": "ui"
},
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"

View File

@ -1,11 +0,0 @@
FROM node:18-buster-slim
COPY . /app
WORKDIR /app
RUN npm i
EXPOSE 8080
CMD [ "npm", "run", "serve" ]

View File

@ -24,6 +24,68 @@ npm run build
KEYBOARD=novnc npm run build
```
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```
### Run Unit Tests with [Vitest](https://vitest.dev/)
```sh
npm run test:unit
```
### Run End-to-End Tests with [Playwright](https://playwright.dev)
```sh
# Install browsers for the first run
npx playwright install
# When testing on CI, must build the project first
npm run build
# Runs the end-to-end tests
npm run test:e2e
# Runs the tests only on Chromium
npm run test:e2e -- --project=chromium
# Runs the tests of a specific file
npm run test:e2e -- tests/example.spec.ts
# Runs the tests in debug mode
npm run test:e2e -- --debug
```
### Lint with [ESLint](https://eslint.org/)
```sh
npm run lint
```
### Example
API consists of accessing Vue reactive state, calling various methods and subscribing to events. Simple usage:

4
e2e/tsconfig.json Normal file
View File

@ -0,0 +1,4 @@
{
"extends": "@tsconfig/node20/tsconfig.json",
"include": ["./**/*"]
}

8
e2e/vue.spec.ts Normal file
View File

@ -0,0 +1,8 @@
import { test, expect } from '@playwright/test';
// See here how to get started:
// https://playwright.dev/docs/intro
test('visits the app root url', async ({ page }) => {
await page.goto('/');
await expect(page.locator('div.greetings > h1')).toHaveText('You did it!');
})

1
env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

12
index.html Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neko</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

12107
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +1,55 @@
{
"name": "@demodesk/neko",
"version": "1.6.32",
"version": "2.0.0",
"description": "Client as reusable Vue.js component for neko streaming server.",
"repository": "https://github.com/demodesk/neko-client",
"publishConfig": {
"registry": "https://npm.pkg.github.com"
},
"type": "module",
"main": "dist/neko.umd.js",
"module": "dist/neko.common.js",
"typings": "dist/types/main.d.ts",
"scripts": {
"serve": "vue-cli-service serve --mode development",
"lint": "vue-cli-service lint",
"build": "vue-cli-service build --target lib --name neko ./src/lib.ts && ./types-build.sh",
"build:page": "vue-cli-service build"
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"test:unit": "vitest",
"test:e2e": "playwright test",
"build-only": "vite build",
"type-check": "vue-tsc --build --force",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"axios": "^1.6.7",
"eventemitter3": "^5.0.0",
"axios": "^1.6.8",
"eventemitter3": "^5.0.1",
"resize-observer-polyfill": "^1.5.1",
"vue": "^2.7.16",
"vue-class-component": "^7.2.6",
"vue-property-decorator": "^9.1.2"
"vue": "^3.4.21"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^6.1.1",
"@types/node": "^18.0.0",
"@types/vue": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^6.19.1",
"@typescript-eslint/parser": "^6.19.1",
"@vue/cli-plugin-babel": "^5.0.4",
"@vue/cli-plugin-eslint": "^5.0.4",
"@vue/cli-plugin-typescript": "^5.0.4",
"@vue/cli-service": "^5.0.4",
"@vue/eslint-config-prettier": "^9.0.0",
"@fortawesome/fontawesome-free": "^6.5.1",
"@playwright/test": "^1.42.1",
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node20": "^20.1.2",
"@types/jsdom": "^21.1.6",
"@types/node": "^20.11.25",
"@vitejs/plugin-vue": "^5.0.4",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"eslint": "^8.15.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-vue": "^9.20.1",
"prettier": "^3.2.4",
"sass": "^1.51.0",
"sass-loader": "^14.0.0",
"ts-node": "^10.7.0",
"typescript": "^5.3.3",
"vue-template-compiler": "^2.6.14"
"@vue/test-utils": "^2.4.4",
"@vue/tsconfig": "^0.5.1",
"eslint": "^8.49.0",
"eslint-plugin-playwright": "^1.5.2",
"eslint-plugin-vue": "^9.17.0",
"jsdom": "^24.0.0",
"npm-run-all2": "^6.1.2",
"prettier": "^3.0.3",
"sass": "^1.72.0",
"typescript": "~5.4.0",
"vite": "^5.1.5",
"vitest": "^1.3.1",
"vue-tsc": "^2.0.6"
},
"files": [
"dist/*"

110
playwright.config.ts Normal file
View File

@ -0,0 +1,110 @@
import process from 'node:process'
import { defineConfig, devices } from '@playwright/test'
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './e2e',
/* Maximum time one test can run for. */
timeout: 30 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000
},
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://localhost:5173',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
/* Only on CI systems run the tests headless */
headless: !!process.env.CI
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome']
}
},
{
name: 'firefox',
use: {
...devices['Desktop Firefox']
}
},
{
name: 'webkit',
use: {
...devices['Desktop Safari']
}
}
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: {
// ...devices['Pixel 5'],
// },
// },
// {
// name: 'Mobile Safari',
// use: {
// ...devices['iPhone 12'],
// },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: {
// channel: 'msedge',
// },
// },
// {
// name: 'Google Chrome',
// use: {
// channel: 'chrome',
// },
// },
],
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
// outputDir: 'test-results/',
/* Run your local dev server before starting the tests */
webServer: {
/**
* Use the dev server by default for faster feedback loop.
* Use the preview server on CI for more realistic testing.
* Playwright will re-use the local server if there is already a dev-server running.
*/
command: process.env.CI ? 'vite preview --port 5173' : 'vite dev',
port: 5173,
reuseExistingServer: !process.env.CI
}
})

View File

@ -20,6 +20,7 @@ models/error-message.ts
models/index.ts
models/keyboard-map.ts
models/keyboard-modifiers.ts
models/member-bulk-delete.ts
models/member-bulk-update.ts
models/member-create.ts
models/member-data.ts

View File

@ -1 +1 @@
6.6.0-SNAPSHOT
7.4.0-SNAPSHOT

View File

@ -14,17 +14,14 @@
import type { Configuration } from '../configuration';
import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
// @ts-ignore
import { BatchRequest } from '../models';
// @ts-ignore
import { BatchResponse } from '../models';
import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from '../base';
import type { RequestArgs } from '../base';
import type { BatchRequest } from '../models';
import type { BatchResponse } from '../models';
/**
* DefaultApi - axios parameter creator
* @export
@ -38,7 +35,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
batch: async (batchRequest: Array<BatchRequest>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
batch: async (batchRequest: Array<BatchRequest>, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'batchRequest' is not null or undefined
assertParamExists('batch', 'batchRequest', batchRequest)
const localVarPath = `/api/batch`;
@ -82,7 +79,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
healthcheck: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
healthcheck: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/health`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -112,7 +109,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
metrics: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
metrics: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/metrics`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -153,9 +150,11 @@ export const DefaultApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async batch(batchRequest: Array<BatchRequest>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<BatchResponse>>> {
async batch(batchRequest: Array<BatchRequest>, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<BatchResponse>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.batch(batchRequest, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['DefaultApi.batch']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -163,9 +162,11 @@ export const DefaultApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async healthcheck(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async healthcheck(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.healthcheck(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['DefaultApi.healthcheck']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -173,9 +174,11 @@ export const DefaultApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async metrics(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async metrics(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.metrics(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['DefaultApi.metrics']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
}
};
@ -233,7 +236,7 @@ export class DefaultApi extends BaseAPI {
* @throws {RequiredError}
* @memberof DefaultApi
*/
public batch(batchRequest: Array<BatchRequest>, options?: AxiosRequestConfig) {
public batch(batchRequest: Array<BatchRequest>, options?: RawAxiosRequestConfig) {
return DefaultApiFp(this.configuration).batch(batchRequest, options).then((request) => request(this.axios, this.basePath));
}
@ -244,7 +247,7 @@ export class DefaultApi extends BaseAPI {
* @throws {RequiredError}
* @memberof DefaultApi
*/
public healthcheck(options?: AxiosRequestConfig) {
public healthcheck(options?: RawAxiosRequestConfig) {
return DefaultApiFp(this.configuration).healthcheck(options).then((request) => request(this.axios, this.basePath));
}
@ -255,7 +258,8 @@ export class DefaultApi extends BaseAPI {
* @throws {RequiredError}
* @memberof DefaultApi
*/
public metrics(options?: AxiosRequestConfig) {
public metrics(options?: RawAxiosRequestConfig) {
return DefaultApiFp(this.configuration).metrics(options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -14,31 +14,70 @@
import type { Configuration } from '../configuration';
import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
// @ts-ignore
import { ErrorMessage } from '../models';
// @ts-ignore
import { MemberBulkUpdate } from '../models';
// @ts-ignore
import { MemberCreate } from '../models';
// @ts-ignore
import { MemberData } from '../models';
// @ts-ignore
import { MemberPassword } from '../models';
// @ts-ignore
import { MemberProfile } from '../models';
import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from '../base';
import type { RequestArgs } from '../base';
import type { ErrorMessage } from '../models';
import type { MemberBulkDelete } from '../models';
import type { MemberBulkUpdate } from '../models';
import type { MemberCreate } from '../models';
import type { MemberData } from '../models';
import type { MemberPassword } from '../models';
import type { MemberProfile } from '../models';
/**
* MembersApi - axios parameter creator
* @export
*/
export const MembersApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
*
* @summary bulk delete members
* @param {MemberBulkDelete} memberBulkDelete
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersBulkDelete: async (memberBulkDelete: MemberBulkDelete, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'memberBulkDelete' is not null or undefined
assertParamExists('membersBulkDelete', 'memberBulkDelete', memberBulkDelete)
const localVarPath = `/api/members_bulk/delete`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication CookieAuth required
// authentication TokenAuth required
await setApiKeyToObject(localVarQueryParameter, "token", configuration)
// authentication BearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(memberBulkDelete, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary bulk update members
@ -46,7 +85,7 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersBulkUpdate: async (memberBulkUpdate: MemberBulkUpdate, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
membersBulkUpdate: async (memberBulkUpdate: MemberBulkUpdate, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'memberBulkUpdate' is not null or undefined
assertParamExists('membersBulkUpdate', 'memberBulkUpdate', memberBulkUpdate)
const localVarPath = `/api/members_bulk/update`;
@ -91,7 +130,7 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersCreate: async (memberCreate: MemberCreate, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
membersCreate: async (memberCreate: MemberCreate, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'memberCreate' is not null or undefined
assertParamExists('membersCreate', 'memberCreate', memberCreate)
const localVarPath = `/api/members`;
@ -136,7 +175,7 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersGetProfile: async (memberId: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
membersGetProfile: async (memberId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'memberId' is not null or undefined
assertParamExists('membersGetProfile', 'memberId', memberId)
const localVarPath = `/api/members/{memberId}`
@ -180,7 +219,7 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersList: async (limit?: number, offset?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
membersList: async (limit?: number, offset?: number, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/members`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -228,7 +267,7 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersRemove: async (memberId: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
membersRemove: async (memberId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'memberId' is not null or undefined
assertParamExists('membersRemove', 'memberId', memberId)
const localVarPath = `/api/members/{memberId}`
@ -272,7 +311,7 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersUpdatePassword: async (memberId: string, memberPassword: MemberPassword, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
membersUpdatePassword: async (memberId: string, memberPassword: MemberPassword, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'memberId' is not null or undefined
assertParamExists('membersUpdatePassword', 'memberId', memberId)
// verify required parameter 'memberPassword' is not null or undefined
@ -321,7 +360,7 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersUpdateProfile: async (memberId: string, memberProfile: MemberProfile, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
membersUpdateProfile: async (memberId: string, memberProfile: MemberProfile, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'memberId' is not null or undefined
assertParamExists('membersUpdateProfile', 'memberId', memberId)
// verify required parameter 'memberProfile' is not null or undefined
@ -372,6 +411,19 @@ export const MembersApiAxiosParamCreator = function (configuration?: Configurati
export const MembersApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = MembersApiAxiosParamCreator(configuration)
return {
/**
*
* @summary bulk delete members
* @param {MemberBulkDelete} memberBulkDelete
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersBulkDelete(memberBulkDelete: MemberBulkDelete, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersBulkDelete(memberBulkDelete, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersBulkDelete']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
* @summary bulk update members
@ -379,9 +431,11 @@ export const MembersApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersBulkUpdate(memberBulkUpdate: MemberBulkUpdate, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async membersBulkUpdate(memberBulkUpdate: MemberBulkUpdate, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersBulkUpdate(memberBulkUpdate, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersBulkUpdate']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -390,9 +444,11 @@ export const MembersApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersCreate(memberCreate: MemberCreate, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<MemberData>> {
async membersCreate(memberCreate: MemberCreate, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<MemberData>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersCreate(memberCreate, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersCreate']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -401,9 +457,11 @@ export const MembersApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersGetProfile(memberId: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<MemberProfile>> {
async membersGetProfile(memberId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<MemberProfile>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersGetProfile(memberId, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersGetProfile']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -413,9 +471,11 @@ export const MembersApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersList(limit?: number, offset?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MemberData>>> {
async membersList(limit?: number, offset?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MemberData>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersList(limit, offset, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersList']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -424,9 +484,11 @@ export const MembersApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersRemove(memberId: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async membersRemove(memberId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersRemove(memberId, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersRemove']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -436,9 +498,11 @@ export const MembersApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersUpdatePassword(memberId: string, memberPassword: MemberPassword, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async membersUpdatePassword(memberId: string, memberPassword: MemberPassword, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersUpdatePassword(memberId, memberPassword, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersUpdatePassword']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -448,9 +512,11 @@ export const MembersApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async membersUpdateProfile(memberId: string, memberProfile: MemberProfile, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async membersUpdateProfile(memberId: string, memberProfile: MemberProfile, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.membersUpdateProfile(memberId, memberProfile, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MembersApi.membersUpdateProfile']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
}
};
@ -462,6 +528,16 @@ export const MembersApiFp = function(configuration?: Configuration) {
export const MembersApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = MembersApiFp(configuration)
return {
/**
*
* @summary bulk delete members
* @param {MemberBulkDelete} memberBulkDelete
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
membersBulkDelete(memberBulkDelete: MemberBulkDelete, options?: any): AxiosPromise<void> {
return localVarFp.membersBulkDelete(memberBulkDelete, options).then((request) => request(axios, basePath));
},
/**
*
* @summary bulk update members
@ -545,6 +621,18 @@ export const MembersApiFactory = function (configuration?: Configuration, basePa
* @extends {BaseAPI}
*/
export class MembersApi extends BaseAPI {
/**
*
* @summary bulk delete members
* @param {MemberBulkDelete} memberBulkDelete
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersBulkDelete(memberBulkDelete: MemberBulkDelete, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersBulkDelete(memberBulkDelete, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary bulk update members
@ -553,7 +641,7 @@ export class MembersApi extends BaseAPI {
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersBulkUpdate(memberBulkUpdate: MemberBulkUpdate, options?: AxiosRequestConfig) {
public membersBulkUpdate(memberBulkUpdate: MemberBulkUpdate, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersBulkUpdate(memberBulkUpdate, options).then((request) => request(this.axios, this.basePath));
}
@ -565,7 +653,7 @@ export class MembersApi extends BaseAPI {
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersCreate(memberCreate: MemberCreate, options?: AxiosRequestConfig) {
public membersCreate(memberCreate: MemberCreate, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersCreate(memberCreate, options).then((request) => request(this.axios, this.basePath));
}
@ -577,7 +665,7 @@ export class MembersApi extends BaseAPI {
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersGetProfile(memberId: string, options?: AxiosRequestConfig) {
public membersGetProfile(memberId: string, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersGetProfile(memberId, options).then((request) => request(this.axios, this.basePath));
}
@ -590,7 +678,7 @@ export class MembersApi extends BaseAPI {
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersList(limit?: number, offset?: number, options?: AxiosRequestConfig) {
public membersList(limit?: number, offset?: number, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersList(limit, offset, options).then((request) => request(this.axios, this.basePath));
}
@ -602,7 +690,7 @@ export class MembersApi extends BaseAPI {
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersRemove(memberId: string, options?: AxiosRequestConfig) {
public membersRemove(memberId: string, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersRemove(memberId, options).then((request) => request(this.axios, this.basePath));
}
@ -615,7 +703,7 @@ export class MembersApi extends BaseAPI {
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersUpdatePassword(memberId: string, memberPassword: MemberPassword, options?: AxiosRequestConfig) {
public membersUpdatePassword(memberId: string, memberPassword: MemberPassword, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersUpdatePassword(memberId, memberPassword, options).then((request) => request(this.axios, this.basePath));
}
@ -628,7 +716,8 @@ export class MembersApi extends BaseAPI {
* @throws {RequiredError}
* @memberof MembersApi
*/
public membersUpdateProfile(memberId: string, memberProfile: MemberProfile, options?: AxiosRequestConfig) {
public membersUpdateProfile(memberId: string, memberProfile: MemberProfile, options?: RawAxiosRequestConfig) {
return MembersApiFp(this.configuration).membersUpdateProfile(memberId, memberProfile, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -14,29 +14,20 @@
import type { Configuration } from '../configuration';
import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
// @ts-ignore
import { BroadcastStatus } from '../models';
// @ts-ignore
import { ClipboardText } from '../models';
// @ts-ignore
import { ControlStatus } from '../models';
// @ts-ignore
import { ErrorMessage } from '../models';
// @ts-ignore
import { KeyboardMap } from '../models';
// @ts-ignore
import { KeyboardModifiers } from '../models';
// @ts-ignore
import { ScreenConfiguration } from '../models';
// @ts-ignore
import { Settings } from '../models';
import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from '../base';
import type { RequestArgs } from '../base';
import type { BroadcastStatus } from '../models';
import type { ClipboardText } from '../models';
import type { ControlStatus } from '../models';
import type { ErrorMessage } from '../models';
import type { KeyboardMap } from '../models';
import type { KeyboardModifiers } from '../models';
import type { ScreenConfiguration } from '../models';
import type { Settings } from '../models';
/**
* RoomApi - axios parameter creator
* @export
@ -50,7 +41,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
boradcastStart: async (broadcastStatus: BroadcastStatus, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
boradcastStart: async (broadcastStatus: BroadcastStatus, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'broadcastStatus' is not null or undefined
assertParamExists('boradcastStart', 'broadcastStatus', broadcastStatus)
const localVarPath = `/api/room/broadcast/start`;
@ -94,7 +85,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
boradcastStop: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
boradcastStop: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/broadcast/stop`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -133,7 +124,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
broadcastStatus: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
broadcastStatus: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/broadcast`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -172,7 +163,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
clipboardGetImage: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
clipboardGetImage: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/clipboard/image.png`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -211,7 +202,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
clipboardGetText: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
clipboardGetText: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/clipboard`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -251,7 +242,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
clipboardSetText: async (clipboardText: ClipboardText, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
clipboardSetText: async (clipboardText: ClipboardText, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'clipboardText' is not null or undefined
assertParamExists('clipboardSetText', 'clipboardText', clipboardText)
const localVarPath = `/api/room/clipboard`;
@ -296,7 +287,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
controlGive: async (sessionId: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
controlGive: async (sessionId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'sessionId' is not null or undefined
assertParamExists('controlGive', 'sessionId', sessionId)
const localVarPath = `/api/room/control/give/{sessionId}`
@ -338,7 +329,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
controlRelease: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
controlRelease: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/control/release`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -377,7 +368,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
controlRequest: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
controlRequest: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/control/request`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -416,7 +407,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
controlReset: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
controlReset: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/control/reset`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -455,7 +446,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
controlStatus: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
controlStatus: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/control`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -494,7 +485,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
controlTake: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
controlTake: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/control/take`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -533,7 +524,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
keyboardMapGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
keyboardMapGet: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/keyboard/map`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -573,7 +564,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
keyboardMapSet: async (keyboardMap: KeyboardMap, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
keyboardMapSet: async (keyboardMap: KeyboardMap, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'keyboardMap' is not null or undefined
assertParamExists('keyboardMapSet', 'keyboardMap', keyboardMap)
const localVarPath = `/api/room/keyboard/map`;
@ -617,7 +608,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
keyboardModifiersGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
keyboardModifiersGet: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/keyboard/modifiers`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -657,7 +648,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
keyboardModifiersSet: async (keyboardModifiers: KeyboardModifiers, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
keyboardModifiersSet: async (keyboardModifiers: KeyboardModifiers, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'keyboardModifiers' is not null or undefined
assertParamExists('keyboardModifiersSet', 'keyboardModifiers', keyboardModifiers)
const localVarPath = `/api/room/keyboard/modifiers`;
@ -701,7 +692,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
screenCastImage: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
screenCastImage: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/screen/cast.jpg`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -740,7 +731,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
screenConfiguration: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
screenConfiguration: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/screen`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -780,7 +771,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
screenConfigurationChange: async (screenConfiguration: ScreenConfiguration, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
screenConfigurationChange: async (screenConfiguration: ScreenConfiguration, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'screenConfiguration' is not null or undefined
assertParamExists('screenConfigurationChange', 'screenConfiguration', screenConfiguration)
const localVarPath = `/api/room/screen`;
@ -824,7 +815,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
screenConfigurationsList: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
screenConfigurationsList: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/screen/configurations`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -863,7 +854,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
screenShotImage: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
screenShotImage: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/screen/shot.jpg`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -902,7 +893,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
settingsGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
settingsGet: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/settings`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -942,7 +933,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
settingsSet: async (settings: Settings, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
settingsSet: async (settings: Settings, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'settings' is not null or undefined
assertParamExists('settingsSet', 'settings', settings)
const localVarPath = `/api/room/settings`;
@ -987,7 +978,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
uploadDialog: async (files?: Array<File>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
uploadDialog: async (files?: Array<File>, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/upload/dialog`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -1036,7 +1027,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
uploadDialogClose: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
uploadDialogClose: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/upload/dialog`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -1078,7 +1069,7 @@ export const RoomApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
uploadDrop: async (x?: number, y?: number, files?: Array<File>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
uploadDrop: async (x?: number, y?: number, files?: Array<File>, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/room/upload/drop`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -1146,9 +1137,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async boradcastStart(broadcastStatus: BroadcastStatus, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async boradcastStart(broadcastStatus: BroadcastStatus, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.boradcastStart(broadcastStatus, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.boradcastStart']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1156,9 +1149,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async boradcastStop(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async boradcastStop(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.boradcastStop(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.boradcastStop']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1166,9 +1161,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async broadcastStatus(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<BroadcastStatus>> {
async broadcastStatus(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<BroadcastStatus>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.broadcastStatus(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.broadcastStatus']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1176,9 +1173,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async clipboardGetImage(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
async clipboardGetImage(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.clipboardGetImage(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.clipboardGetImage']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1186,9 +1185,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async clipboardGetText(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ClipboardText>> {
async clipboardGetText(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ClipboardText>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.clipboardGetText(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.clipboardGetText']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1197,9 +1198,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async clipboardSetText(clipboardText: ClipboardText, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async clipboardSetText(clipboardText: ClipboardText, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.clipboardSetText(clipboardText, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.clipboardSetText']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1208,9 +1211,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async controlGive(sessionId: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async controlGive(sessionId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.controlGive(sessionId, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.controlGive']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1218,9 +1223,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async controlRelease(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async controlRelease(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.controlRelease(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.controlRelease']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1228,9 +1235,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async controlRequest(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async controlRequest(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.controlRequest(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.controlRequest']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1238,9 +1247,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async controlReset(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async controlReset(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.controlReset(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.controlReset']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1248,9 +1259,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async controlStatus(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ControlStatus>> {
async controlStatus(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ControlStatus>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.controlStatus(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.controlStatus']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1258,9 +1271,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async controlTake(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async controlTake(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.controlTake(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.controlTake']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1268,9 +1283,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async keyboardMapGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<KeyboardMap>> {
async keyboardMapGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<KeyboardMap>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.keyboardMapGet(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.keyboardMapGet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1279,9 +1296,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async keyboardMapSet(keyboardMap: KeyboardMap, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async keyboardMapSet(keyboardMap: KeyboardMap, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.keyboardMapSet(keyboardMap, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.keyboardMapSet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1289,9 +1308,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async keyboardModifiersGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<KeyboardModifiers>> {
async keyboardModifiersGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<KeyboardModifiers>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.keyboardModifiersGet(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.keyboardModifiersGet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1300,9 +1321,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async keyboardModifiersSet(keyboardModifiers: KeyboardModifiers, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async keyboardModifiersSet(keyboardModifiers: KeyboardModifiers, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.keyboardModifiersSet(keyboardModifiers, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.keyboardModifiersSet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1310,9 +1333,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async screenCastImage(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
async screenCastImage(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.screenCastImage(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.screenCastImage']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1320,9 +1345,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async screenConfiguration(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ScreenConfiguration>> {
async screenConfiguration(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ScreenConfiguration>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.screenConfiguration(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.screenConfiguration']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1331,9 +1358,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async screenConfigurationChange(screenConfiguration: ScreenConfiguration, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ScreenConfiguration>> {
async screenConfigurationChange(screenConfiguration: ScreenConfiguration, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ScreenConfiguration>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.screenConfigurationChange(screenConfiguration, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.screenConfigurationChange']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1341,9 +1370,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async screenConfigurationsList(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<ScreenConfiguration>>> {
async screenConfigurationsList(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<ScreenConfiguration>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.screenConfigurationsList(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.screenConfigurationsList']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1351,9 +1382,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async screenShotImage(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
async screenShotImage(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.screenShotImage(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.screenShotImage']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1361,9 +1394,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async settingsGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Settings>> {
async settingsGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Settings>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.settingsGet(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.settingsGet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1372,9 +1407,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async settingsSet(settings: Settings, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async settingsSet(settings: Settings, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.settingsSet(settings, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.settingsSet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1383,9 +1420,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async uploadDialog(files?: Array<File>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async uploadDialog(files?: Array<File>, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.uploadDialog(files, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.uploadDialog']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1393,9 +1432,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async uploadDialogClose(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async uploadDialogClose(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.uploadDialogClose(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.uploadDialogClose']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -1406,9 +1447,11 @@ export const RoomApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async uploadDrop(x?: number, y?: number, files?: Array<File>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async uploadDrop(x?: number, y?: number, files?: Array<File>, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.uploadDrop(x, y, files, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RoomApi.uploadDrop']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
}
};
@ -1683,7 +1726,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public boradcastStart(broadcastStatus: BroadcastStatus, options?: AxiosRequestConfig) {
public boradcastStart(broadcastStatus: BroadcastStatus, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).boradcastStart(broadcastStatus, options).then((request) => request(this.axios, this.basePath));
}
@ -1694,7 +1737,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public boradcastStop(options?: AxiosRequestConfig) {
public boradcastStop(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).boradcastStop(options).then((request) => request(this.axios, this.basePath));
}
@ -1705,7 +1748,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public broadcastStatus(options?: AxiosRequestConfig) {
public broadcastStatus(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).broadcastStatus(options).then((request) => request(this.axios, this.basePath));
}
@ -1716,7 +1759,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public clipboardGetImage(options?: AxiosRequestConfig) {
public clipboardGetImage(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).clipboardGetImage(options).then((request) => request(this.axios, this.basePath));
}
@ -1727,7 +1770,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public clipboardGetText(options?: AxiosRequestConfig) {
public clipboardGetText(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).clipboardGetText(options).then((request) => request(this.axios, this.basePath));
}
@ -1739,7 +1782,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public clipboardSetText(clipboardText: ClipboardText, options?: AxiosRequestConfig) {
public clipboardSetText(clipboardText: ClipboardText, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).clipboardSetText(clipboardText, options).then((request) => request(this.axios, this.basePath));
}
@ -1751,7 +1794,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public controlGive(sessionId: string, options?: AxiosRequestConfig) {
public controlGive(sessionId: string, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).controlGive(sessionId, options).then((request) => request(this.axios, this.basePath));
}
@ -1762,7 +1805,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public controlRelease(options?: AxiosRequestConfig) {
public controlRelease(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).controlRelease(options).then((request) => request(this.axios, this.basePath));
}
@ -1773,7 +1816,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public controlRequest(options?: AxiosRequestConfig) {
public controlRequest(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).controlRequest(options).then((request) => request(this.axios, this.basePath));
}
@ -1784,7 +1827,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public controlReset(options?: AxiosRequestConfig) {
public controlReset(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).controlReset(options).then((request) => request(this.axios, this.basePath));
}
@ -1795,7 +1838,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public controlStatus(options?: AxiosRequestConfig) {
public controlStatus(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).controlStatus(options).then((request) => request(this.axios, this.basePath));
}
@ -1806,7 +1849,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public controlTake(options?: AxiosRequestConfig) {
public controlTake(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).controlTake(options).then((request) => request(this.axios, this.basePath));
}
@ -1817,7 +1860,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public keyboardMapGet(options?: AxiosRequestConfig) {
public keyboardMapGet(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).keyboardMapGet(options).then((request) => request(this.axios, this.basePath));
}
@ -1829,7 +1872,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public keyboardMapSet(keyboardMap: KeyboardMap, options?: AxiosRequestConfig) {
public keyboardMapSet(keyboardMap: KeyboardMap, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).keyboardMapSet(keyboardMap, options).then((request) => request(this.axios, this.basePath));
}
@ -1840,7 +1883,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public keyboardModifiersGet(options?: AxiosRequestConfig) {
public keyboardModifiersGet(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).keyboardModifiersGet(options).then((request) => request(this.axios, this.basePath));
}
@ -1852,7 +1895,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public keyboardModifiersSet(keyboardModifiers: KeyboardModifiers, options?: AxiosRequestConfig) {
public keyboardModifiersSet(keyboardModifiers: KeyboardModifiers, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).keyboardModifiersSet(keyboardModifiers, options).then((request) => request(this.axios, this.basePath));
}
@ -1863,7 +1906,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public screenCastImage(options?: AxiosRequestConfig) {
public screenCastImage(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).screenCastImage(options).then((request) => request(this.axios, this.basePath));
}
@ -1874,7 +1917,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public screenConfiguration(options?: AxiosRequestConfig) {
public screenConfiguration(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).screenConfiguration(options).then((request) => request(this.axios, this.basePath));
}
@ -1886,7 +1929,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public screenConfigurationChange(screenConfiguration: ScreenConfiguration, options?: AxiosRequestConfig) {
public screenConfigurationChange(screenConfiguration: ScreenConfiguration, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).screenConfigurationChange(screenConfiguration, options).then((request) => request(this.axios, this.basePath));
}
@ -1897,7 +1940,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public screenConfigurationsList(options?: AxiosRequestConfig) {
public screenConfigurationsList(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).screenConfigurationsList(options).then((request) => request(this.axios, this.basePath));
}
@ -1908,7 +1951,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public screenShotImage(options?: AxiosRequestConfig) {
public screenShotImage(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).screenShotImage(options).then((request) => request(this.axios, this.basePath));
}
@ -1919,7 +1962,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public settingsGet(options?: AxiosRequestConfig) {
public settingsGet(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).settingsGet(options).then((request) => request(this.axios, this.basePath));
}
@ -1931,7 +1974,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public settingsSet(settings: Settings, options?: AxiosRequestConfig) {
public settingsSet(settings: Settings, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).settingsSet(settings, options).then((request) => request(this.axios, this.basePath));
}
@ -1943,7 +1986,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public uploadDialog(files?: Array<File>, options?: AxiosRequestConfig) {
public uploadDialog(files?: Array<File>, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).uploadDialog(files, options).then((request) => request(this.axios, this.basePath));
}
@ -1954,7 +1997,7 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public uploadDialogClose(options?: AxiosRequestConfig) {
public uploadDialogClose(options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).uploadDialogClose(options).then((request) => request(this.axios, this.basePath));
}
@ -1968,7 +2011,8 @@ export class RoomApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RoomApi
*/
public uploadDrop(x?: number, y?: number, files?: Array<File>, options?: AxiosRequestConfig) {
public uploadDrop(x?: number, y?: number, files?: Array<File>, options?: RawAxiosRequestConfig) {
return RoomApiFp(this.configuration).uploadDrop(x, y, files, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -14,19 +14,15 @@
import type { Configuration } from '../configuration';
import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
// @ts-ignore
import { ErrorMessage } from '../models';
// @ts-ignore
import { SessionData } from '../models';
// @ts-ignore
import { SessionLogin } from '../models';
import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from '../base';
import type { RequestArgs } from '../base';
import type { ErrorMessage } from '../models';
import type { SessionData } from '../models';
import type { SessionLogin } from '../models';
/**
* SessionApi - axios parameter creator
* @export
@ -40,7 +36,7 @@ export const SessionApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
login: async (sessionLogin: SessionLogin, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
login: async (sessionLogin: SessionLogin, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'sessionLogin' is not null or undefined
assertParamExists('login', 'sessionLogin', sessionLogin)
const localVarPath = `/api/login`;
@ -75,7 +71,7 @@ export const SessionApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
logout: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
logout: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/logout`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -99,6 +95,45 @@ export const SessionApiAxiosParamCreator = function (configuration?: Configurati
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary get sessions
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
sessionsGet: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sessions`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication CookieAuth required
// authentication TokenAuth required
await setApiKeyToObject(localVarQueryParameter, "token", configuration)
// authentication BearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
@ -114,7 +149,7 @@ export const SessionApiAxiosParamCreator = function (configuration?: Configurati
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
whoami: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
whoami: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/whoami`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -164,9 +199,11 @@ export const SessionApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async login(sessionLogin: SessionLogin, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SessionData>> {
async login(sessionLogin: SessionLogin, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SessionData>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.login(sessionLogin, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['SessionApi.login']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -174,9 +211,23 @@ export const SessionApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async logout(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
async logout(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.logout(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['SessionApi.logout']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
* @summary get sessions
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async sessionsGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<SessionData>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.sessionsGet(options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['SessionApi.sessionsGet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
@ -184,9 +235,11 @@ export const SessionApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async whoami(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SessionData>> {
async whoami(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SessionData>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.whoami(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['SessionApi.whoami']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
}
};
@ -217,6 +270,15 @@ export const SessionApiFactory = function (configuration?: Configuration, basePa
logout(options?: any): AxiosPromise<void> {
return localVarFp.logout(options).then((request) => request(axios, basePath));
},
/**
*
* @summary get sessions
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
sessionsGet(options?: any): AxiosPromise<Array<SessionData>> {
return localVarFp.sessionsGet(options).then((request) => request(axios, basePath));
},
/**
*
* @summary whoami
@ -244,7 +306,7 @@ export class SessionApi extends BaseAPI {
* @throws {RequiredError}
* @memberof SessionApi
*/
public login(sessionLogin: SessionLogin, options?: AxiosRequestConfig) {
public login(sessionLogin: SessionLogin, options?: RawAxiosRequestConfig) {
return SessionApiFp(this.configuration).login(sessionLogin, options).then((request) => request(this.axios, this.basePath));
}
@ -255,10 +317,21 @@ export class SessionApi extends BaseAPI {
* @throws {RequiredError}
* @memberof SessionApi
*/
public logout(options?: AxiosRequestConfig) {
public logout(options?: RawAxiosRequestConfig) {
return SessionApiFp(this.configuration).logout(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary get sessions
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SessionApi
*/
public sessionsGet(options?: RawAxiosRequestConfig) {
return SessionApiFp(this.configuration).sessionsGet(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary whoami
@ -266,7 +339,8 @@ export class SessionApi extends BaseAPI {
* @throws {RequiredError}
* @memberof SessionApi
*/
public whoami(options?: AxiosRequestConfig) {
public whoami(options?: RawAxiosRequestConfig) {
return SessionApiFp(this.configuration).whoami(options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -16,7 +16,7 @@
import type { Configuration } from './configuration';
// Some imports not used depending on template conditions
// @ts-ignore
import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
export const BASE_PATH = "http://localhost:3000".replace(/\/+$/, "");
@ -39,7 +39,7 @@ export const COLLECTION_FORMATS = {
*/
export interface RequestArgs {
url: string;
options: AxiosRequestConfig;
options: RawAxiosRequestConfig;
}
/**
@ -53,7 +53,7 @@ export class BaseAPI {
constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
if (configuration) {
this.configuration = configuration;
this.basePath = configuration.basePath || this.basePath;
this.basePath = configuration.basePath ?? basePath;
}
}
};
@ -70,3 +70,17 @@ export class RequiredError extends Error {
this.name = "RequiredError"
}
}
interface ServerMap {
[key: string]: {
url: string,
description: string,
}[];
}
/**
*
* @export
*/
export const operationServerMap: ServerMap = {
}

View File

@ -144,7 +144,7 @@ export const toPathString = function (url: URL) {
*/
export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) {
return <T = unknown, R = AxiosResponse<T>>(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url};
const axiosRequestArgs = {...axiosArgs.options, url: (axios.defaults.baseURL ? '' : configuration?.basePath ?? basePath) + axiosArgs.url};
return axios.request<T, R>(axiosRequestArgs);
};
}

View File

@ -19,6 +19,7 @@ export interface ConfigurationParameters {
password?: string;
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
basePath?: string;
serverIndex?: number;
baseOptions?: any;
formDataCtor?: new () => any;
}
@ -58,6 +59,13 @@ export class Configuration {
* @memberof Configuration
*/
basePath?: string;
/**
* override server index
*
* @type {number}
* @memberof Configuration
*/
serverIndex?: number;
/**
* base options for axios calls
*
@ -80,6 +88,7 @@ export class Configuration {
this.password = param.password;
this.accessToken = param.accessToken;
this.basePath = param.basePath;
this.serverIndex = param.serverIndex;
this.baseOptions = param.baseOptions;
this.formDataCtor = param.formDataCtor;
}

View File

@ -1,18 +1,19 @@
export * from './batch-request'
export * from './batch-response'
export * from './broadcast-status'
export * from './clipboard-text'
export * from './control-status'
export * from './error-message'
export * from './keyboard-map'
export * from './keyboard-modifiers'
export * from './member-bulk-update'
export * from './member-create'
export * from './member-data'
export * from './member-password'
export * from './member-profile'
export * from './screen-configuration'
export * from './session-data'
export * from './session-login'
export * from './session-state'
export * from './settings'
export * from './batch-request';
export * from './batch-response';
export * from './broadcast-status';
export * from './clipboard-text';
export * from './control-status';
export * from './error-message';
export * from './keyboard-map';
export * from './keyboard-modifiers';
export * from './member-bulk-delete';
export * from './member-bulk-update';
export * from './member-create';
export * from './member-data';
export * from './member-password';
export * from './member-profile';
export * from './screen-configuration';
export * from './session-data';
export * from './session-login';
export * from './session-state';
export * from './settings';

View File

@ -0,0 +1,30 @@
/* tslint:disable */
/* eslint-disable */
/**
* n.eko REST API
* Next Gen Renderer.
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/**
*
* @export
* @interface MemberBulkDelete
*/
export interface MemberBulkDelete {
/**
*
* @type {Array<string>}
* @memberof MemberBulkDelete
*/
'ids'?: Array<string>;
}

View File

@ -15,7 +15,7 @@
// May contain unused imports in some cases
// @ts-ignore
import { MemberProfile } from './member-profile';
import type { MemberProfile } from './member-profile';
/**
*

View File

@ -14,8 +14,7 @@
// May contain unused imports in some cases
// @ts-ignore
import { MemberProfile } from './member-profile';
import type { MemberProfile } from './member-profile';
/**
*

View File

@ -14,8 +14,7 @@
// May contain unused imports in some cases
// @ts-ignore
import { MemberProfile } from './member-profile';
import type { MemberProfile } from './member-profile';
/**
*

View File

@ -14,11 +14,9 @@
// May contain unused imports in some cases
// @ts-ignore
import { MemberProfile } from './member-profile';
import type { MemberProfile } from './member-profile';
// May contain unused imports in some cases
// @ts-ignore
import { SessionState } from './session-state';
import type { SessionState } from './session-state';
/**
*

View File

@ -13,265 +13,250 @@
}
</style>
<script lang="ts">
import { Vue, Component, Ref, Prop, Watch } from 'vue-property-decorator'
<script lang="ts" setup>
import { SessionCursors, Cursor, Session } from './types/state'
import { InactiveCursorDrawFunction, Dimension } from './types/cursors'
import { getMovementXYatPercent } from './utils/canvas-movement'
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
// How often are position data arriving
const POS_INTERVAL_MS = 750
// How many pixel change is considered as movement
const POS_THRESHOLD_PX = 20
import type { SessionCursors, Cursor, Session } from './types/state'
import type { InactiveCursorDrawFunction, Dimension } from './types/cursors'
import { getMovementXYatPercent } from './utils/canvas-movement'
@Component({
name: 'neko-cursors',
})
export default class extends Vue {
@Ref('overlay') readonly _overlay!: HTMLCanvasElement
_ctx!: CanvasRenderingContext2D
// How often are position data arriving
const POS_INTERVAL_MS = 750
// How many pixel change is considered as movement
const POS_THRESHOLD_PX = 20
canvasScale = window.devicePixelRatio
const props = defineProps<{
sessions: Record<string, Session>
sessionId: string
hostId: string | null
screenSize: Dimension
canvasSize: Dimension
cursors: SessionCursors[]
cursorDraw: InactiveCursorDrawFunction | null
fps: number
}>()
@Prop()
readonly sessions!: Record<string, Session>
const overlay = ref<HTMLCanvasElement | null>(null)
const ctx = ref<CanvasRenderingContext2D | null>(null)
const canvasScale = ref(window.devicePixelRatio)
@Prop()
readonly sessionId!: string
let unsubscribePixelRatioChange = null as (() => void) | null
@Prop()
readonly hostId!: string | null
onMounted(() => {
// get canvas overlay context
const canvas = overlay.value
if (canvas != null) {
ctx.value = canvas.getContext('2d')
@Prop()
readonly screenSize!: Dimension
@Prop()
readonly canvasSize!: Dimension
@Prop()
readonly cursors!: SessionCursors[]
@Prop()
readonly cursorDraw!: InactiveCursorDrawFunction | null
@Prop()
readonly fps!: number
mounted() {
// get canvas overlay context
const ctx = this._overlay.getContext('2d')
if (ctx != null) {
this._ctx = ctx
}
// synchronize intrinsic with extrinsic dimensions
const { width, height } = this._overlay.getBoundingClientRect()
this.canvasResize({ width, height })
// react to pixel ratio changes
this.onPixelRatioChange()
// store last drawing points
this._last_points = {}
}
beforeDestroy() {
// stop pixel ratio change listener
if (this.unsubscribePixelRatioChange) {
this.unsubscribePixelRatioChange()
}
}
private unsubscribePixelRatioChange?: () => void
private onPixelRatioChange() {
if (this.unsubscribePixelRatioChange) {
this.unsubscribePixelRatioChange()
}
const media = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
media.addEventListener('change', this.onPixelRatioChange)
this.unsubscribePixelRatioChange = () => {
media.removeEventListener('change', this.onPixelRatioChange)
}
this.canvasScale = window.devicePixelRatio
this.onCanvasSizeChange(this.canvasSize)
}
@Watch('canvasSize')
onCanvasSizeChange({ width, height }: Dimension) {
this.canvasResize({ width, height })
this.canvasUpdateCursors()
}
canvasResize({ width, height }: Dimension) {
this._overlay.width = width * this.canvasScale
this._overlay.height = height * this.canvasScale
this._ctx.setTransform(this.canvasScale, 0, 0, this.canvasScale, 0, 0)
}
// start as undefined to prevent jumping
private _last_animation_time!: number
// current animation progress (0-1)
private _percent!: number
// points to be animated for each session
private _points!: SessionCursors[]
// last points coordinates for each session
private _last_points!: Record<string, Cursor>
canvasAnimateFrame(now: number = NaN) {
// request another frame
if (this._percent <= 1) window.requestAnimationFrame(this.canvasAnimateFrame)
// calc elapsed time since last loop
const elapsed = now - this._last_animation_time
// skip if fps is set and elapsed time is less than fps
if (this.fps > 0 && elapsed < 1000 / this.fps) return
// calc current animation progress
const delta = elapsed / POS_INTERVAL_MS
this._last_animation_time = now
// skip very first delta to prevent jumping
if (isNaN(delta)) return
// set the animation position
this._percent += delta
// draw points for current frame
this.canvasDrawPoints(this._percent)
}
canvasDrawPoints(percent: number = 1) {
// clear canvas
this.canvasClear()
// draw current position
for (const p of this._points) {
const { x, y } = getMovementXYatPercent(p.cursors, percent)
this.canvasDrawCursor(x, y, p.id)
}
}
@Watch('hostId')
@Watch('cursors')
canvasUpdateCursors() {
let new_last_points = {} as Record<string, Cursor>
// track unchanged cursors
let unchanged = 0
// create points for animation
this._points = []
for (const { id, cursors } of this.cursors) {
if (
// if there are no positions
cursors.length == 0 ||
// ignore own cursor
id == this.sessionId ||
// ignore host's cursor
id == this.hostId
) {
unchanged++
continue
}
// get last point
const new_last_point = cursors[cursors.length - 1]
// add last cursor position to cursors (if available)
let pos = { id } as SessionCursors
if (id in this._last_points) {
const last_point = this._last_points[id]
// if cursor did not move considerably
if (
Math.abs(last_point.x - new_last_point.x) < POS_THRESHOLD_PX &&
Math.abs(last_point.y - new_last_point.y) < POS_THRESHOLD_PX
) {
// we knew that this cursor did not change, but other
// might, so we keep only one point to be drawn
pos.cursors = [new_last_point]
// and increase unchanged counter
unchanged++
} else {
// if cursor moved, we want to include last point
// in the animation, so that movement can be seamless
pos.cursors = [last_point, ...cursors]
}
} else {
// if cursor does not have last point, it is not
// displayed in canvas and it should be now
pos.cursors = [...cursors]
}
new_last_points[id] = new_last_point
this._points.push(pos)
}
// apply new last points
this._last_points = new_last_points
// no cursors to animate
if (this._points.length == 0) {
this.canvasClear()
return
}
// if all cursors are unchanged
if (unchanged == this.cursors.length) {
// draw only last known position without animation
this.canvasDrawPoints()
return
}
// start animation if not running
const percent = this._percent
this._percent = 0
if (percent > 1 || !percent) {
this.canvasAnimateFrame()
}
}
canvasDrawCursor(x: number, y: number, id: string) {
// get intrinsic dimensions
const { width, height } = this.canvasSize
x = Math.round((x / this.screenSize.width) * width)
y = Math.round((y / this.screenSize.height) * height)
// reset transformation, X and Y will be 0 again
this._ctx.setTransform(this.canvasScale, 0, 0, this.canvasScale, 0, 0)
// use custom draw function, if available
if (this.cursorDraw) {
this.cursorDraw(this._ctx, x, y, id)
return
}
// get cursor tag
const cursorTag = this.sessions[id]?.profile.name || ''
// draw inactive cursor tag
this._ctx.font = '14px Arial, sans-serif'
this._ctx.textBaseline = 'top'
this._ctx.shadowColor = 'black'
this._ctx.shadowBlur = 2
this._ctx.lineWidth = 2
this._ctx.fillStyle = 'black'
this._ctx.strokeText(cursorTag, x, y)
this._ctx.shadowBlur = 0
this._ctx.fillStyle = 'white'
this._ctx.fillText(cursorTag, x, y)
}
canvasClear() {
// reset transformation, X and Y will be 0 again
this._ctx.setTransform(this.canvasScale, 0, 0, this.canvasScale, 0, 0)
const { width, height } = this.canvasSize
this._ctx.clearRect(0, 0, width, height)
}
// synchronize intrinsic with extrinsic dimensions
const { width, height } = canvas.getBoundingClientRect()
canvasResize({ width, height })
}
// react to pixel ratio changes
onPixelRatioChange()
// store last drawing points
last_points.value = {}
})
onBeforeUnmount(() => {
// stop pixel ratio change listener
if (unsubscribePixelRatioChange) {
unsubscribePixelRatioChange()
}
})
function onPixelRatioChange() {
if (unsubscribePixelRatioChange) {
unsubscribePixelRatioChange()
}
const media = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
media.addEventListener('change', onPixelRatioChange)
unsubscribePixelRatioChange = () => {
media.removeEventListener('change', onPixelRatioChange)
}
canvasScale.value = window.devicePixelRatio
onCanvasSizeChange(props.canvasSize)
}
function onCanvasSizeChange({ width, height }: Dimension) {
canvasResize({ width, height })
canvasUpdateCursors()
}
watch(() => props.canvasSize, onCanvasSizeChange)
function canvasResize({ width, height }: Dimension) {
overlay.value!.width = width * canvasScale.value
overlay.value!.height = height * canvasScale.value
ctx.value?.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
}
// start as undefined to prevent jumping
const last_animation_time = ref<number>(0)
// current animation progress (0-1)
const percent = ref<number>(0)
// points to be animated for each session
const points = ref<SessionCursors[]>([])
// last points coordinates for each session
const last_points = ref<Record<string, Cursor>>({})
function canvasAnimateFrame(now: number = NaN) {
// request another frame
if (percent.value <= 1) window.requestAnimationFrame(canvasAnimateFrame)
// calc elapsed time since last loop
const elapsed = now - last_animation_time.value
// skip if fps is set and elapsed time is less than fps
if (props.fps > 0 && elapsed < 1000 / props.fps) return
// calc current animation progress
const delta = elapsed / POS_INTERVAL_MS
last_animation_time.value = now
// skip very first delta to prevent jumping
if (isNaN(delta)) return
// set the animation position
percent.value += delta
// draw points for current frame
canvasDrawPoints(percent.value)
}
function canvasDrawPoints(percent: number = 1) {
// clear canvas
canvasClear()
// draw current position
for (const p of points.value) {
const { x, y } = getMovementXYatPercent(p.cursors, percent)
canvasDrawCursor(x, y, p.id)
}
}
function canvasUpdateCursors() {
let new_last_points = {} as Record<string, Cursor>
// track unchanged cursors
let unchanged = 0
// create points for animation
points.value = []
for (const { id, cursors } of props.cursors) {
if (
// if there are no positions
cursors.length == 0 ||
// ignore own cursor
id == props.sessionId ||
// ignore host's cursor
id == props.hostId
) {
unchanged++
continue
}
// get last point
const new_last_point = cursors[cursors.length - 1]
// add last cursor position to cursors (if available)
let pos = { id } as SessionCursors
if (id in last_points.value) {
const last_point = last_points.value[id]
// if cursor did not move considerably
if (
Math.abs(last_point.x - new_last_point.x) < POS_THRESHOLD_PX &&
Math.abs(last_point.y - new_last_point.y) < POS_THRESHOLD_PX
) {
// we knew that this cursor did not change, but other
// might, so we keep only one point to be drawn
pos.cursors = [new_last_point]
// and increase unchanged counter
unchanged++
} else {
// if cursor moved, we want to include last point
// in the animation, so that movement can be seamless
pos.cursors = [last_point, ...cursors]
}
} else {
// if cursor does not have last point, it is not
// displayed in canvas and it should be now
pos.cursors = [...cursors]
}
new_last_points[id] = new_last_point
points.value.push(pos)
}
// apply new last points
last_points.value = new_last_points
// no cursors to animate
if (points.value.length == 0) {
canvasClear()
return
}
// if all cursors are unchanged
if (unchanged == props.cursors.length) {
// draw only last known position without animation
canvasDrawPoints()
return
}
// start animation if not running
const p = percent.value
percent.value = 0
if (p > 1 || !p) {
canvasAnimateFrame()
}
}
watch(() => props.hostId, canvasUpdateCursors)
watch(() => props.cursors, canvasUpdateCursors)
function canvasDrawCursor(x: number, y: number, id: string) {
// get intrinsic dimensions
const { width, height } = props.canvasSize
x = Math.round((x / props.screenSize.width) * width)
y = Math.round((y / props.screenSize.height) * height)
// reset transformation, X and Y will be 0 again
ctx.value!.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
// use custom draw function, if available
if (props.cursorDraw) {
props.cursorDraw(ctx.value!, x, y, id)
return
}
// get cursor tag
const cursorTag = props.sessions[id]?.profile.name || ''
// draw inactive cursor tag
ctx.value!.font = '14px Arial, sans-serif'
ctx.value!.textBaseline = 'top'
ctx.value!.shadowColor = 'black'
ctx.value!.shadowBlur = 2
ctx.value!.lineWidth = 2
ctx.value!.fillStyle = 'black'
ctx.value!.strokeText(cursorTag, x, y)
ctx.value!.shadowBlur = 0
ctx.value!.fillStyle = 'white'
ctx.value!.fillText(cursorTag, x, y)
}
function canvasClear() {
// reset transformation, X and Y will be 0 again
ctx.value?.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
const { width, height } = props.canvasSize
ctx.value?.clearRect(0, 0, width, height)
}
</script>

View File

@ -1,12 +1,11 @@
import Vue from 'vue'
import EventEmitter from 'eventemitter3'
import * as EVENT from '../types/events'
import * as webrtcTypes from '../types/webrtc'
import type * as webrtcTypes from '../types/webrtc'
import { NekoWebSocket } from './websocket'
import { NekoLoggerFactory } from './logger'
import { NekoWebRTC } from './webrtc'
import { Connection, WebRTCStats } from '../types/state'
import type { Connection, WebRTCStats } from '../types/state'
import { Reconnector } from './reconnector'
import { WebsocketReconnector } from './reconnector/websocket'
@ -56,11 +55,11 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
}
this._onConnectHandle = () => {
Vue.set(this._state.websocket, 'connected', this.websocket.connected)
Vue.set(this._state.webrtc, 'connected', this.webrtc.connected)
this._state.websocket.connected = this.websocket.connected // TODO: Vue.Set
this._state.webrtc.connected = this.webrtc.connected // TODO: Vue.Set
if (this._state.status !== 'connected' && this.websocket.connected && this.webrtc.connected) {
Vue.set(this._state, 'status', 'connected')
this._state.status = 'connected' // TODO: Vue.Set
}
if (this.websocket.connected && !this.webrtc.connected) {
@ -76,15 +75,15 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
}
this._onDisconnectHandle = () => {
Vue.set(this._state.websocket, 'connected', this.websocket.connected)
Vue.set(this._state.webrtc, 'connected', this.webrtc.connected)
this._state.websocket.connected = this.websocket.connected // TODO: Vue.Set
this._state.webrtc.connected = this.webrtc.connected // TODO: Vue.Set
if (this._state.webrtc.stable && !this.webrtc.connected) {
Vue.set(this._state.webrtc, 'stable', false)
this._state.webrtc.stable = false // TODO: Vue.Set
}
if (this._state.status === 'connected' && this.activated) {
Vue.set(this._state, 'status', 'connecting')
this._state.status = 'connecting' // TODO: Vue.Set
}
}
@ -99,13 +98,13 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
// synchronize webrtc stats with global state
this._webrtcStatsHandle = (stats: WebRTCStats) => {
Vue.set(this._state.webrtc, 'stats', stats)
this._state.webrtc.stats = stats // TODO: Vue.Set
}
this.webrtc.on('stats', this._webrtcStatsHandle)
// synchronize webrtc stable with global state
this._webrtcStableHandle = (isStable: boolean) => {
Vue.set(this._state.webrtc, 'stable', isStable)
this._state.webrtc.stable = isStable // TODO: Vue.Set
}
this.webrtc.on('stable', this._webrtcStableHandle)
@ -138,7 +137,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
window.clearTimeout(webrtcFallbackTimeout)
}
Vue.set(this._state.webrtc, 'connected', true)
this._state.webrtc.connected = true // TODO: Vue.Set
webrtcCongestion = 0
return
}
@ -146,7 +145,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
// try to downgrade quality if it happend many times
if (++webrtcCongestion >= WEBRTC_RECONN_FAILED_ATTEMPTS) {
webrtcFallbackTimeout = window.setTimeout(() => {
Vue.set(this._state.webrtc, 'connected', false)
this._state.webrtc.connected = false // TODO: Vue.Set
}, WEBRTC_FALLBACK_TIMEOUT_MS)
webrtcCongestion = 0
@ -193,7 +192,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
this._open = true
this._peerRequest = peerRequest
Vue.set(this._state, 'status', 'connecting')
this._state.status = 'connecting' // TODO: Vue.Set
// open all reconnectors with deferred connection
Object.values(this._reconnector).forEach((r) => r.open(true))
@ -208,9 +207,9 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
if (active) {
// set state to disconnected
Vue.set(this._state.websocket, 'connected', false)
Vue.set(this._state.webrtc, 'connected', false)
Vue.set(this._state, 'status', 'disconnected')
this._state.websocket.connected = false // TODO: Vue.Set
this._state.webrtc.connected = false // TODO: Vue.Set
this._state.status = 'disconnected' // TODO: Vue.Set
this._closing = true
}
@ -243,9 +242,9 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
Object.values(this._reconnector).forEach((r) => r.destroy())
// set state to disconnected
Vue.set(this._state.websocket, 'connected', false)
Vue.set(this._state.webrtc, 'connected', false)
Vue.set(this._state, 'status', 'disconnected')
this._state.websocket.connected = false // TODO: Vue.Set
this._state.webrtc.connected = false // TODO: Vue.Set
this._state.status = 'disconnected' // TODO: Vue.Set
}
_webrtcQualityDowngrade(quality: string): string | undefined {

View File

@ -1,11 +1,9 @@
import Vue from 'vue'
import * as EVENT from '../types/events'
import * as message from '../types/messages'
import EventEmitter from 'eventemitter3'
import { NekoConnection } from './connection'
import { Control } from '../types/state'
import type { Control } from '../types/state'
export interface NekoControlEvents {
['overlay.click']: (e: MouseEvent) => void
@ -48,11 +46,11 @@ export class NekoControl extends EventEmitter<NekoControlEvents> {
}
public lock() {
Vue.set(this._state, 'locked', true)
this._state.locked = true // TODO: Vue.Set
}
public unlock() {
Vue.set(this._state, 'locked', false)
this._state.locked = false // TODO: Vue.Set
}
public request() {

View File

@ -1,12 +1,11 @@
import Vue from 'vue'
import * as EVENT from '../types/events'
import * as message from '../types/messages'
import EventEmitter from 'eventemitter3'
import { AxiosProgressEvent } from 'axios'
import type { AxiosProgressEvent } from 'axios'
import { Logger } from '../utils/logger'
import { NekoConnection } from './connection'
import NekoState from '../types/state'
import type NekoState from '../types/state'
export interface NekoEvents {
// connection events
@ -104,11 +103,11 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
protected [EVENT.SYSTEM_INIT](conf: message.SystemInit) {
this._localLog.debug(`EVENT.SYSTEM_INIT`)
Vue.set(this._state, 'session_id', conf.session_id)
this._state.session_id = conf.session_id // TODO: Vue.Set
// check if backend supports touch events
Vue.set(this._state.control.touch, 'supported', conf.touch_events)
Vue.set(this._state.connection, 'screencast', conf.screencast_enabled)
Vue.set(this._state.connection.webrtc, 'videos', conf.webrtc.videos)
this._state.control.touch.supported = conf.touch_events // TODO: Vue.Set
this._state.connection.screencast = conf.screencast_enabled // TODO: Vue.Set
this._state.connection.webrtc.videos = conf.webrtc.videos // TODO: Vue.Set
for (const id in conf.sessions) {
this[EVENT.SESSION_CREATED](conf.sessions[id])
@ -131,14 +130,14 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
return b.width - a.width
})
Vue.set(this._state.screen, 'configurations', list)
this._state.screen.configurations = list // TODO: Vue.Set
this[EVENT.BORADCAST_STATUS](broadcast_status)
}
protected [EVENT.SYSTEM_SETTINGS](settings: message.SystemSettings) {
this._localLog.debug(`EVENT.SYSTEM_SETTINGS`)
Vue.set(this._state, 'settings', settings)
this._state.settings = settings // TODO: Vue.Set
}
protected [EVENT.SYSTEM_DISCONNECT]({ message }: message.SystemDisconnect) {
@ -201,14 +200,14 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
protected [EVENT.SIGNAL_VIDEO]({ disabled, id, auto }: message.SignalVideo) {
this._localLog.debug(`EVENT.SIGNAL_VIDEO`, { disabled, id, auto })
Vue.set(this._state.connection.webrtc.video, 'disabled', disabled)
Vue.set(this._state.connection.webrtc.video, 'id', id)
Vue.set(this._state.connection.webrtc.video, 'auto', auto)
this._state.connection.webrtc.video.disabled = disabled // TODO: Vue.Set
this._state.connection.webrtc.video.id = id // TODO: Vue.Set
this._state.connection.webrtc.video.auto = auto // TODO: Vue.Set
}
protected [EVENT.SIGNAL_AUDIO]({ disabled }: message.SignalAudio) {
this._localLog.debug(`EVENT.SIGNAL_AUDIO`, { disabled })
Vue.set(this._state.connection.webrtc.audio, 'disabled', disabled)
this._state.connection.webrtc.audio.disabled = disabled // TODO: Vue.Set
}
protected [EVENT.SIGNAL_CLOSE]() {
@ -220,22 +219,22 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
// Session Events
/////////////////////////////
protected [EVENT.SESSION_CREATED]({ id, ...data }: message.SessionData) {
protected [EVENT.SESSION_CREATED]({ id, profile, ...state }: message.SessionData) {
this._localLog.debug(`EVENT.SESSION_CREATED`, { id })
Vue.set(this._state.sessions, id, data)
this._state.sessions[id] = { id, profile, state } // TODO: Vue.Set
this.emit('session.created', id)
}
protected [EVENT.SESSION_DELETED]({ id }: message.SessionID) {
this._localLog.debug(`EVENT.SESSION_DELETED`, { id })
Vue.delete(this._state.sessions, id)
delete this._state.sessions[id] // TODO: Vue.Delete
this.emit('session.deleted', id)
}
protected [EVENT.SESSION_PROFILE]({ id, ...profile }: message.MemberProfile) {
if (id in this._state.sessions) {
this._localLog.debug(`EVENT.SESSION_PROFILE`, { id })
Vue.set(this._state.sessions[id], 'profile', profile)
this._state.sessions[id].profile = profile // TODO: Vue.Set
this.emit('session.updated', id)
}
}
@ -243,13 +242,17 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
protected [EVENT.SESSION_STATE]({ id, ...state }: message.SessionState) {
if (id in this._state.sessions) {
this._localLog.debug(`EVENT.SESSION_STATE`, { id })
Vue.set(this._state.sessions[id], 'state', state)
this._state.sessions[id].state = state // TODO: Vue.Set
this.emit('session.updated', id)
}
}
protected [EVENT.SESSION_CURSORS](cursors: message.SessionCursor[]) {
Vue.set(this._state, 'cursors', cursors)
//
// TODO: Resolve conflict with state.cursors.
//
//@ts-ignore
this._state.cursors = cursors // TODO: Vue.Set
}
/////////////////////////////
@ -260,13 +263,13 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
this._localLog.debug(`EVENT.CONTROL_HOST`)
if (has_host && host_id) {
Vue.set(this._state.control, 'host_id', host_id)
this._state.control.host_id = host_id // TODO: Vue.Set
} else {
Vue.set(this._state.control, 'host_id', null)
this._state.control.host_id = null // TODO: Vue.Set
}
// save if user is host
Vue.set(this._state.control, 'is_host', has_host && this._state.control.host_id === this._state.session_id)
this._state.control.is_host = has_host && this._state.control.host_id === this._state.session_id // TODO: Vue.Set
this.emit('room.control.host', has_host, host_id)
}
@ -277,7 +280,7 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
protected [EVENT.SCREEN_UPDATED]({ width, height, rate }: message.ScreenSize) {
this._localLog.debug(`EVENT.SCREEN_UPDATED`)
Vue.set(this._state.screen, 'size', { width, height, rate })
this._state.screen.size = { width, height, rate } // TODO: Vue.Set
this.emit('room.screen.updated', width, height, rate)
}
@ -287,7 +290,7 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
protected [EVENT.CLIPBOARD_UPDATED]({ text }: message.ClipboardData) {
this._localLog.debug(`EVENT.CLIPBOARD_UPDATED`)
Vue.set(this._state.control, 'clipboard', { text })
this._state.control.clipboard = { text } // TODO: Vue.Set
try {
navigator.clipboard.writeText(text) // sync user's clipboard

View File

@ -1,6 +1,6 @@
import EventEmitter from 'eventemitter3'
import { ReconnectorConfig } from '../../types/reconnector'
import type { ReconnectorConfig } from '../../types/reconnector'
export interface ReconnectorAbstractEvents {
connect: () => void

View File

@ -1,5 +1,5 @@
import * as EVENT from '../../types/events'
import { Connection } from '../../types/state'
import type { Connection } from '../../types/state'
import { NekoWebSocket } from '../websocket'
import { NekoWebRTC } from '../webrtc'

View File

@ -1,4 +1,4 @@
import { Connection } from '../../types/state'
import type { Connection } from '../../types/state'
import { NekoWebSocket } from '../websocket'

View File

@ -1,31 +1,30 @@
import Vue from 'vue'
import { Video } from '../types/state'
import type { Video } from '../types/state'
export function register(el: HTMLVideoElement, state: Video) {
el.addEventListener('canplaythrough', () => {
Vue.set(state, 'playable', true)
state.playable = true
})
el.addEventListener('playing', () => {
Vue.set(state, 'playing', true)
state.playing = true
})
el.addEventListener('pause', () => {
Vue.set(state, 'playing', false)
state.playing = false
})
el.addEventListener('emptied', () => {
Vue.set(state, 'playable', false)
Vue.set(state, 'playing', false)
state.playable = false
state.playing = false
})
el.addEventListener('error', () => {
Vue.set(state, 'playable', false)
Vue.set(state, 'playing', false)
state.playable = false
state.playing = false
})
el.addEventListener('volumechange', () => {
Vue.set(state, 'muted', el.muted)
Vue.set(state, 'volume', el.volume)
state.muted = el.muted
state.volume = el.volume
})
// Initial state
Vue.set(state, 'muted', el.muted)
Vue.set(state, 'volume', el.volume)
Vue.set(state, 'playing', !el.paused)
state.muted = el.muted
state.volume = el.volume
state.playing = !el.paused
}

View File

@ -1,5 +1,5 @@
import EventEmitter from 'eventemitter3'
import { WebRTCStats, CursorPosition, CursorImage } from '../types/webrtc'
import type { WebRTCStats, CursorPosition, CursorImage } from '../types/webrtc'
import { Logger } from '../utils/logger'
import { videoSnap } from '../utils/video-snap'

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,98 +2,93 @@
<img :src="imageSrc" @load="onImageLoad" @error="onImageError" />
</template>
<script lang="ts">
import { Vue, Component, Watch, Prop } from 'vue-property-decorator'
import { RoomApi } from './api'
<script lang="ts" setup>
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
import { RoomApi } from './api'
const REFRESH_RATE = 1e3
const ERROR_DELAY_MS = 2500
const REFRESH_RATE = 1e3
const ERROR_DELAY_MS = 2500
@Component({
name: 'neko-screencast',
})
export default class extends Vue {
imageSrc = ''
running = false
continue = false
const imageSrc = ref('')
@Prop()
readonly image!: string
const props = defineProps<{
image: string
enabled: boolean
api: RoomApi
}>()
@Watch('image')
setImage(image: string) {
this.imageSrc = image
}
const emit = defineEmits(['imageReady'])
@Prop()
readonly enabled!: boolean
watch(() => props.image, (image) => {
imageSrc.value = image
})
@Prop()
readonly api!: RoomApi
let isRunning = false
let isStopped = false
async loop() {
if (this.running) return
this.running = true
async function loop() {
if (isRunning) return
isRunning = true
while (this.continue) {
const lastLoad = Date.now()
while (!isStopped) {
const lastLoad = Date.now()
try {
const res = await this.api.screenCastImage({ responseType: 'blob' })
this.imageSrc = URL.createObjectURL(res.data)
try {
const res = await props.api.screenCastImage({ responseType: 'blob' })
imageSrc.value = URL.createObjectURL(res.data)
const delay = lastLoad - Date.now() + REFRESH_RATE
if (delay > 0) {
await new Promise((res) => setTimeout(res, delay))
}
} catch {
await new Promise((res) => setTimeout(res, ERROR_DELAY_MS))
}
const delay = lastLoad - Date.now() + REFRESH_RATE
if (delay > 0) {
await new Promise((res) => setTimeout(res, delay))
}
this.running = false
this.imageSrc = ''
}
mounted() {
if (this.enabled) {
this.start()
}
}
beforeDestroy() {
this.stop()
}
start() {
this.continue = true
if (!this.running) {
setTimeout(this.loop, 0)
}
}
stop() {
this.continue = false
}
@Watch('enabled')
onEnabledChanged(enabled: boolean) {
if (enabled) {
this.start()
} else {
this.stop()
}
}
onImageLoad() {
URL.revokeObjectURL(this.imageSrc)
this.$emit('imageReady', this.running)
}
onImageError() {
if (this.imageSrc) URL.revokeObjectURL(this.imageSrc)
this.$emit('imageReady', false)
} catch {
await new Promise((res) => setTimeout(res, ERROR_DELAY_MS))
}
}
isRunning = false
imageSrc.value = ''
}
onMounted(() => {
if (props.enabled) {
start()
}
})
onBeforeUnmount(() => {
stop()
})
function start() {
isStopped = false
if (!isRunning) {
setTimeout(loop, 0)
}
}
function stop() {
isStopped = true
}
function onEnabledChanged(enabled: boolean) {
if (enabled) {
start()
} else {
stop()
}
}
watch(() => props.enabled, onEnabledChanged)
function onImageLoad() {
URL.revokeObjectURL(imageSrc.value)
emit('imageReady', isRunning)
}
function onImageError() {
if (imageSrc.value) URL.revokeObjectURL(imageSrc.value)
emit('imageReady', false)
}
</script>

View File

@ -1,4 +1,4 @@
import { CursorImage } from './webrtc'
import type { CursorImage } from './webrtc'
export type CursorDrawFunction = (
ctx: CanvasRenderingContext2D,

View File

@ -1,6 +1,6 @@
import { ICEServer } from '../internal/webrtc'
import { Settings } from './state'
import { PeerRequest, PeerVideo, PeerAudio } from './webrtc'
import type { ICEServer } from '../internal/webrtc'
import type { Settings } from './state'
import type { PeerRequest, PeerVideo, PeerAudio } from './webrtc'
/////////////////////////////
// System

View File

@ -1,5 +1,5 @@
import * as webrtcTypes from './webrtc'
import * as reconnectorTypes from './reconnector'
import type * as webrtcTypes from './webrtc'
import type * as reconnectorTypes from './reconnector'
export default interface State {
authenticated: boolean

View File

@ -1,5 +1,7 @@
//@ts-ignore
import Keyboard from './keyboards/__KEYBOARD__'
//
// TODO: add support for other keyboards
//
import Keyboard from './keyboards/guacamole'
// conditional import at build time:
// __KEYBOARD__ is replaced by the value of the env variable KEYBOARD

View File

@ -2,7 +2,7 @@ export class Logger {
// eslint-disable-next-line
constructor(
protected readonly _scope: string = 'main',
private readonly _color: boolean = !!process.env.VUE_APP_LOG_COLOR,
private readonly _color: boolean = false // !!process.env.VUE_APP_LOG_COLOR, // TODO: add support for color
) {}
protected _console(level: string, m: string, fields?: Record<string, any>) {

View File

@ -1,6 +1,11 @@
import Vue from 'vue'
import Neko from './component/main.vue'
// TODO
export * as ApiModels from './component/api/models'
export * as StateModels from './component/types/state'
export * as webrtcTypes from './component/types/webrtc'
/**
* Fügt eine "install" function hinzu
*
@ -9,10 +14,14 @@ import Neko from './component/main.vue'
*/
const NekoElements = {
install(vue: typeof Vue): void {
// TODO
// @ts-ignore
vue.component('Neko', Neko)
},
}
// TODO
// @ts-ignore
if (typeof window !== 'undefined' && window.Vue) {
// @ts-ignore
window.Vue.use(NekoElements, {})

View File

@ -1,8 +1,6 @@
import Vue from 'vue'
import app from './page/main.vue'
import { createApp } from 'vue'
import App from './page/main.vue'
Vue.config.productionTip = false
const app = createApp(App)
new Vue({
render: (h) => h(app),
}).$mount('#app')
app.mount('#app')

View File

@ -2,7 +2,7 @@
@use "sass:math";
$fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
$fa-font-path: "@fortawesome/fontawesome-free/webfonts";
$fa-font-size-base: 16px;
$fa-font-display: auto;
$fa-css-prefix: fa;
@ -16,7 +16,7 @@ $fa-secondary-opacity: .4;
$fa-family-default: 'Font Awesome 6 Free';
// Import FA source files
@import "~@fortawesome/fontawesome-free/scss/brands";
@import "~@fortawesome/fontawesome-free/scss/solid";
@import "~@fortawesome/fontawesome-free/scss/regular";
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
@import "@fortawesome/fontawesome-free/scss/brands";
@import "@fortawesome/fontawesome-free/scss/solid";
@import "@fortawesome/fontawesome-free/scss/regular";
@import "@fortawesome/fontawesome-free/scss/fontawesome";

View File

@ -0,0 +1,11 @@
// import { describe, it, expect } from 'vitest'
//
// import { mount } from '@vue/test-utils'
// import HelloWorld from '../HelloWorld.vue'
//
// describe('HelloWorld', () => {
// it('renders properly', () => {
// const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
// expect(wrapper.text()).toContain('Hello Vitest')
// })
// })

View File

@ -1,8 +1,8 @@
<template>
<div class="chat">
<ul class="chat-history" ref="history">
<template v-for="(message, index) in history">
<li :key="index" class="message" v-show="neko && neko.connected">
<template v-for="(message, index) in messages" :key="index">
<li class="message" v-show="neko && neko.connected">
<div class="content">
<div class="content-head">
<span class="session">{{ session(message.id) }}</span>
@ -162,105 +162,114 @@
}
</style>
<script lang="ts">
import { Vue, Component, Prop, Watch, Ref } from 'vue-property-decorator'
import Neko from '~/component/main.vue'
<script lang="ts" setup>
import { ref, watch, onMounted } from 'vue'
import Neko from '@/component/main.vue'
const length = 512 // max length of message
const length = 512 // max length of message
@Component({
name: 'neko-chat',
const history = ref<HTMLUListElement | null>(null)
const props = defineProps<{
neko: typeof Neko
}>()
const emit = defineEmits(['send_message'])
type Message = {
id: string
created: Date
content: string
}
const messages = ref<Message[]>([])
const content = ref('')
onMounted(() => {
setTimeout(() => {
history.value!.scrollTop = history.value!.scrollHeight
}, 0)
})
function timestamp(date: Date | string) {
date = new Date(date)
return (
date.getFullYear() +
'-' +
String(date.getMonth() + 1).padStart(2, '0') +
'-' +
String(date.getDate()).padStart(2, '0') +
' ' +
String(date.getHours()).padStart(2, '0') +
':' +
String(date.getMinutes()).padStart(2, '0') +
':' +
String(date.getSeconds()).padStart(2, '0')
)
}
function session(id: string) {
let session = props.neko.state.sessions[id]
return session ? session.profile.name : id
}
function onNekoChange() {
props.neko.events.on('receive.broadcast', (sender: string, subject: string, body: any) => {
if (subject === 'chat') {
const message = body as Message
messages.value = [...messages.value, message]
}
})
export default class extends Vue {
@Ref('history') readonly _history!: HTMLElement
@Prop() readonly neko!: Neko
}
history = []
content = ''
watch(() => props.neko, onNekoChange)
mounted() {
this.$nextTick(() => {
this._history.scrollTop = this._history.scrollHeight
})
}
function onHistroyChange() {
setTimeout(() => {
history.value!.scrollTop = history.value!.scrollHeight
}, 0)
}
timestamp(date: Date | string) {
date = new Date(date)
watch(messages, onHistroyChange)
return (
date.getFullYear() +
'-' +
String(date.getMonth() + 1).padStart(2, '0') +
'-' +
String(date.getDate()).padStart(2, '0') +
' ' +
String(date.getHours()).padStart(2, '0') +
':' +
String(date.getMinutes()).padStart(2, '0') +
':' +
String(date.getSeconds()).padStart(2, '0')
)
}
session(id: string) {
let session = this.neko.state.sessions[id]
return session ? session.profile.name : id
}
@Watch('neko')
onNekoChange() {
this.neko.events.on('receive.broadcast', (sender: string, subject: string, body: string) => {
if (subject === 'chat') {
Vue.set(this, 'history', [...this.history, body])
}
})
}
@Watch('history')
onHistroyChange() {
this.$nextTick(() => {
this._history.scrollTop = this._history.scrollHeight
})
}
onKeyDown(event: KeyboardEvent) {
if (this.content.length > length) {
this.content = this.content.substring(0, length)
}
if (this.content.length == length) {
if (
[8, 16, 17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 91, 93, 144].includes(event.keyCode) ||
(event.ctrlKey && [67, 65, 88].includes(event.keyCode))
) {
return
}
event.preventDefault()
return
}
if (event.keyCode !== 13 || event.shiftKey) {
return
}
if (this.content === '') {
event.preventDefault()
return
}
this.$emit('send_message', this.content)
let message = {
id: this.neko.state.session_id,
created: new Date(),
content: this.content,
}
this.neko.sendBroadcast('chat', message)
Vue.set(this, 'history', [...this.history, message])
this.content = ''
event.preventDefault()
}
function onKeyDown(event: KeyboardEvent) {
if (content.value.length > length) {
content.value = content.value.substring(0, length)
}
if (content.value.length == length) {
if (
[8, 16, 17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 91, 93, 144].includes(event.keyCode) ||
(event.ctrlKey && [67, 65, 88].includes(event.keyCode))
) {
return
}
event.preventDefault()
return
}
if (event.keyCode !== 13 || event.shiftKey) {
return
}
if (content.value === '') {
event.preventDefault()
return
}
emit('send_message', content.value)
let message = {
id: props.neko.state.session_id,
created: new Date(),
content: content.value,
}
props.neko.sendBroadcast('chat', message)
messages.value = [...messages.value, message]
content.value = ''
event.preventDefault()
}
</script>

View File

@ -35,185 +35,182 @@
}
</style>
<script lang="ts">
import { Vue, Component, Ref, Watch } from 'vue-property-decorator'
<script lang="ts" setup>
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
@Component({
name: 'neko-color',
})
export default class extends Vue {
@Ref('canvas') readonly _canvas!: HTMLCanvasElement
@Ref('color') readonly _color!: HTMLDivElement
const canvas = ref<HTMLCanvasElement | null>(null)
const color = ref<HTMLDivElement | null>(null)
ctx!: CanvasRenderingContext2D | null
video!: HTMLVideoElement | null
interval!: number
picker!: HTMLDivElement | null
bullet!: HTMLDivElement | null
color!: string
const ctx = ref<CanvasRenderingContext2D | null>(null)
const video = ref<HTMLVideoElement | null>(null)
const interval = ref<number>(0)
const picker = ref<HTMLDivElement | null>(null)
const bullet = ref<HTMLDivElement | null>(null)
const currColor = ref<string>('')
x = 0
y = 0
clickOnChange = false
const x = ref<number>(0)
const y = ref<number>(0)
const clickOnChange = ref<boolean>(false)
mounted() {
this.video = document.querySelector('video')
this.ctx = this._canvas.getContext('2d')
}
const emit = defineEmits(['colorChange'])
beforeDestroy() {
if (this.interval) {
window.clearInterval(this.interval)
}
onMounted(() => {
video.value = document.querySelector('video')
ctx.value = canvas.value?.getContext('2d') || null
})
this.clearPoint()
}
@Watch('clickOnChange')
clickOnChangeChanged() {
if (this.clickOnChange) {
// register interval timer
this.interval = window.setInterval(this.intervalTimer, 0)
} else {
// unregister interval timer
window.clearInterval(this.interval)
this.color = ''
}
}
intervalTimer() {
if (!this.video || !this.ctx) {
return
}
this._canvas.width = this.video.videoWidth
this._canvas.height = this.video.videoHeight
this.ctx.clearRect(0, 0, this.video.videoWidth, this.video.videoHeight)
this.ctx.drawImage(this.video, 0, 0, this.video.videoWidth, this.video.videoHeight)
// get color from pixel at x,y
var pixel = this.ctx.getImageData(this.x, this.y, 1, 1)
var data = pixel.data
var rgba = 'rgba(' + data[0] + ', ' + data[1] + ', ' + data[2] + ', ' + data[3] / 255 + ')'
// if color is different, update it
if (this.color != rgba) {
if (this.clickOnChange && this.color) {
this.$emit('colorChange', { x: this.x, y: this.y })
this.clickOnChange = false
}
console.log('color change', rgba, this.color)
this._color.style.backgroundColor = rgba
this.color = rgba
}
}
getCoords(elem: HTMLElement) {
// crossbrowser version
let box = elem.getBoundingClientRect()
let body = document.body
let docEl = document.documentElement
let scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop
let scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft
let clientTop = docEl.clientTop || body.clientTop || 0
let clientLeft = docEl.clientLeft || body.clientLeft || 0
let top = box.top + scrollTop - clientTop
let left = box.left + scrollLeft - clientLeft
return { top: Math.round(top), left: Math.round(left) }
}
setPoint() {
// create new element and add to body
var picker = document.createElement('div')
// coordinates of video element
var video = this.getCoords(this.video!)
// match that dimensions and offset matches video
picker.style.width = this.video!.offsetWidth + 'px'
picker.style.height = this.video!.offsetHeight + 'px'
picker.style.left = video.left + 'px'
picker.style.top = video.top + 'px'
picker.style.position = 'absolute'
picker.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
picker.style.cursor = 'crosshair'
// put it on top of video
picker.style.zIndex = '100'
document.body.appendChild(picker)
// add click event listener to new element
picker.addEventListener('click', this.clickPicker)
this.picker = picker
}
clearPoint() {
this.x = 0
this.y = 0
this.color = ''
this._color.style.backgroundColor = 'transparent'
if (this.bullet) {
this.bullet.remove()
}
if (this.picker) {
this.picker.remove()
}
}
clickPicker(e: any) {
// get mouse position
var x = e.pageX
var y = e.pageY
// get picker position
var picker = this.getCoords(this.picker!)
// calculate new x,y position
var newX = x - picker.left
var newY = y - picker.top
// make it relative to video size
newX = Math.round((newX / this.video!.offsetWidth) * this.video!.videoWidth)
newY = Math.round((newY / this.video!.offsetHeight) * this.video!.videoHeight)
console.log(newX, newY)
// set new x,y position
this.x = newX
this.y = newY
// remove picker element
this.picker!.remove()
// add bullet element to the position
if (this.bullet) {
this.bullet.remove()
}
var bullet = document.createElement('div')
bullet.style.left = x + 'px'
bullet.style.top = y + 'px'
// width and height of bullet
bullet.style.width = '10px'
bullet.style.height = '10px'
// background color of bullet
bullet.style.backgroundColor = 'red'
// border radius of bullet
bullet.style.borderRadius = '50%'
// transform bullet to center
bullet.style.transform = 'translate(-50%, -50%)'
bullet.style.position = 'absolute'
bullet.style.zIndex = '100'
document.body.appendChild(bullet)
this.bullet = bullet
}
onBeforeUnmount(() => {
if (interval.value) {
window.clearInterval(interval.value)
}
clearPoint()
})
function clickOnChangeChanged() {
if (clickOnChange.value) {
// register interval timer
interval.value = window.setInterval(intervalTimer, 0)
} else {
// unregister interval timer
window.clearInterval(interval.value)
currColor.value = ''
}
}
watch(clickOnChange, clickOnChangeChanged)
function intervalTimer() {
if (!video.value || !ctx.value) {
return
}
canvas.value!.width = video.value.videoWidth
canvas.value!.height = video.value.videoHeight
ctx.value.clearRect(0, 0, video.value.videoWidth, video.value.videoHeight)
ctx.value.drawImage(video.value, 0, 0, video.value.videoWidth, video.value.videoHeight)
// get color from pixel at x,y
const pixel = ctx.value.getImageData(x.value, y.value, 1, 1)
const data = pixel.data
const rgba = `rgba(${data[0]}, ${data[1]}, ${data[2]}, ${data[3] / 255})`
// if color is different, update it
if (currColor.value !== rgba) {
if (clickOnChange.value && currColor.value) {
emit('colorChange', { x: x.value, y: y.value })
clickOnChange.value = false
}
console.log('color change', rgba, currColor.value)
color.value!.style.backgroundColor = rgba
currColor.value = rgba
}
}
function getCoords(elem: HTMLElement) {
// crossbrowser version
const box = elem.getBoundingClientRect()
const body = document.body
const docEl = document.documentElement
const scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop
const scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft
const clientTop = docEl.clientTop || body.clientTop || 0
const clientLeft = docEl.clientLeft || body.clientLeft || 0
const top = box.top + scrollTop - clientTop
const left = box.left + scrollLeft - clientLeft
return { top: Math.round(top), left: Math.round(left) }
}
function setPoint() {
// create new element and add to body
const p = document.createElement('div')
// coordinates of video element
const v = getCoords(video.value!)
// match that dimensions and offset matches video
p.style.width = video.value!.offsetWidth + 'px'
p.style.height = video.value!.offsetHeight + 'px'
p.style.left = v.left + 'px'
p.style.top = v.top + 'px'
p.style.position = 'absolute'
p.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
p.style.cursor = 'crosshair'
// put it on top of video
p.style.zIndex = '100'
document.body.appendChild(p)
// add click event listener to new element
p.addEventListener('click', clickPicker)
picker.value = p
}
function clearPoint() {
x.value = 0
y.value = 0
color.value!.style.backgroundColor = 'transparent'
if (bullet.value) {
bullet.value.remove()
}
if (picker.value) {
picker.value.remove()
}
}
function clickPicker(e: any) {
// get mouse position
const x = e.pageX
const y = e.pageY
// get picker position
const p = getCoords(picker.value!)
// calculate new x,y position
let newX = x - p.left
let newY = y - p.top
// make it relative to video size
newX = Math.round((newX / video.value!.offsetWidth) * video.value!.videoWidth)
newY = Math.round((newY / video.value!.offsetHeight) * video.value!.videoHeight)
console.log(newX, newY)
// set new x,y position
x.value = newX
y.value = newY
// remove picker element
picker.value!.remove()
// add bullet element to the position
if (bullet.value) {
bullet.value.remove()
}
const b = document.createElement('div')
b.style.left = x + 'px'
b.style.top = y + 'px'
// width and height of bullet
b.style.width = '10px'
b.style.height = '10px'
// background color of bullet
b.style.backgroundColor = 'red'
// border radius of bullet
b.style.borderRadius = '50%'
// transform bullet to center
b.style.transform = 'translate(-50%, -50%)'
b.style.position = 'absolute'
b.style.zIndex = '100'
document.body.appendChild(b)
bullet.value = b
}
</script>

View File

@ -24,56 +24,53 @@
<style lang="scss"></style>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import Neko from '~/component/main.vue'
<script lang="ts" setup>
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
import Neko from '@/component/main.vue'
@Component({
name: 'neko-controls',
})
export default class extends Vue {
@Prop() readonly neko!: Neko
const props = defineProps<{
neko: typeof Neko
}>()
username: string = 'admin'
password: string = 'admin'
const username = ref('admin')
const password = ref('admin')
async login() {
localStorage.setItem('username', this.username)
localStorage.setItem('password', this.password)
async function login() {
localStorage.setItem('username', username.value)
localStorage.setItem('password', password.value)
try {
await this.neko.login(this.username, this.password)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async connect() {
try {
await this.neko.connect()
} catch (e: any) {
alert(e)
}
}
async logout() {
try {
await this.neko.logout()
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
mounted() {
const username = localStorage.getItem('username')
if (username) {
this.username = username
}
const password = localStorage.getItem('password')
if (password) {
this.password = password
}
}
try {
await props.neko.login(username.value, password.value)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async function connect() {
try {
await props.neko.connect()
} catch (e: any) {
alert(e)
}
}
async function logout() {
try {
await props.neko.logout()
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
onMounted(() => {
const u = localStorage.getItem('username')
if (u) {
username.value = u
}
const p = localStorage.getItem('password')
if (p) {
password.value = p
}
})
</script>

View File

@ -67,7 +67,6 @@
background: transparent;
width: 150px;
height: 20px;
-webkit-appearance: none;
&::-moz-range-thumb {
height: 12px;
width: 12px;
@ -160,88 +159,67 @@
}
</style>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import Neko from '~/component/main.vue'
<script lang="ts" setup>
import { ref, watch, computed, onMounted, onBeforeUnmount } from 'vue'
import Neko from '@/component/main.vue'
@Component({
name: 'neko-controls',
})
export default class extends Vue {
@Prop() readonly neko!: Neko
const props = defineProps<{
neko: typeof Neko
}>()
get can_host() {
return this.neko.connected
const can_host = computed(() => props.neko.connected)
const hosting = computed(() => props.neko.controlling)
const volume = computed({
get: () => props.neko.state.video.volume * 100,
set: (volume: number) => {
props.neko.setVolume(volume / 100)
},
})
const muted = computed(() => props.neko.state.video.muted || props.neko.state.video.volume === 0)
const playing = computed(() => props.neko.state.video.playing)
const playable = computed(() => props.neko.state.video.playable)
const locked = computed({
get: () => props.neko.state.control.locked,
set: (lock: boolean) => {
if (lock) {
props.neko.control.lock()
} else {
props.neko.control.unlock()
}
},
})
get hosting() {
return this.neko.controlling
}
get volume() {
return this.neko.state.video.volume * 100
}
set volume(volume: number) {
this.neko.setVolume(volume / 100)
}
get muted() {
return this.neko.state.video.muted || this.neko.state.video.volume === 0
}
get playing() {
return this.neko.state.video.playing
}
get playable() {
return this.neko.state.video.playable
}
get locked() {
return this.neko.state.control.locked
}
set locked(lock: boolean) {
if (lock) {
this.neko.control.lock()
} else {
this.neko.control.unlock()
}
}
toggleControl() {
if (this.can_host && this.hosting) {
this.neko.room.controlRelease()
}
if (this.can_host && !this.hosting) {
this.neko.room.controlRequest()
}
}
toggleMedia() {
if (this.playable && this.playing) {
this.neko.pause()
}
if (this.playable && !this.playing) {
this.neko.play()
}
}
toggleMute() {
if (this.playable && this.muted) {
this.neko.unmute()
}
if (this.playable && !this.muted) {
this.neko.mute()
}
}
disconnect() {
this.neko.logout()
}
function toggleControl() {
if (can_host.value && hosting.value) {
props.neko.room.controlRelease()
}
if (can_host.value && !hosting.value) {
props.neko.room.controlRequest()
}
}
function toggleMedia() {
if (playable.value && playing.value) {
props.neko.video.pause()
}
if (playable.value && !playing.value) {
props.neko.video.play()
}
}
function toggleMute() {
if (playable.value && muted.value) {
props.neko.video.unmute()
}
if (playable.value && !muted.value) {
props.neko.video.mute()
}
}
function disconnect() {
props.neko.logout()
}
</script>

View File

@ -209,7 +209,7 @@
<td>
<select
:value="neko.state.connection.webrtc.video.id"
@input="neko.setWebRTCVideo({ selector: { id: $event.target.value } })"
@input="neko.setWebRTCVideo({ selector: { id: ($event.target as HTMLSelectElement)!.value || '' } })"
>
<option v-for="video in neko.state.connection.webrtc.videos" :key="video" :value="video">
{{ video }}
@ -252,7 +252,7 @@
min="0"
max="1"
:value="neko.state.video.volume"
@input="neko.setVolume(Number($event.target.value))"
@input="neko.setVolume(Number(($event.target as HTMLInputElement)!.value))"
step="0.01"
/>
</td>
@ -289,7 +289,7 @@
min="-5"
max="5"
:value="neko.state.control.scroll.sensitivity"
@input="neko.setScrollSensitivity(Number($event.target.value))"
@input="neko.setScrollSensitivity(Number(($event.target as HTMLInputElement)!.value))"
step="1"
/>
</td>
@ -300,7 +300,7 @@
<textarea
:readonly="!neko.controlling"
:value="neko.state.control.clipboard ? neko.state.control.clipboard.text : ''"
@input="clipboardText = $event.target.value"
@input="clipboardText = ($event.target as HTMLTextAreaElement)!.value"
></textarea>
<button :disabled="!neko.controlling" @click="neko.room.clipboardSetText({ text: clipboardText })">
send clipboard
@ -322,14 +322,14 @@
type="text"
placeholder="Layout"
:value="neko.state.control.keyboard.layout"
@input="neko.setKeyboard($event.target.value, neko.state.control.keyboard.variant)"
@input="neko.setKeyboard(($event.target as HTMLInputElement)!.value, neko.state.control.keyboard.variant)"
style="width: 50%; box-sizing: border-box"
/>
<input
type="text"
placeholder="Variant"
:value="neko.state.control.keyboard.variant"
@input="neko.setKeyboard(neko.state.control.keyboard.layout, $event.target.value)"
@input="neko.setKeyboard(neko.state.control.keyboard.layout, ($event.target as HTMLInputElement)!.value)"
style="width: 50%; box-sizing: border-box"
/>
</td>
@ -409,7 +409,7 @@
min="0"
max="10"
:value="neko.state.screen.sync.multiplier"
@input="neko.state.screen.sync.multiplier = Number($event.target.value)"
@input="neko.state.screen.sync.multiplier = Number(($event.target as HTMLInputElement)!.value)"
step="0.1"
/>
</td>
@ -425,7 +425,7 @@
min="5"
max="60"
:value="neko.state.screen.sync.rate"
@input="neko.state.screen.sync.rate = Number($event.target.value)"
@input="neko.state.screen.sync.rate = Number(($event.target as HTMLInputElement)!.value)"
step="5"
/>
</td>
@ -597,94 +597,82 @@
}
</style>
<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import Neko from '~/component/main.vue'
import NekoColor from './color.vue'
<script lang="ts" setup>
import { ref, watch, computed, onMounted, onBeforeUnmount } from 'vue'
import Neko from '@/component/main.vue'
import NekoColor from './color.vue'
@Component({
name: 'neko-events',
components: {
NekoColor,
},
})
export default class extends Vue {
@Prop() readonly neko!: Neko
const props = defineProps<{
neko: typeof Neko
}>()
clipboardText: string = ''
bitrate: number | null = null
const clipboardText = ref('')
const bitrate = ref<number | null>(null)
@Watch('neko.state.connection.webrtc.bitrate')
onBitrateChange(val: number) {
this.bitrate = val
}
watch(() => props.neko.state.connection.webrtc.bitrate, (val) => {
bitrate.value = val
})
shift = false
get letters(): number[] {
let letters = [] as number[]
for (let i = (this.shift ? 'A' : 'a').charCodeAt(0); i <= (this.shift ? 'Z' : 'z').charCodeAt(0); i++) {
letters.push(i)
}
return letters
}
// fast sceen changing test
screen_interval = null
screenChangingToggle() {
if (this.screen_interval === null) {
let sizes = this.neko.state.screen.configurations
let len = sizes.length
//@ts-ignore
this.screen_interval = setInterval(() => {
let { width, height, rate } = sizes[Math.floor(Math.random() * len)]
this.neko.setScreenSize(width, height, rate)
}, 10)
} else {
//@ts-ignore
clearInterval(this.screen_interval)
this.screen_interval = null
}
}
screenConfiguration = ''
setScreenConfiguration() {
let [width, height, rate] = this.screenConfiguration.split(/[@x]/)
this.neko.setScreenSize(parseInt(width), parseInt(height), parseInt(rate))
}
@Watch('neko.state.screen.size', { immediate: true })
onScreenSizeChange(val: any) {
this.screenConfiguration = `${val.width}x${val.height}@${val.rate}`
}
// fast cursor moving test
cursor_interval = null
cursorMovingToggle() {
if (this.cursor_interval === null) {
let len = this.neko.state.screen.size.width
//@ts-ignore
this.cursor_interval = setInterval(() => {
let x = Math.floor(Math.random() * len)
let y = Math.floor(Math.random() * len)
this.neko.control.move({ x, y })
}, 10)
} else {
//@ts-ignore
clearInterval(this.cursor_interval)
this.cursor_interval = null
}
}
async updateSettings(settings: any) {
try {
await this.neko.room.settingsSet(settings)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
const shift = ref(false)
const letters = computed(() => {
let letters = [] as number[]
for (let i = (shift.value ? 'A' : 'a').charCodeAt(0); i <= (shift.value ? 'Z' : 'z').charCodeAt(0); i++) {
letters.push(i)
}
return letters
})
// fast sceen changing test
let screen_interval: number | null = null
function screenChangingToggle() {
if (screen_interval === null) {
let sizes = props.neko.state.screen.configurations
let len = sizes.length
screen_interval = setInterval(() => {
let { width, height, rate } = sizes[Math.floor(Math.random() * len)]
props.neko.setScreenSize(width, height, rate)
}, 10)
} else {
clearInterval(screen_interval)
screen_interval = null
}
}
const screenConfiguration = ref('')
function setScreenConfiguration() {
let [width, height, rate] = screenConfiguration.value.split(/[@x]/)
props.neko.setScreenSize(parseInt(width), parseInt(height), parseInt(rate))
}
watch(props.neko.state.screen.size, (val) => {
screenConfiguration.value = `${val.width}x${val.height}@${val.rate}`
})
// fast cursor moving test
let cursor_interval: number | null = null
function cursorMovingToggle() {
if (cursor_interval === null) {
let len = props.neko.state.screen.size.width
cursor_interval = setInterval(() => {
let x = Math.floor(Math.random() * len)
let y = Math.floor(Math.random() * len)
props.neko.control.move({ x, y })
}, 10)
} else {
clearInterval(cursor_interval)
cursor_interval = null
}
}
async function updateSettings(settings: any) {
try {
await props.neko.room.settingsSet(settings)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
</script>

View File

@ -84,34 +84,29 @@
}
</style>
<script lang="ts">
import { Component, Prop, Watch, Vue } from 'vue-property-decorator'
import Neko from '~/component/main.vue'
<script lang="ts" setup>
import { ref, watch, computed, onMounted, onBeforeUnmount } from 'vue'
import Neko from '@/component/main.vue'
@Component({
name: 'neko-header',
})
export default class extends Vue {
@Prop() readonly neko!: Neko
const props = defineProps<{
neko: typeof Neko
}>()
@Watch('neko.state.connection.url')
updateUrl(url: string) {
this.url = url
}
const url = ref('')
url: string = ''
watch(() => props.neko.state.connection.url, (u) => {
url.value = u
})
async setUrl() {
if (this.url == '') {
this.url = location.href
}
await this.neko.setUrl(this.url)
}
toggleMenu() {
this.$emit('toggle')
//this.$accessor.client.toggleSide()
}
async function setUrl() {
if (url.value == '') {
url.value = location.href
}
await props.neko.setUrl(url.value)
}
function toggleMenu() {
props.neko.toggleSide()
}
</script>

View File

@ -40,146 +40,144 @@
<style lang="scss" scoped></style>
<script lang="ts">
import { Vue, Component, Prop, Ref } from 'vue-property-decorator'
import Neko from '~/component/main.vue'
<script lang="ts" setup>
import { ref, watch, computed, onMounted, onBeforeUnmount } from 'vue'
import Neko from '@/component/main.vue'
@Component({
name: 'neko-media',
})
export default class extends Vue {
@Prop() readonly neko!: Neko
@Ref('audio') readonly _audio!: HTMLAudioElement
@Ref('video') readonly _video!: HTMLVideoElement
const props = defineProps<{
neko: typeof Neko
}>()
private audioDevice: string = ''
private audioDevices: MediaDeviceInfo[] = []
const audio = ref<HTMLAudioElement | null>(null)
const video = ref<HTMLVideoElement | null>(null)
private micTracks: MediaStreamTrack[] = []
private micSenders: RTCRtpSender[] = []
const audioDevice = ref<string>('')
const audioDevices = ref<MediaDeviceInfo[]>([])
private videoDevice: string = ''
private videoDevices: MediaDeviceInfo[] = []
const micTracks = ref<MediaStreamTrack[]>([])
const micSenders = ref<RTCRtpSender[]>([])
private camTracks: MediaStreamTrack[] = []
private camSenders: RTCRtpSender[] = []
const videoDevice = ref<string>('')
const videoDevices = ref<MediaDeviceInfo[]>([])
mounted() {
this.loadAudioDevices()
this.loadVideoDevices()
const camTracks = ref<MediaStreamTrack[]>([])
const camSenders = ref<RTCRtpSender[]>([])
onMounted(() => {
loadAudioDevices()
loadVideoDevices()
})
async function loadAudioDevices() {
let devices = await navigator.mediaDevices.enumerateDevices()
audioDevices.value = devices.filter((device) => device.kind === 'audioinput')
console.log('audioDevices', audioDevices.value)
}
async function addMicrophone() {
micTracks.value = []
micSenders.value = []
try {
let a = { echoCancellation: true } as MediaTrackConstraints
if (audioDevice.value != '') {
a.deviceId = audioDevice.value
}
async loadAudioDevices() {
let devices = await navigator.mediaDevices.enumerateDevices()
this.audioDevices = devices.filter((device) => device.kind === 'audioinput')
console.log('audioDevices', this.audioDevices)
}
const stream = await navigator.mediaDevices.getUserMedia({ video: false, audio: a })
audio.value!.srcObject = stream
console.log('Got MediaStream:', stream)
async addMicrophone() {
this.micTracks = []
this.micSenders = []
const tracks = stream.getTracks()
console.log('Got tracks:', tracks)
try {
let audio = { echoCancellation: true } as MediaTrackConstraints
if (this.audioDevice != '') {
audio.deviceId = this.audioDevice
}
tracks.forEach((track) => {
micTracks.value.push(track)
console.log('Adding track', track, stream)
const stream = await navigator.mediaDevices.getUserMedia({ video: false, audio })
this._audio.srcObject = stream
console.log('Got MediaStream:', stream)
const rtcp = props.neko.addTrack(track, stream)
micSenders.value.push(rtcp)
console.log('rtcp sender', rtcp, rtcp.transport)
const tracks = stream.getTracks()
console.log('Got tracks:', tracks)
tracks.forEach((track) => {
this.micTracks.push(track)
console.log('Adding track', track, stream)
const rtcp = this.neko.addTrack(track, stream)
this.micSenders.push(rtcp)
console.log('rtcp sender', rtcp, rtcp.transport)
// TODO: Can be null.
rtcp.transport?.addEventListener('statechange', () => {
console.log('track - on state change', rtcp.transport?.state)
})
})
} catch (error) {
alert('Error accessing media devices.' + error)
}
}
stopMicrophone() {
this.micTracks.forEach((track) => {
track.stop()
// TODO: Can be null.
rtcp.transport?.addEventListener('statechange', () => {
console.log('track - on state change', rtcp.transport?.state)
})
this.micSenders.forEach((rtcp) => {
this.neko.removeTrack(rtcp)
})
this._audio.srcObject = null
this.micTracks = []
this.micSenders = []
}
async loadVideoDevices() {
let devices = await navigator.mediaDevices.enumerateDevices()
this.videoDevices = devices.filter((device) => device.kind === 'videoinput')
console.log('videoDevices', this.videoDevices)
}
async addWebcam() {
this.camTracks = []
this.camSenders = []
try {
let video = {
width: 1280,
height: 720,
} as MediaTrackConstraints
if (this.videoDevice != '') {
video.deviceId = this.videoDevice
}
const stream = await navigator.mediaDevices.getUserMedia({ video, audio: false })
this._video.srcObject = stream
console.log('Got MediaStream:', stream)
const tracks = stream.getTracks()
console.log('Got tracks:', tracks)
tracks.forEach((track) => {
this.camTracks.push(track)
console.log('Adding track', track, stream)
const rtcp = this.neko.addTrack(track, stream)
this.camSenders.push(rtcp)
console.log('rtcp sender', rtcp, rtcp.transport)
// TODO: Can be null.
rtcp.transport?.addEventListener('statechange', () => {
console.log('track - on state change', rtcp.transport?.state)
})
})
} catch (error) {
alert('Error accessing media devices.' + error)
}
}
stopWebcam() {
this.camTracks.forEach((track) => {
track.stop()
})
this.camSenders.forEach((rtcp) => {
this.neko.removeTrack(rtcp)
})
this._audio.srcObject = null
this.camTracks = []
this.camSenders = []
}
})
} catch (error) {
alert('Error accessing media devices.' + error)
}
}
function stopMicrophone() {
micTracks.value.forEach((track) => {
track.stop()
})
micSenders.value.forEach((rtcp) => {
props.neko.removeTrack(rtcp)
})
audio.value!.srcObject = null
micTracks.value = []
micSenders.value = []
}
async function loadVideoDevices() {
let devices = await navigator.mediaDevices.enumerateDevices()
videoDevices.value = devices.filter((device) => device.kind === 'videoinput')
console.log('videoDevices', videoDevices.value)
}
async function addWebcam() {
camTracks.value = []
camSenders.value = []
try {
let v = {
width: 1280,
height: 720,
} as MediaTrackConstraints
if (videoDevice.value != '') {
v.deviceId = videoDevice.value
}
const stream = await navigator.mediaDevices.getUserMedia({ video: v, audio: false })
video.value!.srcObject = stream
console.log('Got MediaStream:', stream)
const tracks = stream.getTracks()
console.log('Got tracks:', tracks)
tracks.forEach((track) => {
camTracks.value.push(track)
console.log('Adding track', track, stream)
const rtcp = props.neko.addTrack(track, stream)
camSenders.value.push(rtcp)
console.log('rtcp sender', rtcp, rtcp.transport)
// TODO: Can be null.
rtcp.transport?.addEventListener('statechange', () => {
console.log('track - on state change', rtcp.transport?.state)
})
})
} catch (error) {
alert('Error accessing media devices.' + error)
}
}
function stopWebcam() {
camTracks.value.forEach((track) => {
track.stop()
})
camSenders.value.forEach((rtcp) => {
props.neko.removeTrack(rtcp)
})
video.value!.srcObject = null
camTracks.value = []
camSenders.value = []
}
</script>

View File

@ -14,7 +14,7 @@
</tr>
<tr>
<td colspan="2" style="text-align: center">
<button @click="$set(plugins, 'new', [...plugins.new, ['', '']])">+</button>
<button @click="plugins.new = [...plugins.new, ['', '']]">+</button>
</td>
</tr>
<tr>
@ -114,7 +114,7 @@
'state-is':
session.profile.sends_inactive_cursor &&
neko.state.settings.inactive_cursors &&
neko.state.cursors.some((e) => e.id == id),
neko.state.cursors.some((e:any) => e.id == id),
'state-disabled': !session.profile.can_login || !session.profile.can_connect,
}"
@click="
@ -141,7 +141,7 @@
<p class="title">
<span>Members</span>
<button @click="membersLoad">reload</button>
<button @click="membersLoad()">reload</button>
</p>
<div
@ -152,7 +152,7 @@
v-for="member in membersWithoutSessions"
:key="'member-' + member.id"
>
<div class="topbar">
<div class="topbar" v-if="member.profile && member.id">
<div class="name">
<i v-if="neko.is_admin" class="fa fa-trash-alt" @click="memberRemove(member.id)" title="remove" />
{{ member.profile.name }}
@ -406,168 +406,160 @@
}
</style>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import Neko, { ApiModels, StateModels } from '~/component/main.vue'
<script lang="ts" setup>
import { ref, watch, computed, onMounted, onBeforeUnmount } from 'vue'
import Neko from '@/component/main.vue'
@Component({
name: 'neko-members',
})
export default class extends Vue {
@Prop() readonly neko!: Neko
// TODO: get from lib ts?
import type * as ApiModels from '@/component/api/models'
import type * as StateModels from '@/component/types/state'
constructor() {
super()
const props = defineProps<{
neko: typeof Neko
}>()
// init
this.newProfile = Object.assign({}, this.defProfile)
const sessions = computed(() => props.neko.state.sessions as Record<string, StateModels.Session>)
const membersWithoutSessions = computed(() => {
return props.neko.state.members.filter(({ id }: { id: string }) => id && !(id in sessions.value)) as ApiModels.MemberData[]
})
const members = ref<ApiModels.MemberData[]>([])
const plugins = ref<{
id: string
old: Array<Array<string>>
new: Array<Array<string>>
profile: ApiModels.MemberProfile
} | null>(null)
const newUsername = ref('')
const newPassword = ref('')
const newProfile = ref<ApiModels.MemberProfile>({})
const defProfile = ref<ApiModels.MemberProfile>({
name: '',
is_admin: false,
can_login: true,
can_connect: true,
can_watch: true,
can_host: true,
can_share_media: true,
can_access_clipboard: true,
sends_inactive_cursor: true,
can_see_inactive_cursors: true,
})
newProfile.value = Object.assign({}, defProfile.value)
async function memberCreate() {
try {
const res = await props.neko.members.membersCreate({
username: newUsername.value,
password: newPassword.value,
profile: newProfile.value,
})
if (res.data) {
members.value = [...members.value, res.data]
}
get sessions(): Record<string, StateModels.Session> {
return this.neko.state.sessions
}
get membersWithoutSessions(): ApiModels.MemberData[] {
return this.members.filter(({ id }) => id && !(id in this.sessions))
}
members: ApiModels.MemberData[] = []
plugins: {
id: string
old: Array<Array<string>>
new: Array<Array<string>>
profile: ApiModels.MemberProfile
} | null = null
newUsername: string = ''
newPassword: string = ''
newProfile: ApiModels.MemberProfile = {}
defProfile: ApiModels.MemberProfile = {
name: '',
is_admin: false,
can_login: true,
can_connect: true,
can_watch: true,
can_host: true,
can_share_media: true,
can_access_clipboard: true,
sends_inactive_cursor: true,
can_see_inactive_cursors: true,
}
async memberCreate() {
try {
const res = await this.neko.members.membersCreate({
username: this.newUsername,
password: this.newPassword,
profile: this.newProfile,
})
if (res.data) {
Vue.set(this, 'members', [...this.members, res.data])
}
// clear
Vue.set(this, 'newUsername', '')
Vue.set(this, 'newPassword', '')
Vue.set(this, 'newProfile', Object.assign({}, this.defProfile))
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async membersLoad(limit: number = 0) {
const offset = 0
try {
const res = await this.neko.members.membersList(limit, offset)
Vue.set(this, 'members', res.data)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async memberGetProfile(memberId: string): Promise<ApiModels.MemberProfile | undefined> {
try {
const res = await this.neko.members.membersGetProfile(memberId)
return res.data
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async updateProfile(memberId: string, memberProfile: ApiModels.MemberProfile) {
try {
await this.neko.members.membersUpdateProfile(memberId, memberProfile)
const members = this.members.map((member) => {
if (member.id == memberId) {
return {
id: memberId,
profile: { ...member.profile, ...memberProfile },
}
} else {
return member
}
})
Vue.set(this, 'members', members)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async updatePassword(memberId: string, password: string) {
try {
await this.neko.members.membersUpdatePassword(memberId, { password })
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async memberRemove(memberId: string) {
try {
await this.neko.members.membersRemove(memberId)
const members = this.members.filter(({ id }) => id != memberId)
Vue.set(this, 'members', members)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
showPlugins(id: string, profile: ApiModels.MemberProfile) {
const old = Object.entries(profile.plugins || {}).map(([key, val]) => [key, JSON.stringify(val, null, 2)])
this.plugins = {
id,
old,
new: old.length > 0 ? [] : [['', '']],
profile,
}
}
savePlugins() {
if (!this.plugins) return
let errKey = ''
try {
let plugins = {} as any
for (let [key, val] of this.plugins.old) {
errKey = key
plugins[key] = JSON.parse(val)
}
for (let [key, val] of this.plugins.new) {
errKey = key
plugins[key] = JSON.parse(val)
}
this.updateProfile(this.plugins.id, { plugins })
this.plugins = null
} catch (e: any) {
alert(errKey + ': ' + e)
}
}
mounted() {
this.membersLoad(10)
}
// clear
newUsername.value = ''
newPassword.value = ''
newProfile.value = Object.assign({}, defProfile.value)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async function membersLoad(limit: number = 0) {
const offset = 0
try {
const res = await props.neko.members.membersList(limit, offset)
members.value = res.data
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async function memberGetProfile(memberId: string): Promise<ApiModels.MemberProfile | undefined> {
try {
const res = await props.neko.members.membersGetProfile(memberId)
return res.data
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async function updateProfile(memberId: string, memberProfile: ApiModels.MemberProfile) {
try {
await props.neko.members.membersUpdateProfile(memberId, memberProfile)
const newMembers = members.value.map((member) => {
if (member.id == memberId) {
return {
id: memberId,
profile: { ...member.profile, ...memberProfile },
}
} else {
return member
}
})
members.value = newMembers // TODO: Vue.Set
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async function updatePassword(memberId: string, password: string) {
try {
await props.neko.members.membersUpdatePassword(memberId, { password })
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
async function memberRemove(memberId: string) {
try {
await props.neko.members.membersRemove(memberId)
const newMembers = members.value.filter(({ id }) => id != memberId)
members.value = newMembers // TODO: Vue.Set
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
function showPlugins(id: string, profile: ApiModels.MemberProfile) {
const old = Object.entries(profile.plugins || {}).map(([key, val]) => [key, JSON.stringify(val, null, 2)])
plugins.value = {
id,
old,
new: old.length > 0 ? [] : [['', '']],
profile,
}
}
function savePlugins() {
if (!plugins.value) return
let errKey = ''
try {
let plugins = {} as any
for (let [key, val] of plugins.value.old) {
errKey = key
plugins[key] = JSON.parse(val)
}
for (let [key, val] of plugins.value.new) {
errKey = key
plugins[key] = JSON.parse(val)
}
updateProfile(plugins.value.id, { plugins })
plugins.value = null
} catch (e: any) {
alert(errKey + ': ' + e)
}
}
onMounted(() => {
membersLoad(10)
})
</script>

View File

@ -1,17 +1,17 @@
<template>
<div id="neko" :class="[expanded ? 'expanded' : '']">
<main class="neko-main">
<div class="header-container">
<neko-header :neko="neko" @toggle="expanded = !expanded" />
<div class="header-container" v-if="neko">
<NekoHeader :neko="neko" @toggle="expanded = !expanded" />
</div>
<div class="video-container">
<neko-canvas ref="neko" :server="server" autologin autoconnect autoplay />
<div v-if="loaded && neko.private_mode_enabled" class="player-notif">Private mode is currently enabled.</div>
<NekoCanvas ref="neko" :server="server" autologin autoconnect autoplay />
<div v-if="loaded && neko!.private_mode_enabled" class="player-notif">Private mode is currently enabled.</div>
<div
v-if="loaded && neko.state.connection.type === 'webrtc' && !neko.state.video.playing"
v-if="loaded && neko!.state.connection.type === 'webrtc' && !neko!.state.video.playing"
class="player-overlay"
>
<i @click.stop.prevent="neko.play()" v-if="neko.state.video.playable" class="fas fa-play-circle" />
<i @click.stop.prevent="neko!.play()" v-if="neko!.state.video.playable" class="fas fa-play-circle" />
</div>
<div v-if="uploadActive" class="player-overlay" style="background: rgba(0, 0, 0, 0.8); font-size: 1vw">
UPLOAD IN PROGRESS: {{ Math.round(uploadProgress) }}%
@ -30,11 +30,11 @@
@dragenter.stop.prevent
@dragleave.stop.prevent
@dragover.stop.prevent
@drop.stop.prevent="dialogUploadFiles($event.dataTransfer.files)"
@drop.stop.prevent="dialogUploadFiles([...$event.dataTransfer!.files])"
>
<span style="padding: 1em">UPLOAD REQUESTED:</span>
<span style="background: white">
<input type="file" @change="dialogUploadFiles($event.target.files)" multiple />
<input type="file" @change="dialogUploadFiles([...($event.target as HTMLInputElement)!.files!])" multiple />
</span>
<span style="padding: 1em; padding-bottom: 0; font-style: italic">(or drop files here)</span>
<span style="padding: 1em">
@ -45,15 +45,15 @@
<div class="room-container" style="text-align: center">
<button
v-if="loaded && isTouchDevice"
@click="neko.mobileKeyboardToggle"
@click="neko!.mobileKeyboardToggle"
style="position: absolute; left: 5px; transform: translateY(-100%)"
>
<i class="fa fa-keyboard" />
</button>
<span v-if="loaded && neko.state.session_id" style="padding-top: 10px">
<span v-if="loaded && neko!.state.session_id" style="padding-top: 10px">
You are logged in as
<strong style="font-weight: bold">
{{ neko.state.sessions[neko.state.session_id].profile.name }}
{{ neko!.state.sessions[neko!.state.session_id].profile.name }}
</strong>
</span>
@ -65,14 +65,14 @@
</button>
</div>
<div class="controls">
<template v-if="loaded">
<neko-connect v-if="neko.state.connection.status == 'disconnected'" :neko="neko" />
<neko-controls v-else :neko="neko" />
<template v-if="loaded && neko">
<NekoConnect v-if="neko!.state.connection.status == 'disconnected'" :neko="neko" />
<NekoControls v-else :neko="neko" />
</template>
</div>
<div class="right-menu">
<div style="text-align: right" v-if="loaded">
<button v-if="neko.state.connection.status != 'disconnected'" @click="neko.disconnect()">
<button v-if="neko!.state.connection.status != 'disconnected'" @click="neko!.disconnect()">
disconnect
</button>
</div>
@ -104,11 +104,11 @@
<component v-for="(el, key) in pluginsTabs" :key="key" :is="el" :tab="tab" @tab="tab = $event" />
</ul>
</div>
<div class="page-container">
<neko-events v-if="tab === 'events'" :neko="neko" />
<neko-members v-if="tab === 'members'" :neko="neko" />
<neko-media v-if="tab === 'media'" :neko="neko" />
<neko-chat v-show="tab === 'chat'" :neko="neko" />
<div class="page-container" v-if="neko">
<NekoEvents v-if="tab === 'events'" :neko="neko" />
<NekoMembers v-if="tab === 'members'" :neko="neko" />
<NekoMedia v-if="tab === 'media'" :neko="neko" />
<NekoChat v-show="tab === 'chat'" :neko="neko" />
<!-- Plugins -->
<component v-for="(el, key) in pluginsComponents" :key="key" :is="el" :tab="tab" :neko="neko" />
@ -318,345 +318,331 @@
}
</style>
<script lang="ts">
// plugins must be available at:
// ./plugins/{name}/main-tabs.vue
// ./plugins/{name}/main-components.vue
let plugins = [] as string[]
<script lang="ts" setup>
// plugins must be available at:
// ./plugins/{name}/main-tabs.vue
// ./plugins/{name}/main-components.vue
let plugins = [] as string[]
// dynamic plugins loader
;(function (r: any) {
r.keys().forEach((key: string) => {
const found = key.match(/\.\/(.*?)\//)
if (found) {
plugins.push(found[1])
console.log('loading a plugin:', found[1])
}
})
})(require.context('./plugins/', true, /(main-tabs|main-components)\.vue$/))
// dynamic plugins loader
//;(function (r: any) {
// r.keys().forEach((key: string) => {
// const found = key.match(/\.\/(.*?)\//)
// if (found) {
// plugins.push(found[1])
// console.log('loading a plugin:', found[1])
// }
// })
//})(require.context('./plugins/', true, /(main-tabs|main-components)\.vue$/))
import { Vue, Component, Ref } from 'vue-property-decorator'
import { AxiosProgressEvent } from 'axios'
import NekoCanvas from '~/component/main.vue'
import NekoHeader from './components/header.vue'
import NekoConnect from './components/connect.vue'
import NekoControls from './components/controls.vue'
import NekoEvents from './components/events.vue'
import NekoMembers from './components/members.vue'
import NekoMedia from './components/media.vue'
import NekoChat from './components/chat.vue'
import { ref, computed, onMounted } from 'vue'
@Component({
name: 'neko',
components: {
'neko-canvas': NekoCanvas,
'neko-header': NekoHeader,
'neko-connect': NekoConnect,
'neko-controls': NekoControls,
'neko-events': NekoEvents,
'neko-members': NekoMembers,
'neko-media': NekoMedia,
'neko-chat': NekoChat,
},
computed: {
pluginsTabs() {
let x = {} as Record<string, any>
for (let p of plugins) {
x[p] = () => import('./plugins/' + p + '/main-tabs.vue')
}
return x
},
pluginsComponents() {
let x = {} as Record<string, any>
for (let p of plugins) {
x[p] = () => import('./plugins/' + p + '/main-components.vue')
}
return x
},
},
})
export default class extends Vue {
@Ref('neko') readonly neko!: NekoCanvas
expanded: boolean = !window.matchMedia('(max-width: 600px)').matches // default to expanded on bigger screens
loaded: boolean = false
tab: string = ''
import type { AxiosProgressEvent } from 'axios'
import NekoCanvas from '@/component/main.vue'
import NekoHeader from './components/header.vue'
import NekoConnect from './components/connect.vue'
import NekoControls from './components/controls.vue'
import NekoEvents from './components/events.vue'
import NekoMembers from './components/members.vue'
import NekoMedia from './components/media.vue'
import NekoChat from './components/chat.vue'
server: string = location.href
const pluginsTabs = computed(() => {
let x = {} as Record<string, any>
for (let p of plugins) {
x[p] = () => import('./plugins/' + p + '/main-tabs.vue')
}
return x
})
uploadActive = false
uploadProgress = 0
const pluginsComponents = computed(() => {
let x = {} as Record<string, any>
for (let p of plugins) {
x[p] = () => import('./plugins/' + p + '/main-components.vue')
}
return x
})
get isTouchDevice(): boolean {
return 'ontouchstart' in window || navigator.maxTouchPoints > 0
}
const neko = ref<typeof NekoCanvas>()
dialogOverlayActive = false
dialogRequestActive = false
async dialogUploadFiles(files: File[]) {
console.log('will upload files', files)
const expanded = ref(!window.matchMedia('(max-width: 600px)').matches) // default to expanded on bigger screens
const loaded = ref(false)
const tab = ref('')
this.uploadActive = true
this.uploadProgress = 0
try {
await this.neko.room.uploadDialog([...files], {
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
if (!progressEvent.total) {
this.uploadProgress = 0
return
}
this.uploadProgress = (progressEvent.loaded / progressEvent.total) * 100
},
})
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
} finally {
this.uploadActive = false
}
}
const server = ref(location.href)
dialogCancel() {
this.neko.room.uploadDialogClose()
}
const uploadActive = ref(false)
const uploadProgress = ref(0)
mounted() {
this.loaded = true
this.tab = 'events'
//@ts-ignore
window.neko = this.neko
const isTouchDevice = computed(() => 'ontouchstart' in window || navigator.maxTouchPoints > 0)
// initial URL
const url = new URL(location.href).searchParams.get('url')
if (url) {
this.server = url
}
const dialogOverlayActive = ref(false)
const dialogRequestActive = ref(false)
async function dialogUploadFiles(files: File[]) {
console.log('will upload files', files)
//
// connection events
//
this.neko.events.on('connection.status', (status: 'connected' | 'connecting' | 'disconnected') => {
console.log('connection.status', status)
})
this.neko.events.on('connection.type', (type: 'fallback' | 'webrtc' | 'none') => {
console.log('connection.type', type)
})
this.neko.events.on('connection.webrtc.sdp', (type: 'local' | 'remote', data: string) => {
console.log('connection.webrtc.sdp', type, data)
})
this.neko.events.on('connection.webrtc.sdp.candidate', (type: 'local' | 'remote', data: RTCIceCandidateInit) => {
console.log('connection.webrtc.sdp.candidate', type, data)
})
this.neko.events.on('connection.closed', (error?: Error) => {
if (error) {
alert('Connection closed with error: ' + error.message)
} else {
alert('Connection closed without error.')
}
})
//
// drag and drop events
//
this.neko.events.on('upload.drop.started', () => {
this.uploadActive = true
this.uploadProgress = 0
})
this.neko.events.on('upload.drop.progress', (progressEvent: AxiosProgressEvent) => {
uploadActive.value = true
uploadProgress.value = 0
try {
await neko.value!.room.uploadDialog([...files], {
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
if (!progressEvent.total) {
this.uploadProgress = 0
uploadProgress.value = 0
return
}
this.uploadProgress = (progressEvent.loaded / progressEvent.total) * 100
})
this.neko.events.on('upload.drop.finished', (e?: any) => {
this.uploadActive = false
if (e) {
alert(e.response ? e.response.data.message : e)
}
})
//
// upload dialog events
//
this.neko.events.on('upload.dialog.requested', () => {
this.dialogRequestActive = true
})
this.neko.events.on('upload.dialog.overlay', (id: string) => {
this.dialogOverlayActive = true
console.log('upload.dialog.overlay', id)
})
this.neko.events.on('upload.dialog.closed', () => {
this.dialogOverlayActive = false
this.dialogRequestActive = false
})
//
// custom messages events
//
this.neko.events.on('receive.unicast', (sender: string, subject: string, body: string) => {
console.log('receive.unicast', sender, subject, body)
})
this.neko.events.on('receive.broadcast', (sender: string, subject: string, body: string) => {
console.log('receive.broadcast', sender, subject, body)
})
//
// session events
//
this.neko.events.on('session.created', (id: string) => {
console.log('session.created', id)
})
this.neko.events.on('session.deleted', (id: string) => {
console.log('session.deleted', id)
})
this.neko.events.on('session.updated', (id: string) => {
console.log('session.updated', id)
})
//
// room events
//
this.neko.events.on('room.control.host', (hasHost: boolean, hostID?: string) => {
console.log('room.control.host', hasHost, hostID)
})
this.neko.events.on('room.screen.updated', (width: number, height: number, rate: number) => {
console.log('room.screen.updated', width, height, rate)
})
this.neko.events.on('room.clipboard.updated', (text: string) => {
console.log('room.clipboard.updated', text)
})
this.neko.events.on('room.broadcast.status', (isActive: boolean, url?: string) => {
console.log('room.broadcast.status', isActive, url)
})
//
// control events
//
this.neko.control.on('overlay.click', (e: MouseEvent) => {
console.log('control: overlay.click', e)
})
this.neko.control.on('overlay.contextmenu', (e: MouseEvent) => {
console.log('control: overlay.contextmenu', e)
})
// custom inactive cursor draw function
this.neko.setInactiveCursorDrawFunction(
(ctx: CanvasRenderingContext2D, x: number, y: number, sessionId: string) => {
const cursorTag = this.neko.state.sessions[sessionId]?.profile.name || ''
const colorLight = '#CCDFF6'
const colorDark = '#488DDE'
// get current cursor position
x -= 4
y -= 4
// draw arrow path
const arrowPath = new Path2D('M5 5L19 12.5L12.3286 14.465L8.29412 20L5 5Z')
ctx.globalAlpha = 0.5
ctx.translate(x, y)
ctx.fillStyle = colorLight
ctx.fill(arrowPath)
ctx.lineWidth = 1.5
ctx.lineJoin = 'miter'
ctx.miterLimit = 10
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
ctx.strokeStyle = colorDark
ctx.stroke(arrowPath)
// draw cursor tag
if (cursorTag) {
const x = 20 // box margin x
const y = 20 // box margin y
ctx.globalAlpha = 0.5
ctx.font = '10px Arial, sans-serif'
ctx.textBaseline = 'top'
ctx.shadowColor = 'black'
ctx.shadowBlur = 2
ctx.lineWidth = 2
ctx.fillStyle = 'black'
ctx.strokeText(cursorTag, x, y)
ctx.shadowBlur = 0
ctx.fillStyle = 'white'
ctx.fillText(cursorTag, x, y)
}
},
)
this.toggleCursor()
}
private usesCursor = false
toggleCursor() {
if (this.usesCursor) {
this.usesCursor = false
this.neko.setCursorDrawFunction()
return
}
// custom cursor draw function
this.neko.setCursorDrawFunction(
(ctx: CanvasRenderingContext2D, x: number, y: number, {}, {}, sessionId: string) => {
const cursorTag = this.neko.state.sessions[sessionId]?.profile.name || ''
const colorLight = '#CCDFF6'
const colorDark = '#488DDE'
const fontColor = '#ffffff'
// get current cursor position
x -= 4
y -= 4
// draw arrow path
const arrowPath = new Path2D('M5 5L26 16.5L15.9929 19.513L9.94118 28L5 5Z')
ctx.translate(x, y)
ctx.fillStyle = colorLight
ctx.fill(arrowPath)
ctx.lineWidth = 2
ctx.lineJoin = 'miter'
ctx.miterLimit = 10
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
ctx.strokeStyle = colorDark
ctx.stroke(arrowPath)
// draw cursor tag
if (cursorTag) {
const fontSize = 12
const boxPaddingX = 9
const boxPaddingY = 6
const x = 22 // box margin x
const y = 28 // box margin y
// prepare tag text
ctx.font = '500 ' + fontSize + 'px Roboto, sans-serif'
ctx.textBaseline = 'ideographic'
// create tag container
const txtWidth = ctx.measureText(cursorTag).width
const w = txtWidth + boxPaddingX * 2
const h = fontSize + boxPaddingY * 2
const r = Math.min(w / 2, h / 2)
ctx.beginPath()
ctx.moveTo(x + r, y)
ctx.arcTo(x + w, y, x + w, y + h, r) // Top-Right
ctx.arcTo(x + w, y + h, x, y + h, r) // Bottom-Right
ctx.arcTo(x, y + h, x, y, r) // Bottom-Left
ctx.arcTo(x, y, x + w, y, 2) // Top-Left
ctx.closePath()
ctx.fillStyle = colorDark
ctx.fill()
// fill in tag text
ctx.fillStyle = fontColor
ctx.fillText(cursorTag, x + boxPaddingX, y + fontSize + boxPaddingY)
}
},
)
this.usesCursor = true
}
uploadProgress.value = (progressEvent.loaded / progressEvent.total) * 100
},
})
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
} finally {
uploadActive.value = false
}
}
function dialogCancel() {
neko.value!.room.uploadDialogClose()
}
onMounted(() => {
loaded.value = true
tab.value = 'events'
//@ts-ignore
window.neko = neko
// initial URL
const url = new URL(location.href).searchParams.get('url')
if (url) {
server.value = url
}
//
// connection events
//
neko.value!.events.on('connection.status', (status: 'connected' | 'connecting' | 'disconnected') => {
console.log('connection.status', status)
})
neko.value!.events.on('connection.type', (type: 'fallback' | 'webrtc' | 'none') => {
console.log('connection.type', type)
})
neko.value!.events.on('connection.webrtc.sdp', (type: 'local' | 'remote', data: string) => {
console.log('connection.webrtc.sdp', type, data)
})
neko.value!.events.on('connection.webrtc.sdp.candidate', (type: 'local' | 'remote', data: RTCIceCandidateInit) => {
console.log('connection.webrtc.sdp.candidate', type, data)
})
neko.value!.events.on('connection.closed', (error?: Error) => {
if (error) {
alert('Connection closed with error: ' + error.message)
} else {
alert('Connection closed without error.')
}
})
//
// drag and drop events
//
neko.value!.events.on('upload.drop.started', () => {
uploadActive.value = true
uploadProgress.value = 0
})
neko.value!.events.on('upload.drop.progress', (progressEvent: AxiosProgressEvent) => {
if (!progressEvent.total) {
uploadProgress.value = 0
return
}
uploadProgress.value = (progressEvent.loaded / progressEvent.total) * 100
})
neko.value!.events.on('upload.drop.finished', (e?: any) => {
uploadActive.value = false
if (e) {
alert(e.response ? e.response.data.message : e)
}
})
//
// upload dialog events
//
neko.value!.events.on('upload.dialog.requested', () => {
dialogRequestActive.value = true
})
neko.value!.events.on('upload.dialog.overlay', (id: string) => {
dialogOverlayActive.value = true
console.log('upload.dialog.overlay', id)
})
neko.value!.events.on('upload.dialog.closed', () => {
dialogOverlayActive.value = false
dialogRequestActive.value = false
})
//
// custom messages events
//
neko.value!.events.on('receive.unicast', (sender: string, subject: string, body: string) => {
console.log('receive.unicast', sender, subject, body)
})
neko.value!.events.on('receive.broadcast', (sender: string, subject: string, body: string) => {
console.log('receive.broadcast', sender, subject, body)
})
//
// session events
//
neko.value!.events.on('session.created', (id: string) => {
console.log('session.created', id)
})
neko.value!.events.on('session.deleted', (id: string) => {
console.log('session.deleted', id)
})
neko.value!.events.on('session.updated', (id: string) => {
console.log('session.updated', id)
})
//
// room events
//
neko.value!.events.on('room.control.host', (hasHost: boolean, hostID?: string) => {
console.log('room.control.host', hasHost, hostID)
})
neko.value!.events.on('room.screen.updated', (width: number, height: number, rate: number) => {
console.log('room.screen.updated', width, height, rate)
})
neko.value!.events.on('room.clipboard.updated', (text: string) => {
console.log('room.clipboard.updated', text)
})
neko.value!.events.on('room.broadcast.status', (isActive: boolean, url?: string) => {
console.log('room.broadcast.status', isActive, url)
})
//
// control events
//
neko.value!.control.on('overlay.click', (e: MouseEvent) => {
console.log('control: overlay.click', e)
})
neko.value!.control.on('overlay.contextmenu', (e: MouseEvent) => {
console.log('control: overlay.contextmenu', e)
})
// custom inactive cursor draw function
neko.value!.setInactiveCursorDrawFunction(
(ctx: CanvasRenderingContext2D, x: number, y: number, sessionId: string) => {
const cursorTag = neko.value!.state.sessions[sessionId]?.profile.name || ''
const colorLight = '#CCDFF6'
const colorDark = '#488DDE'
// get current cursor position
x -= 4
y -= 4
// draw arrow path
const arrowPath = new Path2D('M5 5L19 12.5L12.3286 14.465L8.29412 20L5 5Z')
ctx.globalAlpha = 0.5
ctx.translate(x, y)
ctx.fillStyle = colorLight
ctx.fill(arrowPath)
ctx.lineWidth = 1.5
ctx.lineJoin = 'miter'
ctx.miterLimit = 10
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
ctx.strokeStyle = colorDark
ctx.stroke(arrowPath)
// draw cursor tag
if (cursorTag) {
const x = 20 // box margin x
const y = 20 // box margin y
ctx.globalAlpha = 0.5
ctx.font = '10px Arial, sans-serif'
ctx.textBaseline = 'top'
ctx.shadowColor = 'black'
ctx.shadowBlur = 2
ctx.lineWidth = 2
ctx.fillStyle = 'black'
ctx.strokeText(cursorTag, x, y)
ctx.shadowBlur = 0
ctx.fillStyle = 'white'
ctx.fillText(cursorTag, x, y)
}
},
)
toggleCursor()
})
const usesCursor = ref(false)
function toggleCursor() {
if (usesCursor.value) {
neko.value!.setCursorDrawFunction()
usesCursor.value = false
return
}
// custom cursor draw function
neko.value!.setCursorDrawFunction(
(ctx: CanvasRenderingContext2D, x: number, y: number, {}, {}, sessionId: string) => {
const cursorTag = neko.value!.state.sessions[sessionId]?.profile.name || ''
const colorLight = '#CCDFF6'
const colorDark = '#488DDE'
const fontColor = '#ffffff'
// get current cursor position
x -= 4
y -= 4
// draw arrow path
const arrowPath = new Path2D('M5 5L26 16.5L15.9929 19.513L9.94118 28L5 5Z')
ctx.translate(x, y)
ctx.fillStyle = colorLight
ctx.fill(arrowPath)
ctx.lineWidth = 2
ctx.lineJoin = 'miter'
ctx.miterLimit = 10
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
ctx.strokeStyle = colorDark
ctx.stroke(arrowPath)
// draw cursor tag
if (cursorTag) {
const fontSize = 12
const boxPaddingX = 9
const boxPaddingY = 6
const x = 22 // box margin x
const y = 28 // box margin y
// prepare tag text
ctx.font = '500 ' + fontSize + 'px Roboto, sans-serif'
ctx.textBaseline = 'ideographic'
// create tag container
const txtWidth = ctx.measureText(cursorTag).width
const w = txtWidth + boxPaddingX * 2
const h = fontSize + boxPaddingY * 2
const r = Math.min(w / 2, h / 2)
ctx.beginPath()
ctx.moveTo(x + r, y)
ctx.arcTo(x + w, y, x + w, y + h, r) // Top-Right
ctx.arcTo(x + w, y + h, x, y + h, r) // Bottom-Right
ctx.arcTo(x, y + h, x, y, r * 2) // Bottom-Left
ctx.arcTo(x, y, x + w, y, r * 2) // Top-Left
ctx.closePath()
ctx.fillStyle = colorDark
ctx.fill()
// fill in tag text
ctx.fillStyle = fontColor
ctx.fillText(cursorTag, x + boxPaddingX, y + fontSize + boxPaddingY)
}
},
)
usesCursor.value = true
}
</script>
<style>

14
tsconfig.app.json Normal file
View File

@ -0,0 +1,14 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

View File

@ -1,42 +1,14 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"skipLibCheck": true,
"baseUrl": ".",
"types": [
"node",
"webpack-env"
],
"paths": {
"~/*": [
"src/*"
],
"@/*": [
"src/*"
]
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
],
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
],
"exclude": [
"node_modules"
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.vitest.json"
}
]
}

19
tsconfig.node.json Normal file
View File

@ -0,0 +1,19 @@
{
"extends": "@tsconfig/node20/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*"
],
"compilerOptions": {
"composite": true,
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

11
tsconfig.vitest.json Normal file
View File

@ -0,0 +1,11 @@
{
"extends": "./tsconfig.app.json",
"exclude": [],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo",
"lib": [],
"types": ["node", "jsdom"]
}
}

View File

@ -1,50 +0,0 @@
#!/bin/bash
rm -rf dist/types
# Find all vue files, and convert them to .ts files
find src/component -name "*.vue" -type f -print0 | while IFS= read -r -d '' file; do
# Get the file name
filename=$(basename -- "$file")
# Get the file name without extension
filename="${filename%.*}"
# Get the directory name
directory=$(dirname -- "$file")
# Get the directory name without the first dot
directory="${directory}"
if [ "$directory" = "" ]; then
directory="."
fi
echo "Creating: $file --> $directory/$filename.ts"
# Get contant of the file, that is between <script lang="ts"> and </script>
content=$(sed -n '/<script lang="ts">/,/<\/script>/p' "$file" | sed '1d;$d')
# Remove .vue in imports
content=$(echo "$content" | sed 's/\.vue//g')
# Create a new file with the same name and .ts extension
echo "$content" > "$directory/$filename.ts"
# Add file to .toDelete file
echo "$directory/$filename.ts" >> .toDelete
done
echo "Compiling files"
npx tsc -p types-tsconfig.json
# Remove all .js files in dist/types folder
echo "Removing .js files in dist/types"
find dist/types -name "*.js" -type f -delete
# Remove all files listed in .toDelete
echo "Removing files listed in .toDelete"
while read -r file; do
echo "Removing: $file"
rm -f "$file"
done < .toDelete
# Remove .toDelete file
rm -f .toDelete

View File

@ -1,26 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"declaration": true,
"rootDir": "src/component",
"outDir": "dist/types",
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/component/**/*.ts"
],
"exclude": [
"node_modules"
]
}

16
vite.config.ts Normal file
View File

@ -0,0 +1,16 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})

14
vitest.config.ts Normal file
View File

@ -0,0 +1,14 @@
import { fileURLToPath } from 'node:url'
import { mergeConfig, defineConfig, configDefaults } from 'vitest/config'
import viteConfig from './vite.config'
export default mergeConfig(
viteConfig,
defineConfig({
test: {
environment: 'jsdom',
exclude: [...configDefaults.exclude, 'e2e/*'],
root: fileURLToPath(new URL('./', import.meta.url))
}
})
)

View File

@ -1,33 +0,0 @@
const path = require('path')
const webpack = require('webpack')
module.exports = {
productionSourceMap: false,
publicPath: './',
assetsDir: './',
configureWebpack: {
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js',
'~': path.resolve(__dirname, 'src/'),
},
},
plugins: [
new webpack.NormalModuleReplacementPlugin(
/(.*)__KEYBOARD__/,
function(resource){
resource.request = resource.request
.replace(/__KEYBOARD__/, process.env.KEYBOARD || 'guacamole');
},
),
],
},
devServer: {
allowedHosts: "all",
proxy: {
'^/api': {
target: 'http://' + process.env.NEKO_HOST + ':' + process.env.NEKO_PORT + '/',
},
},
},
}