Frontend: Removed calckey-js autogenerated docs and integrations, reformated the entire frontend
ci/woodpecker/push/ociImagePush Pipeline failed Details

This commit is contained in:
Natty 2023-07-23 15:31:28 +02:00
parent 40c471ff56
commit 8cce5fc419
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
648 changed files with 62526 additions and 82020 deletions

View File

@ -1,364 +0,0 @@
/**
* Config file for API Extractor. For more info, please visit: https://api-extractor.com
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
/**
* Optionally specifies another JSON config file that this file extends from. This provides a way for
* standard settings to be shared across multiple projects.
*
* If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains
* the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be
* resolved using NodeJS require().
*
* SUPPORTED TOKENS: none
* DEFAULT VALUE: ""
*/
// "extends": "./shared/api-extractor-base.json"
// "extends": "my-package/include/api-extractor-base.json"
/**
* Determines the "<projectFolder>" token that can be used with other config file settings. The project folder
* typically contains the tsconfig.json and package.json config files, but the path is user-defined.
*
* The path is resolved relative to the folder of the config file that contains the setting.
*
* The default value for "projectFolder" is the token "<lookup>", which means the folder is determined by traversing
* parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder
* that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error
* will be reported.
*
* SUPPORTED TOKENS: <lookup>
* DEFAULT VALUE: "<lookup>"
*/
// "projectFolder": "..",
/**
* (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor
* analyzes the symbols exported by this module.
*
* The file extension must be ".d.ts" and not ".ts".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
*/
"mainEntryPointFilePath": "<projectFolder>/built/index.d.ts",
/**
* A list of NPM package names whose exports should be treated as part of this package.
*
* For example, suppose that Webpack is used to generate a distributed bundle for the project "library1",
* and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part
* of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly
* imports library2. To avoid this, we can specify:
*
* "bundledPackages": [ "library2" ],
*
* This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been
* local files for library1.
*/
"bundledPackages": [],
/**
* Determines how the TypeScript compiler engine will be invoked by API Extractor.
*/
"compiler": {
/**
* Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* Note: This setting will be ignored if "overrideTsconfig" is used.
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/tsconfig.json"
*/
// "tsconfigFilePath": "<projectFolder>/tsconfig.json",
/**
* Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk.
* The object must conform to the TypeScript tsconfig schema:
*
* http://json.schemastore.org/tsconfig
*
* If omitted, then the tsconfig.json file will be read from the "projectFolder".
*
* DEFAULT VALUE: no overrideTsconfig section
*/
// "overrideTsconfig": {
// . . .
// }
/**
* This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended
* and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when
* dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses
* for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck.
*
* DEFAULT VALUE: false
*/
// "skipLibCheck": true,
},
/**
* Configures how the API report file (*.api.md) will be generated.
*/
"apiReport": {
/**
* (REQUIRED) Whether to generate an API report.
*/
"enabled": true
/**
* The filename for the API report files. It will be combined with "reportFolder" or "reportTempFolder" to produce
* a full file path.
*
* The file extension should be ".api.md", and the string should not contain a path separator such as "\" or "/".
*
* SUPPORTED TOKENS: <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<unscopedPackageName>.api.md"
*/
// "reportFileName": "<unscopedPackageName>.api.md",
/**
* Specifies the folder where the API report file is written. The file name portion is determined by
* the "reportFileName" setting.
*
* The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy,
* e.g. for an API review.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/etc/"
*/
// "reportFolder": "<projectFolder>/etc/",
/**
* Specifies the folder where the temporary report file is written. The file name portion is determined by
* the "reportFileName" setting.
*
* After the temporary file is written to disk, it is compared with the file in the "reportFolder".
* If they are different, a production build will fail.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/temp/"
*/
// "reportTempFolder": "<projectFolder>/temp/"
},
/**
* Configures how the doc model file (*.api.json) will be generated.
*/
"docModel": {
/**
* (REQUIRED) Whether to generate a doc model file.
*/
"enabled": true
/**
* The output path for the doc model file. The file extension should be ".api.json".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/temp/<unscopedPackageName>.api.json"
*/
// "apiJsonFilePath": "<projectFolder>/temp/<unscopedPackageName>.api.json"
},
/**
* Configures how the .d.ts rollup file will be generated.
*/
"dtsRollup": {
/**
* (REQUIRED) Whether to generate the .d.ts rollup file.
*/
"enabled": false
/**
* Specifies the output path for a .d.ts rollup file to be generated without any trimming.
* This file will include all declarations that are exported by the main entry point.
*
* If the path is an empty string, then this file will not be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/dist/<unscopedPackageName>.d.ts"
*/
// "untrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>.d.ts",
/**
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release.
* This file will include only declarations that are marked as "@public" or "@beta".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: ""
*/
// "betaTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-beta.d.ts",
/**
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release.
* This file will include only declarations that are marked as "@public".
*
* If the path is an empty string, then this file will not be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: ""
*/
// "publicTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-public.d.ts",
/**
* When a declaration is trimmed, by default it will be replaced by a code comment such as
* "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the
* declaration completely.
*
* DEFAULT VALUE: false
*/
// "omitTrimmingComments": true
},
/**
* Configures how the tsdoc-metadata.json file will be generated.
*/
"tsdocMetadata": {
/**
* Whether to generate the tsdoc-metadata.json file.
*
* DEFAULT VALUE: true
*/
// "enabled": true,
/**
* Specifies where the TSDoc metadata file should be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* The default value is "<lookup>", which causes the path to be automatically inferred from the "tsdocMetadata",
* "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup
* falls back to "tsdoc-metadata.json" in the package folder.
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<lookup>"
*/
// "tsdocMetadataFilePath": "<projectFolder>/dist/tsdoc-metadata.json"
},
/**
* Specifies what type of newlines API Extractor should use when writing output files. By default, the output files
* will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead.
* To use the OS's default newline kind, specify "os".
*
* DEFAULT VALUE: "crlf"
*/
// "newlineKind": "crlf",
/**
* Configures how API Extractor reports error and warning messages produced during analysis.
*
* There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages.
*/
"messages": {
/**
* Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing
* the input .d.ts files.
*
* TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551"
*
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
*/
"compilerMessageReporting": {
/**
* Configures the default routing for messages that don't match an explicit rule in this table.
*/
"default": {
/**
* Specifies whether the message should be written to the the tool's output log. Note that
* the "addToApiReportFile" property may supersede this option.
*
* Possible values: "error", "warning", "none"
*
* Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail
* and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes
* the "--local" option), the warning is displayed but the build will not fail.
*
* DEFAULT VALUE: "warning"
*/
"logLevel": "warning"
/**
* When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md),
* then the message will be written inside that file; otherwise, the message is instead logged according to
* the "logLevel" option.
*
* DEFAULT VALUE: false
*/
// "addToApiReportFile": false
}
// "TS2551": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
},
/**
* Configures handling of messages reported by API Extractor during its analysis.
*
* API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag"
*
* DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings
*/
"extractorMessageReporting": {
"default": {
"logLevel": "none"
// "addToApiReportFile": false
}
// "ae-extra-release-tag": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
},
/**
* Configures handling of messages reported by the TSDoc parser when analyzing code comments.
*
* TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text"
*
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
*/
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
// "addToApiReportFile": false
}
// "tsdoc-link-tag-unescaped-text": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Acct](./calckey-js.acct.md)
## Acct type
**Signature:**
```typescript
export declare type Acct = {
username: string;
host: string | null;
};
```

View File

@ -1,24 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [APIClient](./calckey-js.api.apiclient.md) &gt; [(constructor)](./calckey-js.api.apiclient._constructor_.md)
## api.APIClient.(constructor)
Constructs a new instance of the `APIClient` class
**Signature:**
```typescript
constructor(opts: {
origin: APIClient["origin"];
credential?: APIClient["credential"];
fetch?: APIClient["fetch"] | null | undefined;
});
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| opts | { origin: [APIClient](./calckey-js.api.apiclient.md)<!-- -->\["origin"\]; credential?: [APIClient](./calckey-js.api.apiclient.md)<!-- -->\["credential"\]; fetch?: [APIClient](./calckey-js.api.apiclient.md)<!-- -->\["fetch"\] \| null \| undefined; } | |

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [APIClient](./calckey-js.api.apiclient.md) &gt; [credential](./calckey-js.api.apiclient.credential.md)
## api.APIClient.credential property
**Signature:**
```typescript
credential: string | null | undefined;
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [APIClient](./calckey-js.api.apiclient.md) &gt; [fetch](./calckey-js.api.apiclient.fetch.md)
## api.APIClient.fetch property
**Signature:**
```typescript
fetch: FetchLike;
```

View File

@ -1,32 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [APIClient](./calckey-js.api.apiclient.md)
## api.APIClient class
**Signature:**
```typescript
export declare class APIClient
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(opts)](./calckey-js.api.apiclient._constructor_.md) | | Constructs a new instance of the <code>APIClient</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [credential](./calckey-js.api.apiclient.credential.md) | | string \| null \| undefined | |
| [fetch](./calckey-js.api.apiclient.fetch.md) | | [FetchLike](./calckey-js.api.fetchlike.md) | |
| [origin](./calckey-js.api.apiclient.origin.md) | | string | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [request(endpoint, params, credential)](./calckey-js.api.apiclient.request.md) | | |

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [APIClient](./calckey-js.api.apiclient.md) &gt; [origin](./calckey-js.api.apiclient.origin.md)
## api.APIClient.origin property
**Signature:**
```typescript
origin: string;
```

View File

@ -1,57 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [APIClient](./calckey-js.api.apiclient.md) &gt; [request](./calckey-js.api.apiclient.request.md)
## api.APIClient.request() method
**Signature:**
```typescript
request<E extends keyof Endpoints, P extends Endpoints[E]["req"]>(
endpoint: E,
params?: P,
credential?: string | null | undefined,
): Promise<
Endpoints[E]["res"] extends {
$switch: {
$cases: [any, any][];
$default: any;
};
}
? IsCaseMatched<E, P, 0> extends true
? GetCaseResult<E, P, 0>
: IsCaseMatched<E, P, 1> extends true
? GetCaseResult<E, P, 1>
: IsCaseMatched<E, P, 2> extends true
? GetCaseResult<E, P, 2>
: IsCaseMatched<E, P, 3> extends true
? GetCaseResult<E, P, 3>
: IsCaseMatched<E, P, 4> extends true
? GetCaseResult<E, P, 4>
: IsCaseMatched<E, P, 5> extends true
? GetCaseResult<E, P, 5>
: IsCaseMatched<E, P, 6> extends true
? GetCaseResult<E, P, 6>
: IsCaseMatched<E, P, 7> extends true
? GetCaseResult<E, P, 7>
: IsCaseMatched<E, P, 8> extends true
? GetCaseResult<E, P, 8>
: IsCaseMatched<E, P, 9> extends true
? GetCaseResult<E, P, 9>
: Endpoints[E]["res"]["$switch"]["$default"]
: Endpoints[E]["res"]
>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| endpoint | E | |
| params | P | _(Optional)_ |
| credential | string \| null \| undefined | _(Optional)_ |
**Returns:**
Promise&lt; [Endpoints](./calckey-js.endpoints.md)<!-- -->\[E\]\["res"\] extends { $switch: { $cases: \[any, any\]\[\]; $default: any; }; } ? IsCaseMatched&lt;E, P, 0&gt; extends true ? GetCaseResult&lt;E, P, 0&gt; : IsCaseMatched&lt;E, P, 1&gt; extends true ? GetCaseResult&lt;E, P, 1&gt; : IsCaseMatched&lt;E, P, 2&gt; extends true ? GetCaseResult&lt;E, P, 2&gt; : IsCaseMatched&lt;E, P, 3&gt; extends true ? GetCaseResult&lt;E, P, 3&gt; : IsCaseMatched&lt;E, P, 4&gt; extends true ? GetCaseResult&lt;E, P, 4&gt; : IsCaseMatched&lt;E, P, 5&gt; extends true ? GetCaseResult&lt;E, P, 5&gt; : IsCaseMatched&lt;E, P, 6&gt; extends true ? GetCaseResult&lt;E, P, 6&gt; : IsCaseMatched&lt;E, P, 7&gt; extends true ? GetCaseResult&lt;E, P, 7&gt; : IsCaseMatched&lt;E, P, 8&gt; extends true ? GetCaseResult&lt;E, P, 8&gt; : IsCaseMatched&lt;E, P, 9&gt; extends true ? GetCaseResult&lt;E, P, 9&gt; : [Endpoints](./calckey-js.endpoints.md)<!-- -->\[E\]\["res"\]\["$switch"\]\["$default"\] : [Endpoints](./calckey-js.endpoints.md)<!-- -->\[E\]\["res"\] &gt;

View File

@ -1,17 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [APIError](./calckey-js.api.apierror.md)
## api.APIError type
**Signature:**
```typescript
export declare type APIError = {
id: string;
code: string;
message: string;
kind: "client" | "server";
info: Record<string, any>;
};
```

View File

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [FetchLike](./calckey-js.api.fetchlike.md)
## api.FetchLike type
**Signature:**
```typescript
export declare type FetchLike = (
input: string,
init?: {
method?: string;
body?: string;
credentials?: RequestCredentials;
cache?: RequestCache;
},
) => Promise<{
status: number;
json(): Promise<any>;
}>;
```

View File

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md) &gt; [isAPIError](./calckey-js.api.isapierror.md)
## api.isAPIError() function
**Signature:**
```typescript
export declare function isAPIError(reason: any): reason is APIError;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| reason | any | |
**Returns:**
reason is [APIError](./calckey-js.api.apierror.md)

View File

@ -1,25 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [api](./calckey-js.api.md)
## api namespace
## Classes
| Class | Description |
| --- | --- |
| [APIClient](./calckey-js.api.apiclient.md) | |
## Functions
| Function | Description |
| --- | --- |
| [isAPIError(reason)](./calckey-js.api.isapierror.md) | |
## Type Aliases
| Type Alias | Description |
| --- | --- |
| [APIError](./calckey-js.api.apierror.md) | |
| [FetchLike](./calckey-js.api.fetchlike.md) | |

View File

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [(constructor)](./calckey-js.channelconnection._constructor_.md)
## ChannelConnection.(constructor)
Constructs a new instance of the `Connection` class
**Signature:**
```typescript
constructor(stream: Stream, channel: string, name?: string);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| stream | [Stream](./calckey-js.stream.md) | |
| channel | string | |
| name | string | _(Optional)_ |

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [channel](./calckey-js.channelconnection.channel.md)
## ChannelConnection.channel property
**Signature:**
```typescript
channel: string;
```

View File

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [dispose](./calckey-js.channelconnection.dispose.md)
## ChannelConnection.dispose() method
**Signature:**
```typescript
abstract dispose(): void;
```
**Returns:**
void

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [id](./calckey-js.channelconnection.id.md)
## ChannelConnection.id property
**Signature:**
```typescript
abstract id: string;
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [inCount](./calckey-js.channelconnection.incount.md)
## ChannelConnection.inCount property
**Signature:**
```typescript
inCount: number;
```

View File

@ -1,39 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md)
## ChannelConnection class
**Signature:**
```typescript
export declare abstract class Connection<
Channel extends AnyOf<Channels> = any,
> extends EventEmitter<Channel["events"]>
```
**Extends:** EventEmitter&lt;Channel\["events"\]&gt;
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(stream, channel, name)](./calckey-js.channelconnection._constructor_.md) | | Constructs a new instance of the <code>Connection</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [channel](./calckey-js.channelconnection.channel.md) | | string | |
| [id](./calckey-js.channelconnection.id.md) | <code>abstract</code> | string | |
| [inCount](./calckey-js.channelconnection.incount.md) | | number | |
| [name?](./calckey-js.channelconnection.name.md) | | string | _(Optional)_ |
| [outCount](./calckey-js.channelconnection.outcount.md) | | number | |
| [stream](./calckey-js.channelconnection.stream.md) | <code>protected</code> | [Stream](./calckey-js.stream.md) | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [dispose()](./calckey-js.channelconnection.dispose.md) | <code>abstract</code> | |
| [send(type, body)](./calckey-js.channelconnection.send.md) | | |

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [name](./calckey-js.channelconnection.name.md)
## ChannelConnection.name property
**Signature:**
```typescript
name?: string;
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [outCount](./calckey-js.channelconnection.outcount.md)
## ChannelConnection.outCount property
**Signature:**
```typescript
outCount: number;
```

View File

@ -1,26 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [send](./calckey-js.channelconnection.send.md)
## ChannelConnection.send() method
**Signature:**
```typescript
send<T extends keyof Channel["receives"]>(
type: T,
body: Channel["receives"][T],
): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| type | T | |
| body | Channel\["receives"\]\[T\] | |
**Returns:**
void

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ChannelConnection](./calckey-js.channelconnection.md) &gt; [stream](./calckey-js.channelconnection.stream.md)
## ChannelConnection.stream property
**Signature:**
```typescript
protected stream: Stream;
```

View File

@ -1,143 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Channels](./calckey-js.channels.md)
## Channels type
**Signature:**
```typescript
export declare type Channels = {
main: {
params: null;
events: {
notification: (payload: Notification) => void;
mention: (payload: Note) => void;
reply: (payload: Note) => void;
renote: (payload: Note) => void;
follow: (payload: User) => void;
followed: (payload: User) => void;
unfollow: (payload: User) => void;
meUpdated: (payload: MeDetailed) => void;
pageEvent: (payload: PageEvent) => void;
urlUploadFinished: (payload: {
marker: string;
file: DriveFile;
}) => void;
readAllNotifications: () => void;
unreadNotification: (payload: Notification) => void;
unreadMention: (payload: Note["id"]) => void;
readAllUnreadMentions: () => void;
unreadSpecifiedNote: (payload: Note["id"]) => void;
readAllUnreadSpecifiedNotes: () => void;
readAllMessagingMessages: () => void;
messagingMessage: (payload: MessagingMessage) => void;
unreadMessagingMessage: (payload: MessagingMessage) => void;
readAllAntennas: () => void;
unreadAntenna: (payload: Antenna) => void;
readAllAnnouncements: () => void;
readAllChannels: () => void;
unreadChannel: (payload: Note["id"]) => void;
myTokenRegenerated: () => void;
reversiNoInvites: () => void;
reversiInvited: (payload: FIXME) => void;
signin: (payload: FIXME) => void;
registryUpdated: (payload: {
scope?: string[];
key: string;
value: any | null;
}) => void;
driveFileCreated: (payload: DriveFile) => void;
readAntenna: (payload: Antenna) => void;
};
receives: null;
};
homeTimeline: {
params: null;
events: {
note: (payload: Note) => void;
};
receives: null;
};
localTimeline: {
params: null;
events: {
note: (payload: Note) => void;
};
receives: null;
};
hybridTimeline: {
params: null;
events: {
note: (payload: Note) => void;
};
receives: null;
};
recommendedTimeline: {
params: null;
events: {
note: (payload: Note) => void;
};
receives: null;
};
globalTimeline: {
params: null;
events: {
note: (payload: Note) => void;
};
receives: null;
};
antenna: {
params: {
antennaId: Antenna["id"];
};
events: {
note: (payload: Note) => void;
};
receives: null;
};
messaging: {
params: {
otherparty?: User["id"] | null;
group?: UserGroup["id"] | null;
};
events: {
message: (payload: MessagingMessage) => void;
deleted: (payload: MessagingMessage["id"]) => void;
read: (payload: MessagingMessage["id"][]) => void;
typers: (payload: User[]) => void;
};
receives: {
read: {
id: MessagingMessage["id"];
};
};
};
serverStats: {
params: null;
events: {
stats: (payload: FIXME) => void;
};
receives: {
requestLog: {
id: string | number;
length: number;
};
};
};
queueStats: {
params: null;
events: {
stats: (payload: FIXME) => void;
};
receives: {
requestLog: {
id: string | number;
length: number;
};
};
};
};
```
**References:** [Note](./calckey-js.entities.note.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [MeDetailed](./calckey-js.entities.medetailed.md)<!-- -->, [PageEvent](./calckey-js.entities.pageevent.md)<!-- -->, [DriveFile](./calckey-js.entities.drivefile.md)<!-- -->, [MessagingMessage](./calckey-js.entities.messagingmessage.md)<!-- -->, [Antenna](./calckey-js.entities.antenna.md)<!-- -->, [UserGroup](./calckey-js.entities.usergroup.md)

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Ad](./calckey-js.entities.ad.md)
## entities.Ad type
**Signature:**
```typescript
export declare type Ad = TODO;
```

View File

@ -1,21 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Announcement](./calckey-js.entities.announcement.md)
## entities.Announcement type
**Signature:**
```typescript
export declare type Announcement = {
id: ID;
createdAt: DateString;
updatedAt: DateString | null;
text: string;
title: string;
imageUrl: string | null;
isRead?: boolean;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)

View File

@ -1,29 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Antenna](./calckey-js.entities.antenna.md)
## entities.Antenna type
**Signature:**
```typescript
export declare type Antenna = {
id: ID;
createdAt: DateString;
name: string;
keywords: string[][];
excludeKeywords: string[][];
src: "home" | "all" | "users" | "list" | "group" | "instances";
userListId: ID | null;
userGroupId: ID | null;
users: string[];
instances: string[];
caseSensitive: boolean;
notify: boolean;
withReplies: boolean;
withFile: boolean;
hasUnreadNote: boolean;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [App](./calckey-js.entities.app.md)
## entities.App type
**Signature:**
```typescript
export declare type App = TODO;
```

View File

@ -1,17 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [AuthSession](./calckey-js.entities.authsession.md)
## entities.AuthSession type
**Signature:**
```typescript
export declare type AuthSession = {
id: ID;
app: App;
token: string;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [App](./calckey-js.entities.app.md)

View File

@ -1,18 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Blocking](./calckey-js.entities.blocking.md)
## entities.Blocking type
**Signature:**
```typescript
export declare type Blocking = {
id: ID;
createdAt: DateString;
blockeeId: User["id"];
blockee: UserDetailed;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [UserDetailed](./calckey-js.entities.userdetailed.md)

View File

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Channel](./calckey-js.entities.channel.md)
## entities.Channel type
**Signature:**
```typescript
export declare type Channel = {
id: ID;
};
```
**References:** [ID](./calckey-js.entities.id.md)

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Clip](./calckey-js.entities.clip.md)
## entities.Clip type
**Signature:**
```typescript
export declare type Clip = TODO;
```

View File

@ -1,17 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [CustomEmoji](./calckey-js.entities.customemoji.md)
## entities.CustomEmoji type
**Signature:**
```typescript
export declare type CustomEmoji = {
id: string;
name: string;
url: string;
category: string;
aliases: string[];
};
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [DateString](./calckey-js.entities.datestring.md)
## entities.DateString type
**Signature:**
```typescript
export declare type DateString = string;
```

View File

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [DetailedInstanceMetadata](./calckey-js.entities.detailedinstancemetadata.md)
## entities.DetailedInstanceMetadata type
**Signature:**
```typescript
export declare type DetailedInstanceMetadata = LiteInstanceMetadata & {
features: Record<string, any>;
};
```
**References:** [LiteInstanceMetadata](./calckey-js.entities.liteinstancemetadata.md)

View File

@ -1,26 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [DriveFile](./calckey-js.entities.drivefile.md)
## entities.DriveFile type
**Signature:**
```typescript
export declare type DriveFile = {
id: ID;
createdAt: DateString;
isSensitive: boolean;
name: string;
thumbnailUrl: string;
url: string;
type: string;
size: number;
md5: string;
blurhash: string;
comment: string | null;
properties: Record<string, any>;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [DriveFolder](./calckey-js.entities.drivefolder.md)
## entities.DriveFolder type
**Signature:**
```typescript
export declare type DriveFolder = TODO;
```

View File

@ -1,18 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Following](./calckey-js.entities.following.md)
## entities.Following type
**Signature:**
```typescript
export declare type Following = {
id: ID;
createdAt: DateString;
followerId: User["id"];
followeeId: User["id"];
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [User](./calckey-js.entities.user.md)

View File

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [FollowingFolloweePopulated](./calckey-js.entities.followingfolloweepopulated.md)
## entities.FollowingFolloweePopulated type
**Signature:**
```typescript
export declare type FollowingFolloweePopulated = Following & {
followee: UserDetailed;
};
```
**References:** [Following](./calckey-js.entities.following.md)<!-- -->, [UserDetailed](./calckey-js.entities.userdetailed.md)

View File

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [FollowingFollowerPopulated](./calckey-js.entities.followingfollowerpopulated.md)
## entities.FollowingFollowerPopulated type
**Signature:**
```typescript
export declare type FollowingFollowerPopulated = Following & {
follower: UserDetailed;
};
```
**References:** [Following](./calckey-js.entities.following.md)<!-- -->, [UserDetailed](./calckey-js.entities.userdetailed.md)

View File

@ -1,17 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [FollowRequest](./calckey-js.entities.followrequest.md)
## entities.FollowRequest type
**Signature:**
```typescript
export declare type FollowRequest = {
id: ID;
follower: User;
followee: User;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [User](./calckey-js.entities.user.md)

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [GalleryPost](./calckey-js.entities.gallerypost.md)
## entities.GalleryPost type
**Signature:**
```typescript
export declare type GalleryPost = TODO;
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [ID](./calckey-js.entities.id.md)
## entities.ID type
**Signature:**
```typescript
export declare type ID = string;
```

View File

@ -1,40 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Instance](./calckey-js.entities.instance.md)
## entities.Instance type
**Signature:**
```typescript
export declare type Instance = {
id: ID;
caughtAt: DateString;
host: string;
usersCount: number;
notesCount: number;
followingCount: number;
followersCount: number;
driveUsage: number;
driveFiles: number;
latestRequestSentAt: DateString | null;
latestStatus: number | null;
latestRequestReceivedAt: DateString | null;
lastCommunicatedAt: DateString;
isNotResponding: boolean;
isSuspended: boolean;
softwareName: string | null;
softwareVersion: string | null;
openRegistrations: boolean | null;
name: string | null;
description: string | null;
maintainerName: string | null;
maintainerEmail: string | null;
iconUrl: string | null;
faviconUrl: string | null;
themeColor: string | null;
infoUpdatedAt: DateString | null;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)

View File

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [InstanceMetadata](./calckey-js.entities.instancemetadata.md)
## entities.InstanceMetadata type
**Signature:**
```typescript
export declare type InstanceMetadata =
| LiteInstanceMetadata
| DetailedInstanceMetadata;
```
**References:** [LiteInstanceMetadata](./calckey-js.entities.liteinstancemetadata.md)<!-- -->, [DetailedInstanceMetadata](./calckey-js.entities.detailedinstancemetadata.md)

View File

@ -1,46 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [LiteInstanceMetadata](./calckey-js.entities.liteinstancemetadata.md)
## entities.LiteInstanceMetadata type
**Signature:**
```typescript
export declare type LiteInstanceMetadata = {
maintainerName: string | null;
maintainerEmail: string | null;
version: string;
name: string | null;
uri: string;
description: string | null;
tosUrl: string | null;
disableRegistration: boolean;
disableLocalTimeline: boolean;
disableRecommendedTimeline: boolean;
disableGlobalTimeline: boolean;
driveCapacityPerLocalUserMb: number;
driveCapacityPerRemoteUserMb: number;
enableHcaptcha: boolean;
hcaptchaSiteKey: string | null;
enableRecaptcha: boolean;
recaptchaSiteKey: string | null;
swPublickey: string | null;
maxNoteTextLength: number;
enableEmail: boolean;
enableTwitterIntegration: boolean;
enableGithubIntegration: boolean;
enableDiscordIntegration: boolean;
enableServiceWorker: boolean;
emojis: CustomEmoji[];
ads: {
id: ID;
ratio: number;
place: string;
url: string;
imageUrl: string;
}[];
};
```
**References:** [CustomEmoji](./calckey-js.entities.customemoji.md)<!-- -->, [ID](./calckey-js.entities.id.md)

View File

@ -1,51 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md)
## entities namespace
## Type Aliases
| Type Alias | Description |
| --- | --- |
| [Ad](./calckey-js.entities.ad.md) | |
| [Announcement](./calckey-js.entities.announcement.md) | |
| [Antenna](./calckey-js.entities.antenna.md) | |
| [App](./calckey-js.entities.app.md) | |
| [AuthSession](./calckey-js.entities.authsession.md) | |
| [Blocking](./calckey-js.entities.blocking.md) | |
| [Channel](./calckey-js.entities.channel.md) | |
| [Clip](./calckey-js.entities.clip.md) | |
| [CustomEmoji](./calckey-js.entities.customemoji.md) | |
| [DateString](./calckey-js.entities.datestring.md) | |
| [DetailedInstanceMetadata](./calckey-js.entities.detailedinstancemetadata.md) | |
| [DriveFile](./calckey-js.entities.drivefile.md) | |
| [DriveFolder](./calckey-js.entities.drivefolder.md) | |
| [Following](./calckey-js.entities.following.md) | |
| [FollowingFolloweePopulated](./calckey-js.entities.followingfolloweepopulated.md) | |
| [FollowingFollowerPopulated](./calckey-js.entities.followingfollowerpopulated.md) | |
| [FollowRequest](./calckey-js.entities.followrequest.md) | |
| [GalleryPost](./calckey-js.entities.gallerypost.md) | |
| [ID](./calckey-js.entities.id.md) | |
| [Instance](./calckey-js.entities.instance.md) | |
| [InstanceMetadata](./calckey-js.entities.instancemetadata.md) | |
| [LiteInstanceMetadata](./calckey-js.entities.liteinstancemetadata.md) | |
| [MeDetailed](./calckey-js.entities.medetailed.md) | |
| [MessagingMessage](./calckey-js.entities.messagingmessage.md) | |
| [Note](./calckey-js.entities.note.md) | |
| [NoteFavorite](./calckey-js.entities.notefavorite.md) | |
| [NoteReaction](./calckey-js.entities.notereaction.md) | |
| [Notification](./calckey-js.entities.notification.md) | |
| [OriginType](./calckey-js.entities.origintype.md) | |
| [Page](./calckey-js.entities.page.md) | |
| [PageEvent](./calckey-js.entities.pageevent.md) | |
| [ServerInfo](./calckey-js.entities.serverinfo.md) | |
| [Signin](./calckey-js.entities.signin.md) | |
| [Stats](./calckey-js.entities.stats.md) | |
| [User](./calckey-js.entities.user.md) | |
| [UserDetailed](./calckey-js.entities.userdetailed.md) | |
| [UserGroup](./calckey-js.entities.usergroup.md) | |
| [UserList](./calckey-js.entities.userlist.md) | |
| [UserLite](./calckey-js.entities.userlite.md) | |
| [UserSorting](./calckey-js.entities.usersorting.md) | |

View File

@ -1,40 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [MeDetailed](./calckey-js.entities.medetailed.md)
## entities.MeDetailed type
**Signature:**
```typescript
export declare type MeDetailed = UserDetailed & {
avatarId: DriveFile["id"];
bannerId: DriveFile["id"];
autoAcceptFollowed: boolean;
alwaysMarkNsfw: boolean;
carefulBot: boolean;
emailNotificationTypes: string[];
hasPendingReceivedFollowRequest: boolean;
hasUnreadAnnouncement: boolean;
hasUnreadAntenna: boolean;
hasUnreadChannel: boolean;
hasUnreadMentions: boolean;
hasUnreadMessagingMessage: boolean;
hasUnreadNotification: boolean;
hasUnreadSpecifiedNotes: boolean;
hideOnlineStatus: boolean;
injectFeaturedNote: boolean;
integrations: Record<string, any>;
isDeleted: boolean;
isExplorable: boolean;
mutedWords: string[][];
mutingNotificationTypes: string[];
noCrawle: boolean;
preventAiLearning: boolean;
receiveAnnouncementEmail: boolean;
usePasswordLessLogin: boolean;
[other: string]: any;
};
```
**References:** [UserDetailed](./calckey-js.entities.userdetailed.md)<!-- -->, [DriveFile](./calckey-js.entities.drivefile.md)

View File

@ -1,27 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [MessagingMessage](./calckey-js.entities.messagingmessage.md)
## entities.MessagingMessage type
**Signature:**
```typescript
export declare type MessagingMessage = {
id: ID;
createdAt: DateString;
file: DriveFile | null;
fileId: DriveFile["id"] | null;
isRead: boolean;
reads: User["id"][];
text: string | null;
user: User;
userId: User["id"];
recipient?: User | null;
recipientId: User["id"] | null;
group?: UserGroup | null;
groupId: UserGroup["id"] | null;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [DriveFile](./calckey-js.entities.drivefile.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [UserGroup](./calckey-js.entities.usergroup.md)

View File

@ -1,51 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Note](./calckey-js.entities.note.md)
## entities.Note type
**Signature:**
```typescript
export declare type Note = {
id: ID;
createdAt: DateString;
text: string | null;
cw: string | null;
user: User;
userId: User["id"];
reply?: Note;
replyId: Note["id"];
renote?: Note;
renoteId: Note["id"];
files: DriveFile[];
fileIds: DriveFile["id"][];
visibility: "public" | "home" | "followers" | "specified";
visibleUserIds?: User["id"][];
localOnly?: boolean;
channel?: Channel["id"];
myReaction?: string;
reactions: Record<string, number>;
renoteCount: number;
repliesCount: number;
poll?: {
expiresAt: DateString | null;
multiple: boolean;
choices: {
isVoted: boolean;
text: string;
votes: number;
}[];
};
emojis: {
name: string;
url: string;
}[];
uri?: string;
url?: string;
updatedAt?: DateString;
isHidden?: boolean;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [Note](./calckey-js.entities.note.md)<!-- -->, [DriveFile](./calckey-js.entities.drivefile.md)<!-- -->, [Channel](./calckey-js.entities.channel.md)

View File

@ -1,18 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [NoteFavorite](./calckey-js.entities.notefavorite.md)
## entities.NoteFavorite type
**Signature:**
```typescript
export declare type NoteFavorite = {
id: ID;
createdAt: DateString;
noteId: Note["id"];
note: Note;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [Note](./calckey-js.entities.note.md)

View File

@ -1,18 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [NoteReaction](./calckey-js.entities.notereaction.md)
## entities.NoteReaction type
**Signature:**
```typescript
export declare type NoteReaction = {
id: ID;
createdAt: DateString;
user: UserLite;
type: string;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [UserLite](./calckey-js.entities.userlite.md)

View File

@ -1,82 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Notification](./calckey-js.entities.notification.md)
## entities.Notification type
**Signature:**
```typescript
export declare type Notification = {
id: ID;
createdAt: DateString;
isRead: boolean;
} & (
| {
type: "reaction";
reaction: string;
user: User;
userId: User["id"];
note: Note;
}
| {
type: "reply";
user: User;
userId: User["id"];
note: Note;
}
| {
type: "renote";
user: User;
userId: User["id"];
note: Note;
}
| {
type: "quote";
user: User;
userId: User["id"];
note: Note;
}
| {
type: "mention";
user: User;
userId: User["id"];
note: Note;
}
| {
type: "pollVote";
user: User;
userId: User["id"];
note: Note;
}
| {
type: "follow";
user: User;
userId: User["id"];
}
| {
type: "followRequestAccepted";
user: User;
userId: User["id"];
}
| {
type: "receiveFollowRequest";
user: User;
userId: User["id"];
}
| {
type: "groupInvited";
invitation: UserGroup;
user: User;
userId: User["id"];
}
| {
type: "app";
header?: string | null;
body: string;
icon?: string | null;
}
);
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [Note](./calckey-js.entities.note.md)<!-- -->, [UserGroup](./calckey-js.entities.usergroup.md)

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [OriginType](./calckey-js.entities.origintype.md)
## entities.OriginType type
**Signature:**
```typescript
export declare type OriginType = "combined" | "local" | "remote";
```

View File

@ -1,33 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Page](./calckey-js.entities.page.md)
## entities.Page type
**Signature:**
```typescript
export declare type Page = {
id: ID;
createdAt: DateString;
updatedAt: DateString;
userId: User["id"];
user: User;
content: Record<string, any>[];
variables: Record<string, any>[];
title: string;
name: string;
summary: string | null;
hideTitleWhenPinned: boolean;
alignCenter: boolean;
font: string;
script: string;
eyeCatchingImageId: DriveFile["id"] | null;
eyeCatchingImage: DriveFile | null;
attachedFiles: any;
likedCount: number;
isLiked?: boolean;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [DriveFile](./calckey-js.entities.drivefile.md)

View File

@ -1,19 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [PageEvent](./calckey-js.entities.pageevent.md)
## entities.PageEvent type
**Signature:**
```typescript
export declare type PageEvent = {
pageId: Page["id"];
event: string;
var: any;
userId: User["id"];
user: User;
};
```
**References:** [Page](./calckey-js.entities.page.md)<!-- -->, [User](./calckey-js.entities.user.md)

View File

@ -1,24 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [ServerInfo](./calckey-js.entities.serverinfo.md)
## entities.ServerInfo type
**Signature:**
```typescript
export declare type ServerInfo = {
machine: string;
cpu: {
model: string;
cores: number;
};
mem: {
total: number;
};
fs: {
total: number;
used: number;
};
};
```

View File

@ -1,19 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Signin](./calckey-js.entities.signin.md)
## entities.Signin type
**Signature:**
```typescript
export declare type Signin = {
id: ID;
createdAt: DateString;
ip: string;
headers: Record<string, any>;
success: boolean;
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)

View File

@ -1,19 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [Stats](./calckey-js.entities.stats.md)
## entities.Stats type
**Signature:**
```typescript
export declare type Stats = {
notesCount: number;
originalNotesCount: number;
usersCount: number;
originalUsersCount: number;
instances: number;
driveUsageLocal: number;
driveUsageRemote: number;
};
```

View File

@ -1,13 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [User](./calckey-js.entities.user.md)
## entities.User type
**Signature:**
```typescript
export declare type User = UserLite | UserDetailed;
```
**References:** [UserLite](./calckey-js.entities.userlite.md)<!-- -->, [UserDetailed](./calckey-js.entities.userdetailed.md)

View File

@ -1,56 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [UserDetailed](./calckey-js.entities.userdetailed.md)
## entities.UserDetailed type
**Signature:**
```typescript
export declare type UserDetailed = UserLite & {
bannerBlurhash: string | null;
bannerColor: string | null;
bannerUrl: string | null;
birthday: string | null;
createdAt: DateString;
description: string | null;
ffVisibility: "public" | "followers" | "private";
fields: {
name: string;
value: string;
}[];
followersCount: number;
followingCount: number;
hasPendingFollowRequestFromYou: boolean;
hasPendingFollowRequestToYou: boolean;
isAdmin: boolean;
isBlocked: boolean;
isBlocking: boolean;
isBot: boolean;
isCat: boolean;
isFollowed: boolean;
isFollowing: boolean;
isLocked: boolean;
isModerator: boolean;
isMuted: boolean;
isRenoteMuted: boolean;
isSilenced: boolean;
isSuspended: boolean;
lang: string | null;
lastFetchedAt?: DateString;
location: string | null;
notesCount: number;
pinnedNoteIds: ID[];
pinnedNotes: Note[];
pinnedPage: Page | null;
pinnedPageId: string | null;
publicReactions: boolean;
securityKeys: boolean;
twoFactorEnabled: boolean;
updatedAt: DateString | null;
uri: string | null;
url: string | null;
};
```
**References:** [UserLite](./calckey-js.entities.userlite.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [ID](./calckey-js.entities.id.md)<!-- -->, [Note](./calckey-js.entities.note.md)<!-- -->, [Page](./calckey-js.entities.page.md)

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [UserGroup](./calckey-js.entities.usergroup.md)
## entities.UserGroup type
**Signature:**
```typescript
export declare type UserGroup = TODO;
```

View File

@ -1,18 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [UserList](./calckey-js.entities.userlist.md)
## entities.UserList type
**Signature:**
```typescript
export declare type UserList = {
id: ID;
createdAt: DateString;
name: string;
userIds: User["id"][];
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [User](./calckey-js.entities.user.md)

View File

@ -1,35 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [UserLite](./calckey-js.entities.userlite.md)
## entities.UserLite type
**Signature:**
```typescript
export declare type UserLite = {
id: ID;
username: string;
host: string | null;
name: string;
onlineStatus: "online" | "active" | "offline" | "unknown";
avatarUrl: string;
avatarBlurhash: string;
alsoKnownAs: string[];
movedToUri: any;
emojis: {
name: string;
url: string;
}[];
instance?: {
name: Instance["name"];
softwareName: Instance["softwareName"];
softwareVersion: Instance["softwareVersion"];
iconUrl: Instance["iconUrl"];
faviconUrl: Instance["faviconUrl"];
themeColor: Instance["themeColor"];
};
};
```
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [Instance](./calckey-js.entities.instance.md)

View File

@ -1,17 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [entities](./calckey-js.entities.md) &gt; [UserSorting](./calckey-js.entities.usersorting.md)
## entities.UserSorting type
**Signature:**
```typescript
export declare type UserSorting =
| "+follower"
| "-follower"
| "+createdAt"
| "-createdAt"
| "+updatedAt"
| "-updatedAt";
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [ffVisibility](./calckey-js.ffvisibility.md)
## ffVisibility variable
**Signature:**
```typescript
ffVisibility: readonly ["public", "followers", "private"]
```

View File

@ -1,43 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md)
## calckey-js package
## Classes
| Class | Description |
| --- | --- |
| [Stream](./calckey-js.stream.md) | |
## Abstract Classes
| Abstract Class | Description |
| --- | --- |
| [ChannelConnection](./calckey-js.channelconnection.md) | |
## Namespaces
| Namespace | Description |
| --- | --- |
| [api](./calckey-js.api.md) | |
| [entities](./calckey-js.entities.md) | |
## Variables
| Variable | Description |
| --- | --- |
| [ffVisibility](./calckey-js.ffvisibility.md) | |
| [mutedNoteReasons](./calckey-js.mutednotereasons.md) | |
| [noteVisibilities](./calckey-js.notevisibilities.md) | |
| [notificationTypes](./calckey-js.notificationtypes.md) | |
| [permissions](./calckey-js.permissions.md) | |
## Type Aliases
| Type Alias | Description |
| --- | --- |
| [Acct](./calckey-js.acct.md) | |
| [Channels](./calckey-js.channels.md) | |
| [Endpoints](./calckey-js.endpoints.md) | |

View File

@ -1,16 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [mutedNoteReasons](./calckey-js.mutednotereasons.md)
## mutedNoteReasons variable
**Signature:**
```typescript
mutedNoteReasons: readonly [
"word",
"manual",
"spam",
"other",
]
```

View File

@ -1,16 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [noteVisibilities](./calckey-js.notevisibilities.md)
## noteVisibilities variable
**Signature:**
```typescript
noteVisibilities: readonly [
"public",
"home",
"followers",
"specified",
]
```

View File

@ -1,24 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [notificationTypes](./calckey-js.notificationtypes.md)
## notificationTypes variable
**Signature:**
```typescript
notificationTypes: readonly [
"follow",
"mention",
"reply",
"renote",
"quote",
"reaction",
"pollVote",
"pollEnded",
"receiveFollowRequest",
"followRequestAccepted",
"groupInvited",
"app",
]
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [permissions](./calckey-js.permissions.md)
## permissions variable
**Signature:**
```typescript
permissions: string[]
```

View File

@ -1,30 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [(constructor)](./calckey-js.stream._constructor_.md)
## Stream.(constructor)
Constructs a new instance of the `Stream` class
**Signature:**
```typescript
constructor(
origin: string,
user: {
token: string;
} | null,
options?: {
WebSocket?: any;
},
);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| origin | string | |
| user | { token: string; } \| null | |
| options | { WebSocket?: any; } | _(Optional)_ |

View File

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [close](./calckey-js.stream.close.md)
## Stream.close() method
**Signature:**
```typescript
close(): void;
```
**Returns:**
void

View File

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [disconnectToChannel](./calckey-js.stream.disconnecttochannel.md)
## Stream.disconnectToChannel() method
**Signature:**
```typescript
disconnectToChannel(connection: NonSharedConnection): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| connection | NonSharedConnection | |
**Returns:**
void

View File

@ -1,36 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md)
## Stream class
**Signature:**
```typescript
export default class Stream extends EventEmitter<StreamEvents>
```
**Extends:** EventEmitter&lt;StreamEvents&gt;
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(origin, user, options)](./calckey-js.stream._constructor_.md) | | Constructs a new instance of the <code>Stream</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [state](./calckey-js.stream.state.md) | | "initializing" \| "reconnecting" \| "connected" | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [close()](./calckey-js.stream.close.md) | | |
| [disconnectToChannel(connection)](./calckey-js.stream.disconnecttochannel.md) | | |
| [removeSharedConnection(connection)](./calckey-js.stream.removesharedconnection.md) | | |
| [removeSharedConnectionPool(pool)](./calckey-js.stream.removesharedconnectionpool.md) | | |
| [send(typeOrPayload, payload)](./calckey-js.stream.send.md) | | |
| [useChannel(channel, params, name)](./calckey-js.stream.usechannel.md) | | |

View File

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [removeSharedConnection](./calckey-js.stream.removesharedconnection.md)
## Stream.removeSharedConnection() method
**Signature:**
```typescript
removeSharedConnection(connection: SharedConnection): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| connection | SharedConnection | |
**Returns:**
void

View File

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [removeSharedConnectionPool](./calckey-js.stream.removesharedconnectionpool.md)
## Stream.removeSharedConnectionPool() method
**Signature:**
```typescript
removeSharedConnectionPool(pool: Pool): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| pool | Pool | |
**Returns:**
void

View File

@ -1,23 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [send](./calckey-js.stream.send.md)
## Stream.send() method
**Signature:**
```typescript
send(typeOrPayload: any, payload?: any): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| typeOrPayload | any | |
| payload | any | _(Optional)_ |
**Returns:**
void

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [state](./calckey-js.stream.state.md)
## Stream.state property
**Signature:**
```typescript
state: "initializing" | "reconnecting" | "connected";
```

View File

@ -1,28 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [calckey-js](./calckey-js.md) &gt; [Stream](./calckey-js.stream.md) &gt; [useChannel](./calckey-js.stream.usechannel.md)
## Stream.useChannel() method
**Signature:**
```typescript
useChannel<C extends keyof Channels>(
channel: C,
params?: Channels[C]["params"],
name?: string,
): Connection<Channels[C]>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| channel | C | |
| params | [Channels](./calckey-js.channels.md)<!-- -->\[C\]\["params"\] | _(Optional)_ |
| name | string | _(Optional)_ |
**Returns:**
[Connection](./calckey-js.channelconnection.md)<!-- -->&lt;[Channels](./calckey-js.channels.md)<!-- -->\[C\]&gt;

View File

@ -1,12 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md)
## API Reference
## Packages
| Package | Description |
| --- | --- |
| [calckey-js](./calckey-js.md) | |

View File

@ -6,19 +6,13 @@
"types": "./built/index.d.ts",
"scripts": {
"build": "pnpm swc src -d built -D",
"render": "pnpm run build && pnpm run api && pnpm run api-prod && cp temp/calckey-js.api.json etc/ && pnpm run api-doc",
"tsd": "tsc && tsd",
"api": "pnpm api-extractor run --local --verbose",
"api-prod": "pnpm api-extractor run --verbose",
"api-doc": "pnpm api-documenter markdown -i ./etc/"
"tsd": "tsc && tsd"
},
"repository": {
"type": "git",
"url": "https://codeberg.org/calckey/calckey.git"
},
"devDependencies": {
"@microsoft/api-extractor": "^7.36.0",
"@microsoft/api-documenter": "^7.22.21",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.62",
"@types/node": "20.3.1",

View File

@ -97,7 +97,6 @@ export type MeDetailed = UserDetailed & {
hasUnreadSpecifiedNotes: boolean;
hideOnlineStatus: boolean;
injectFeaturedNote: boolean;
integrations: Record<string, any>;
isDeleted: boolean;
isExplorable: boolean;
mutedWords: string[][];
@ -290,9 +289,6 @@ export type LiteInstanceMetadata = {
swPublickey: string | null;
maxNoteTextLength: number;
enableEmail: boolean;
enableTwitterIntegration: boolean;
enableGithubIntegration: boolean;
enableDiscordIntegration: boolean;
enableServiceWorker: boolean;
emojis: CustomEmoji[];
ads: {

View File

@ -14,281 +14,291 @@ const accountData = localStorage.getItem("account");
// TODO: 外部からはreadonlyに
export const $i = accountData
? reactive(JSON.parse(accountData) as Account)
: null;
? reactive(JSON.parse(accountData) as Account)
: null;
export const iAmModerator = $i != null && ($i.isAdmin || $i.isModerator);
export const iAmAdmin = $i?.isAdmin;
export async function signout() {
waiting();
localStorage.removeItem("account");
waiting();
localStorage.removeItem("account");
await removeAccount($i.id);
await removeAccount($i.id);
const accounts = await getAccounts();
const accounts = await getAccounts();
//#region Remove service worker registration
try {
if (navigator.serviceWorker.controller) {
const registration = await navigator.serviceWorker.ready;
const push = await registration.pushManager.getSubscription();
if (push) {
await fetch(`${apiUrl}/sw/unregister`, {
method: "POST",
body: JSON.stringify({
i: $i.token,
endpoint: push.endpoint,
}),
});
}
}
//#region Remove service worker registration
try {
if (navigator.serviceWorker.controller) {
const registration = await navigator.serviceWorker.ready;
const push = await registration.pushManager.getSubscription();
if (push) {
await fetch(`${apiUrl}/sw/unregister`, {
method: "POST",
body: JSON.stringify({
i: $i.token,
endpoint: push.endpoint,
}),
});
}
}
if (accounts.length === 0) {
await navigator.serviceWorker.getRegistrations().then((registrations) => {
return Promise.all(
registrations.map((registration) => registration.unregister()),
);
});
}
} catch (err) {}
//#endregion
if (accounts.length === 0) {
await navigator.serviceWorker
.getRegistrations()
.then((registrations) => {
return Promise.all(
registrations.map((registration) =>
registration.unregister()
)
);
});
}
} catch (err) {}
//#endregion
document.cookie = "igi=; path=/";
document.cookie = "igi=; path=/";
if (accounts.length > 0) login(accounts[0].token);
else unisonReload("/");
if (accounts.length > 0) login(accounts[0].token);
else unisonReload("/");
}
export async function getAccounts(): Promise<
{ id: Account["id"]; token: Account["token"] }[]
{ id: Account["id"]; token: Account["token"] }[]
> {
return (await get("accounts")) || [];
return (await get("accounts")) || [];
}
export async function addAccount(id: Account["id"], token: Account["token"]) {
const accounts = await getAccounts();
if (!accounts.some((x) => x.id === id)) {
await set("accounts", accounts.concat([{ id, token }]));
}
const accounts = await getAccounts();
if (!accounts.some((x) => x.id === id)) {
await set("accounts", accounts.concat([{ id, token }]));
}
}
export async function removeAccount(id: Account["id"]) {
const accounts = await getAccounts();
accounts.splice(
accounts.findIndex((x) => x.id === id),
1,
);
const accounts = await getAccounts();
accounts.splice(
accounts.findIndex((x) => x.id === id),
1
);
if (accounts.length > 0) await set("accounts", accounts);
else await del("accounts");
if (accounts.length > 0) await set("accounts", accounts);
else await del("accounts");
}
function fetchAccount(token: string): Promise<Account> {
return new Promise((done, fail) => {
// Fetch user
fetch(`${apiUrl}/i`, {
method: "POST",
body: JSON.stringify({
i: token,
}),
})
.then((res) => res.json())
.then((res) => {
if (res.error) {
if (res.error.id === "a8c724b3-6e9c-4b46-b1a8-bc3ed6258370") {
showSuspendedDialog().then(() => {
signout();
});
} else {
alert({
type: "error",
title: i18n.ts.failedToFetchAccountInformation,
text: JSON.stringify(res.error),
});
}
} else {
res.token = token;
done(res);
}
})
.catch(fail);
});
return new Promise((done, fail) => {
// Fetch user
fetch(`${apiUrl}/i`, {
method: "POST",
body: JSON.stringify({
i: token,
}),
})
.then((res) => res.json())
.then((res) => {
if (res.error) {
if (
res.error.id === "a8c724b3-6e9c-4b46-b1a8-bc3ed6258370"
) {
showSuspendedDialog().then(() => {
signout();
});
} else {
alert({
type: "error",
title: i18n.ts.failedToFetchAccountInformation,
text: JSON.stringify(res.error),
});
}
} else {
res.token = token;
done(res);
}
})
.catch(fail);
});
}
export function updateAccount(accountData) {
for (const [key, value] of Object.entries(accountData)) {
$i[key] = value;
}
localStorage.setItem("account", JSON.stringify($i));
for (const [key, value] of Object.entries(accountData)) {
$i[key] = value;
}
localStorage.setItem("account", JSON.stringify($i));
}
export function refreshAccount() {
return fetchAccount($i.token).then(updateAccount);
return fetchAccount($i.token).then(updateAccount);
}
export async function login(token: Account["token"], redirect?: string) {
waiting();
if (_DEV_) console.log("logging as token ", token);
const me = await fetchAccount(token);
localStorage.setItem("account", JSON.stringify(me));
document.cookie = `token=${token}; path=/; max-age=31536000`; // bull dashboardの認証とかで使う
await addAccount(me.id, token);
waiting();
if (_DEV_) console.log("logging as token ", token);
const me = await fetchAccount(token);
localStorage.setItem("account", JSON.stringify(me));
document.cookie = `token=${token}; path=/; max-age=31536000`; // bull dashboardの認証とかで使う
await addAccount(me.id, token);
if (redirect) {
// 他のタブは再読み込みするだけ
reloadChannel.postMessage(null);
// このページはredirectで指定された先に移動
location.href = redirect;
return;
}
if (redirect) {
// 他のタブは再読み込みするだけ
reloadChannel.postMessage(null);
// このページはredirectで指定された先に移動
location.href = redirect;
return;
}
unisonReload();
unisonReload();
}
export async function openAccountMenu(
opts: {
includeCurrentAccount?: boolean;
withExtraOperation: boolean;
active?: misskey.entities.UserDetailed["id"];
onChoose?: (account: misskey.entities.UserDetailed) => void;
},
ev: MouseEvent,
opts: {
includeCurrentAccount?: boolean;
withExtraOperation: boolean;
active?: misskey.entities.UserDetailed["id"];
onChoose?: (account: misskey.entities.UserDetailed) => void;
},
ev: MouseEvent
) {
function showSigninDialog() {
popup(
defineAsyncComponent(() => import("@/components/MkSigninDialog.vue")),
{},
{
done: (res) => {
addAccount(res.id, res.i);
success();
},
},
"closed",
);
}
function showSigninDialog() {
popup(
defineAsyncComponent(
() => import("@/components/MkSigninDialog.vue")
),
{},
{
done: (res) => {
addAccount(res.id, res.i);
success();
},
},
"closed"
);
}
function createAccount() {
popup(
defineAsyncComponent(() => import("@/components/MkSignupDialog.vue")),
{},
{
done: (res) => {
addAccount(res.id, res.i);
switchAccountWithToken(res.i);
},
},
"closed",
);
}
function createAccount() {
popup(
defineAsyncComponent(
() => import("@/components/MkSignupDialog.vue")
),
{},
{
done: (res) => {
addAccount(res.id, res.i);
switchAccountWithToken(res.i);
},
},
"closed"
);
}
async function switchAccount(account: misskey.entities.UserDetailed) {
const storedAccounts = await getAccounts();
const token = storedAccounts.find((x) => x.id === account.id).token;
switchAccountWithToken(token);
}
async function switchAccount(account: misskey.entities.UserDetailed) {
const storedAccounts = await getAccounts();
const token = storedAccounts.find((x) => x.id === account.id).token;
switchAccountWithToken(token);
}
function switchAccountWithToken(token: string) {
login(token);
}
function switchAccountWithToken(token: string) {
login(token);
}
const storedAccounts = await getAccounts().then((accounts) =>
accounts.filter((x) => x.id !== $i.id),
);
const accountsPromise = api("users/show", {
userIds: storedAccounts.map((x) => x.id),
});
const storedAccounts = await getAccounts().then((accounts) =>
accounts.filter((x) => x.id !== $i.id)
);
const accountsPromise = api("users/show", {
userIds: storedAccounts.map((x) => x.id),
});
function createItem(account: misskey.entities.UserDetailed) {
return {
type: "user",
user: account,
active: opts.active != null ? opts.active === account.id : false,
action: () => {
if (opts.onChoose) {
opts.onChoose(account);
} else {
switchAccount(account);
}
},
};
}
function createItem(account: misskey.entities.UserDetailed) {
return {
type: "user",
user: account,
active: opts.active != null ? opts.active === account.id : false,
action: () => {
if (opts.onChoose) {
opts.onChoose(account);
} else {
switchAccount(account);
}
},
};
}
const accountItemPromises = storedAccounts.map(
(a) =>
new Promise((res) => {
accountsPromise.then((accounts) => {
const account = accounts.find((x) => x.id === a.id);
if (account == null) return res(null);
res(createItem(account));
});
}),
);
const accountItemPromises = storedAccounts.map(
(a) =>
new Promise((res) => {
accountsPromise.then((accounts) => {
const account = accounts.find((x) => x.id === a.id);
if (account == null) return res(null);
res(createItem(account));
});
})
);
if (opts.withExtraOperation) {
popupMenu(
[
...[
{
type: "link",
text: i18n.ts.profile,
to: `/@${$i.username}`,
avatar: $i,
},
null,
...(opts.includeCurrentAccount ? [createItem($i)] : []),
...accountItemPromises,
{
type: "parent",
icon: "ph-plus ph-bold ph-lg",
text: i18n.ts.addAccount,
children: [
{
text: i18n.ts.existingAccount,
action: () => {
showSigninDialog();
},
},
{
text: i18n.ts.createAccount,
action: () => {
createAccount();
},
},
],
},
{
type: "link",
icon: "ph-users ph-bold ph-lg",
text: i18n.ts.manageAccounts,
to: "/settings/accounts",
},
{
type: "button",
icon: "ph-sign-out ph-bold ph-lg",
text: i18n.ts.logout,
action: () => {
signout();
},
},
],
],
ev.currentTarget ?? ev.target,
{
align: "left",
},
);
} else {
popupMenu(
[
...(opts.includeCurrentAccount ? [createItem($i)] : []),
...accountItemPromises,
],
ev.currentTarget ?? ev.target,
{
align: "left",
},
);
}
if (opts.withExtraOperation) {
popupMenu(
[
...[
{
type: "link",
text: i18n.ts.profile,
to: `/@${$i.username}`,
avatar: $i,
},
null,
...(opts.includeCurrentAccount ? [createItem($i)] : []),
...accountItemPromises,
{
type: "parent",
icon: "ph-plus ph-bold ph-lg",
text: i18n.ts.addAccount,
children: [
{
text: i18n.ts.existingAccount,
action: () => {
showSigninDialog();
},
},
{
text: i18n.ts.createAccount,
action: () => {
createAccount();
},
},
],
},
{
type: "link",
icon: "ph-users ph-bold ph-lg",
text: i18n.ts.manageAccounts,
to: "/settings/accounts",
},
{
type: "button",
icon: "ph-sign-out ph-bold ph-lg",
text: i18n.ts.logout,
action: () => {
signout();
},
},
],
],
ev.currentTarget ?? ev.target,
{
align: "left",
}
);
} else {
popupMenu(
[
...(opts.includeCurrentAccount ? [createItem($i)] : []),
...accountItemPromises,
],
ev.currentTarget ?? ev.target,
{
align: "left",
}
);
}
}

View File

@ -1,67 +1,67 @@
<template>
<div class="bcekxzvu _gap _panel">
<div class="target">
<MkA
v-user-preview="report.targetUserId"
class="info"
:to="`/user-info/${report.targetUserId}`"
>
<MkAvatar
class="avatar"
:user="report.targetUser"
:show-indicator="true"
:disable-link="true"
/>
<div class="names">
<MkUserName class="name" :user="report.targetUser" />
<MkAcct
class="acct"
:user="report.targetUser"
style="display: block"
/>
</div>
</MkA>
<MkKeyValue class="_formBlock">
<template #key>{{ i18n.ts.registeredDate }}</template>
<template #value
>{{
new Date(report.targetUser.createdAt).toLocaleString()
}}
(<MkTime :time="report.targetUser.createdAt" />)</template
>
</MkKeyValue>
</div>
<div class="detail">
<div>
<Mfm :text="report.comment" />
</div>
<hr />
<div>
{{ i18n.ts.reporter }}: <MkAcct :user="report.reporter" />
</div>
<div v-if="report.assignee">
{{ i18n.ts.moderator }}:
<MkAcct :user="report.assignee" />
</div>
<div><MkTime :time="report.createdAt" /></div>
<div class="action">
<MkSwitch
v-model="forward"
:disabled="
report.targetUser.host == null || report.resolved
"
>
{{ i18n.ts.forwardReport }}
<template #caption>{{
i18n.ts.forwardReportIsAnonymous
}}</template>
</MkSwitch>
<MkButton v-if="!report.resolved" primary @click="resolve">{{
i18n.ts.abuseMarkAsResolved
}}</MkButton>
</div>
</div>
</div>
<div class="bcekxzvu _gap _panel">
<div class="target">
<MkA
v-user-preview="report.targetUserId"
class="info"
:to="`/user-info/${report.targetUserId}`"
>
<MkAvatar
class="avatar"
:user="report.targetUser"
:show-indicator="true"
:disable-link="true"
/>
<div class="names">
<MkUserName class="name" :user="report.targetUser" />
<MkAcct
class="acct"
:user="report.targetUser"
style="display: block"
/>
</div>
</MkA>
<MkKeyValue class="_formBlock">
<template #key>{{ i18n.ts.registeredDate }}</template>
<template #value
>{{
new Date(report.targetUser.createdAt).toLocaleString()
}}
(<MkTime :time="report.targetUser.createdAt" />)</template
>
</MkKeyValue>
</div>
<div class="detail">
<div>
<Mfm :text="report.comment" />
</div>
<hr />
<div>
{{ i18n.ts.reporter }}: <MkAcct :user="report.reporter" />
</div>
<div v-if="report.assignee">
{{ i18n.ts.moderator }}:
<MkAcct :user="report.assignee" />
</div>
<div><MkTime :time="report.createdAt" /></div>
<div class="action">
<MkSwitch
v-model="forward"
:disabled="
report.targetUser.host == null || report.resolved
"
>
{{ i18n.ts.forwardReport }}
<template #caption>{{
i18n.ts.forwardReportIsAnonymous
}}</template>
</MkSwitch>
<MkButton v-if="!report.resolved" primary @click="resolve">{{
i18n.ts.abuseMarkAsResolved
}}</MkButton>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
@ -73,75 +73,75 @@ import * as os from "@/os";
import { i18n } from "@/i18n";
const props = defineProps<{
report: any;
report: any;
}>();
const emit = defineEmits<{
(ev: "resolved", reportId: string): void;
(ev: "resolved", reportId: string): void;
}>();
let forward = $ref(props.report.forwarded);
function resolve() {
os.apiWithDialog("admin/resolve-abuse-user-report", {
forward: forward,
reportId: props.report.id,
}).then(() => {
emit("resolved", props.report.id);
});
os.apiWithDialog("admin/resolve-abuse-user-report", {
forward: forward,
reportId: props.report.id,
}).then(() => {
emit("resolved", props.report.id);
});
}
</script>
<style lang="scss" scoped>
.bcekxzvu {
display: flex;
display: flex;
> .target {
width: 35%;
box-sizing: border-box;
text-align: left;
padding: 24px;
border-right: solid 1px var(--divider);
> .target {
width: 35%;
box-sizing: border-box;
text-align: left;
padding: 24px;
border-right: solid 1px var(--divider);
> .info {
display: flex;
box-sizing: border-box;
align-items: center;
padding: 14px;
border-radius: 8px;
--c: rgb(255 196 0 / 15%);
background-image: linear-gradient(
45deg,
var(--c) 16.67%,
transparent 16.67%,
transparent 50%,
var(--c) 50%,
var(--c) 66.67%,
transparent 66.67%,
transparent 100%
);
background-size: 16px 16px;
> .info {
display: flex;
box-sizing: border-box;
align-items: center;
padding: 14px;
border-radius: 8px;
--c: rgb(255 196 0 / 15%);
background-image: linear-gradient(
45deg,
var(--c) 16.67%,
transparent 16.67%,
transparent 50%,
var(--c) 50%,
var(--c) 66.67%,
transparent 66.67%,
transparent 100%
);
background-size: 16px 16px;
> .avatar {
width: 42px;
height: 42px;
}
> .avatar {
width: 42px;
height: 42px;
}
> .names {
margin-left: 0.3em;
padding: 0 8px;
flex: 1;
> .names {
margin-left: 0.3em;
padding: 0 8px;
flex: 1;
> .name {
font-weight: bold;
}
}
}
}
> .name {
font-weight: bold;
}
}
}
}
> .detail {
flex: 1;
padding: 24px;
}
> .detail {
flex: 1;
padding: 24px;
}
}
</style>

View File

@ -1,42 +1,42 @@
<template>
<XWindow
ref="uiWindow"
:initial-width="400"
:initial-height="500"
:can-resize="true"
@closed="emit('closed')"
>
<template #header>
<i
class="ph-warning-circle ph-bold ph-lg"
style="margin-right: 0.5em"
></i>
<I18n :src="i18n.ts.reportAbuseOf" tag="span">
<template #name>
<b><MkAcct :user="user" /></b>
</template>
</I18n>
</template>
<div class="dpvffvvy _monolithic_">
<div class="_section">
<MkTextarea v-model="comment">
<template #label>{{ i18n.ts.details }}</template>
<template #caption>{{
i18n.ts.fillAbuseReportDescription
}}</template>
</MkTextarea>
</div>
<div class="_section">
<MkButton
primary
full
:disabled="comment.length === 0"
@click="send"
>{{ i18n.ts.send }}</MkButton
>
</div>
</div>
</XWindow>
<XWindow
ref="uiWindow"
:initial-width="400"
:initial-height="500"
:can-resize="true"
@closed="emit('closed')"
>
<template #header>
<i
class="ph-warning-circle ph-bold ph-lg"
style="margin-right: 0.5em"
></i>
<I18n :src="i18n.ts.reportAbuseOf" tag="span">
<template #name>
<b><MkAcct :user="user" /></b>
</template>
</I18n>
</template>
<div class="dpvffvvy _monolithic_">
<div class="_section">
<MkTextarea v-model="comment">
<template #label>{{ i18n.ts.details }}</template>
<template #caption>{{
i18n.ts.fillAbuseReportDescription
}}</template>
</MkTextarea>
</div>
<div class="_section">
<MkButton
primary
full
:disabled="comment.length === 0"
@click="send"
>{{ i18n.ts.send }}</MkButton
>
</div>
</div>
</XWindow>
</template>
<script setup lang="ts">
@ -49,38 +49,38 @@ import * as os from "@/os";
import { i18n } from "@/i18n";
const props = defineProps<{
user: Misskey.entities.User;
initialComment?: string;
user: Misskey.entities.User;
initialComment?: string;
}>();
const emit = defineEmits<{
(ev: "closed"): void;
(ev: "closed"): void;
}>();
const uiWindow = ref<InstanceType<typeof XWindow>>();
const comment = ref(props.initialComment || "");
function send() {
os.apiWithDialog(
"users/report-abuse",
{
userId: props.user.id,
comment: comment.value,
},
undefined
).then((res) => {
os.alert({
type: "success",
text: i18n.ts.abuseReported,
});
uiWindow.value?.close();
emit("closed");
});
os.apiWithDialog(
"users/report-abuse",
{
userId: props.user.id,
comment: comment.value,
},
undefined
).then((res) => {
os.alert({
type: "success",
text: i18n.ts.abuseReported,
});
uiWindow.value?.close();
emit("closed");
});
}
</script>
<style lang="scss" scoped>
.dpvffvvy {
--root-margin: 16px;
--root-margin: 16px;
}
</style>

View File

@ -1,62 +1,62 @@
<template>
<svg class="mbcofsoe" viewBox="0 0 10 10" preserveAspectRatio="none">
<template v-if="props.graduations === 'dots'">
<circle
v-for="(angle, i) in graduationsMajor"
:cx="5 + Math.sin(angle) * (5 - graduationsPadding)"
:cy="5 - Math.cos(angle) * (5 - graduationsPadding)"
:r="0.125"
:fill="
(props.twentyfour ? h : h % 12) === i
? nowColor
: majorGraduationColor
"
:opacity="
!props.fadeGraduations ||
(props.twentyfour ? h : h % 12) === i
? 1
: Math.max(
0,
1 -
angleDiff(hAngle, angle) / Math.PI -
numbersOpacityFactor
)
"
/>
</template>
<template v-else-if="props.graduations === 'numbers'">
<text
v-for="(angle, i) in texts"
:x="5 + Math.sin(angle) * (5 - textsPadding)"
:y="5 - Math.cos(angle) * (5 - textsPadding)"
text-anchor="middle"
dominant-baseline="middle"
:font-size="(props.twentyfour ? h : h % 12) === i ? 1 : 0.7"
:font-weight="
(props.twentyfour ? h : h % 12) === i ? 'bold' : 'normal'
"
:fill="
(props.twentyfour ? h : h % 12) === i
? nowColor
: 'currentColor'
"
:opacity="
!props.fadeGraduations ||
(props.twentyfour ? h : h % 12) === i
? 1
: Math.max(
0,
1 -
angleDiff(hAngle, angle) / Math.PI -
numbersOpacityFactor
)
"
>
{{ i === 0 ? (props.twentyfour ? "24" : "12") : i }}
</text>
</template>
<svg class="mbcofsoe" viewBox="0 0 10 10" preserveAspectRatio="none">
<template v-if="props.graduations === 'dots'">
<circle
v-for="(angle, i) in graduationsMajor"
:cx="5 + Math.sin(angle) * (5 - graduationsPadding)"
:cy="5 - Math.cos(angle) * (5 - graduationsPadding)"
:r="0.125"
:fill="
(props.twentyfour ? h : h % 12) === i
? nowColor
: majorGraduationColor
"
:opacity="
!props.fadeGraduations ||
(props.twentyfour ? h : h % 12) === i
? 1
: Math.max(
0,
1 -
angleDiff(hAngle, angle) / Math.PI -
numbersOpacityFactor
)
"
/>
</template>
<template v-else-if="props.graduations === 'numbers'">
<text
v-for="(angle, i) in texts"
:x="5 + Math.sin(angle) * (5 - textsPadding)"
:y="5 - Math.cos(angle) * (5 - textsPadding)"
text-anchor="middle"
dominant-baseline="middle"
:font-size="(props.twentyfour ? h : h % 12) === i ? 1 : 0.7"
:font-weight="
(props.twentyfour ? h : h % 12) === i ? 'bold' : 'normal'
"
:fill="
(props.twentyfour ? h : h % 12) === i
? nowColor
: 'currentColor'
"
:opacity="
!props.fadeGraduations ||
(props.twentyfour ? h : h % 12) === i
? 1
: Math.max(
0,
1 -
angleDiff(hAngle, angle) / Math.PI -
numbersOpacityFactor
)
"
>
{{ i === 0 ? (props.twentyfour ? "24" : "12") : i }}
</text>
</template>
<!--
<!--
<line
:x1="5 - (Math.sin(sAngle) * (sHandLengthRatio * handsTailLength))"
:y1="5 + (Math.cos(sAngle) * (sHandLengthRatio * handsTailLength))"
@ -68,61 +68,61 @@
/>
-->
<line
class="s"
:class="{
animate: !disableSAnimate && sAnimation !== 'none',
elastic: sAnimation === 'elastic',
easeOut: sAnimation === 'easeOut',
}"
:x1="5 - 0 * (sHandLengthRatio * handsTailLength)"
:y1="5 + 1 * (sHandLengthRatio * handsTailLength)"
:x2="5 + 0 * (sHandLengthRatio * 5 - handsPadding)"
:y2="5 - 1 * (sHandLengthRatio * 5 - handsPadding)"
:stroke="sHandColor"
:stroke-width="thickness / 2"
:style="`transform: rotateZ(${sAngle}rad)`"
stroke-linecap="round"
/>
<line
class="s"
:class="{
animate: !disableSAnimate && sAnimation !== 'none',
elastic: sAnimation === 'elastic',
easeOut: sAnimation === 'easeOut',
}"
:x1="5 - 0 * (sHandLengthRatio * handsTailLength)"
:y1="5 + 1 * (sHandLengthRatio * handsTailLength)"
:x2="5 + 0 * (sHandLengthRatio * 5 - handsPadding)"
:y2="5 - 1 * (sHandLengthRatio * 5 - handsPadding)"
:stroke="sHandColor"
:stroke-width="thickness / 2"
:style="`transform: rotateZ(${sAngle}rad)`"
stroke-linecap="round"
/>
<line
:x1="5 - Math.sin(mAngle) * (mHandLengthRatio * handsTailLength)"
:y1="5 + Math.cos(mAngle) * (mHandLengthRatio * handsTailLength)"
:x2="5 + Math.sin(mAngle) * (mHandLengthRatio * 5 - handsPadding)"
:y2="5 - Math.cos(mAngle) * (mHandLengthRatio * 5 - handsPadding)"
:stroke="mHandColor"
:stroke-width="thickness"
stroke-linecap="round"
/>
<line
:x1="5 - Math.sin(mAngle) * (mHandLengthRatio * handsTailLength)"
:y1="5 + Math.cos(mAngle) * (mHandLengthRatio * handsTailLength)"
:x2="5 + Math.sin(mAngle) * (mHandLengthRatio * 5 - handsPadding)"
:y2="5 - Math.cos(mAngle) * (mHandLengthRatio * 5 - handsPadding)"
:stroke="mHandColor"
:stroke-width="thickness"
stroke-linecap="round"
/>
<line
:x1="5 - Math.sin(hAngle) * (hHandLengthRatio * handsTailLength)"
:y1="5 + Math.cos(hAngle) * (hHandLengthRatio * handsTailLength)"
:x2="5 + Math.sin(hAngle) * (hHandLengthRatio * 5 - handsPadding)"
:y2="5 - Math.cos(hAngle) * (hHandLengthRatio * 5 - handsPadding)"
:stroke="hHandColor"
:stroke-width="thickness"
stroke-linecap="round"
/>
</svg>
<line
:x1="5 - Math.sin(hAngle) * (hHandLengthRatio * handsTailLength)"
:y1="5 + Math.cos(hAngle) * (hHandLengthRatio * handsTailLength)"
:x2="5 + Math.sin(hAngle) * (hHandLengthRatio * 5 - handsPadding)"
:y2="5 - Math.cos(hAngle) * (hHandLengthRatio * 5 - handsPadding)"
:stroke="hHandColor"
:stroke-width="thickness"
stroke-linecap="round"
/>
</svg>
</template>
<script lang="ts" setup>
import {
ref,
computed,
onMounted,
onBeforeUnmount,
shallowRef,
nextTick,
ref,
computed,
onMounted,
onBeforeUnmount,
shallowRef,
nextTick,
} from "vue";
import tinycolor from "tinycolor2";
import { globalEvents } from "@/events.js";
// https://stackoverflow.com/questions/1878907/how-can-i-find-the-difference-between-two-angles
const angleDiff = (a: number, b: number) => {
const x = Math.abs(a - b);
return Math.abs(((x + Math.PI) % (Math.PI * 2)) - Math.PI);
const x = Math.abs(a - b);
return Math.abs(((x + Math.PI) % (Math.PI * 2)) - Math.PI);
};
const graduationsPadding = 0.5;
@ -135,42 +135,42 @@ const sHandLengthRatio = 1;
const numbersOpacityFactor = 0.35;
const props = withDefaults(
defineProps<{
thickness?: number;
offset?: number;
twentyfour?: boolean;
graduations?: "none" | "dots" | "numbers";
fadeGraduations?: boolean;
sAnimation?: "none" | "elastic" | "easeOut";
}>(),
{
numbers: false,
thickness: 0.1,
offset: 0 - new Date().getTimezoneOffset(),
twentyfour: false,
graduations: "dots",
fadeGraduations: true,
sAnimation: "elastic",
}
defineProps<{
thickness?: number;
offset?: number;
twentyfour?: boolean;
graduations?: "none" | "dots" | "numbers";
fadeGraduations?: boolean;
sAnimation?: "none" | "elastic" | "easeOut";
}>(),
{
numbers: false,
thickness: 0.1,
offset: 0 - new Date().getTimezoneOffset(),
twentyfour: false,
graduations: "dots",
fadeGraduations: true,
sAnimation: "elastic",
}
);
const graduationsMajor = computed(() => {
const angles: number[] = [];
const times = props.twentyfour ? 24 : 12;
for (let i = 0; i < times; i++) {
const angle = (Math.PI * i) / (times / 2);
angles.push(angle);
}
return angles;
const angles: number[] = [];
const times = props.twentyfour ? 24 : 12;
for (let i = 0; i < times; i++) {
const angle = (Math.PI * i) / (times / 2);
angles.push(angle);
}
return angles;
});
const texts = computed(() => {
const angles: number[] = [];
const times = props.twentyfour ? 24 : 12;
for (let i = 0; i < times; i++) {
const angle = (Math.PI * i) / (times / 2);
angles.push(angle);
}
return angles;
const angles: number[] = [];
const times = props.twentyfour ? 24 : 12;
for (let i = 0; i < times; i++) {
const angle = (Math.PI * i) / (times / 2);
angles.push(angle);
}
return angles;
});
let enabled = true;
@ -190,91 +190,91 @@ let disableSAnimate = $ref(false);
let sOneRound = false;
function tick() {
const now = new Date();
now.setMinutes(
now.getMinutes() + (new Date().getTimezoneOffset() + props.offset)
);
s = now.getSeconds();
m = now.getMinutes();
h = now.getHours();
hAngle =
(Math.PI * ((h % (props.twentyfour ? 24 : 12)) + (m + s / 60) / 60)) /
(props.twentyfour ? 12 : 6);
mAngle = (Math.PI * (m + s / 60)) / 30;
if (sOneRound) {
// (59->0)
sAngle = (Math.PI * 60) / 30;
window.setTimeout(() => {
disableSAnimate = true;
window.setTimeout(() => {
sAngle = 0;
window.setTimeout(() => {
disableSAnimate = false;
}, 100);
}, 100);
}, 700);
} else {
sAngle = (Math.PI * s) / 30;
}
sOneRound = s === 59;
const now = new Date();
now.setMinutes(
now.getMinutes() + (new Date().getTimezoneOffset() + props.offset)
);
s = now.getSeconds();
m = now.getMinutes();
h = now.getHours();
hAngle =
(Math.PI * ((h % (props.twentyfour ? 24 : 12)) + (m + s / 60) / 60)) /
(props.twentyfour ? 12 : 6);
mAngle = (Math.PI * (m + s / 60)) / 30;
if (sOneRound) {
// (59->0)
sAngle = (Math.PI * 60) / 30;
window.setTimeout(() => {
disableSAnimate = true;
window.setTimeout(() => {
sAngle = 0;
window.setTimeout(() => {
disableSAnimate = false;
}, 100);
}, 100);
}, 700);
} else {
sAngle = (Math.PI * s) / 30;
}
sOneRound = s === 59;
}
tick();
function calcColors() {
const computedStyle = getComputedStyle(document.documentElement);
const dark = tinycolor(computedStyle.getPropertyValue("--bg")).isDark();
const accent = tinycolor(
computedStyle.getPropertyValue("--accent")
).toHexString();
majorGraduationColor = dark
? "rgba(255, 255, 255, 0.3)"
: "rgba(0, 0, 0, 0.3)";
//minorGraduationColor = dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
sHandColor = dark ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.3)";
mHandColor = tinycolor(
computedStyle.getPropertyValue("--fg")
).toHexString();
hHandColor = accent;
nowColor = accent;
const computedStyle = getComputedStyle(document.documentElement);
const dark = tinycolor(computedStyle.getPropertyValue("--bg")).isDark();
const accent = tinycolor(
computedStyle.getPropertyValue("--accent")
).toHexString();
majorGraduationColor = dark
? "rgba(255, 255, 255, 0.3)"
: "rgba(0, 0, 0, 0.3)";
//minorGraduationColor = dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
sHandColor = dark ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.3)";
mHandColor = tinycolor(
computedStyle.getPropertyValue("--fg")
).toHexString();
hHandColor = accent;
nowColor = accent;
}
calcColors();
onMounted(() => {
const update = () => {
if (enabled) {
tick();
window.setTimeout(update, 1000);
}
};
update();
const update = () => {
if (enabled) {
tick();
window.setTimeout(update, 1000);
}
};
update();
globalEvents.on("themeChanged", calcColors);
globalEvents.on("themeChanged", calcColors);
});
onBeforeUnmount(() => {
enabled = false;
enabled = false;
globalEvents.off("themeChanged", calcColors);
globalEvents.off("themeChanged", calcColors);
});
</script>
<style lang="scss" scoped>
.mbcofsoe {
display: block;
display: block;
> .s {
will-change: transform;
transform-origin: 50% 50%;
> .s {
will-change: transform;
transform-origin: 50% 50%;
&.animate.elastic {
transition: transform 0.2s cubic-bezier(0.4, 2.08, 0.55, 0.44);
}
&.animate.elastic {
transition: transform 0.2s cubic-bezier(0.4, 2.08, 0.55, 0.44);
}
&.animate.easeOut {
transition: transform 0.7s cubic-bezier(0, 0.7, 0.3, 1);
}
}
&.animate.easeOut {
transition: transform 0.7s cubic-bezier(0, 0.7, 0.3, 1);
}
}
}
</style>

View File

@ -1,96 +1,96 @@
<template>
<div
ref="rootEl"
class="swhvrteh _popup _shadow"
:style="{ zIndex }"
@contextmenu.prevent="() => {}"
>
<ol v-if="type === 'user'" ref="suggests" class="users">
<li
v-for="user in users"
tabindex="-1"
class="user"
@click="complete(type, user)"
@keydown="onKeydown"
>
<img class="avatar" :src="user.avatarUrl" />
<span class="name">
<MkUserName :key="user.id" :user="user" />
</span>
<span class="username">@{{ acct(user) }}</span>
</li>
<li
tabindex="-1"
class="choose"
@click="chooseUser()"
@keydown="onKeydown"
>
{{ i18n.ts.selectUser }}
</li>
</ol>
<ol v-else-if="hashtags.length > 0" ref="suggests" class="hashtags">
<li
v-for="hashtag in hashtags"
tabindex="-1"
@click="complete(type, hashtag)"
@keydown="onKeydown"
>
<span class="name">{{ hashtag }}</span>
</li>
</ol>
<ol v-else-if="emojis.length > 0" ref="suggests" class="emojis">
<li
v-for="emoji in emojis"
tabindex="-1"
@click="complete(type, emoji.emoji)"
@keydown="onKeydown"
>
<span v-if="emoji.isCustomEmoji" class="emoji"
><img
:src="
defaultStore.state.disableShowingAnimatedImages
? getStaticImageUrl(emoji.url)
: emoji.url
"
:alt="emoji.emoji"
/></span>
<span
v-else-if="!defaultStore.state.useOsNativeEmojis"
class="emoji"
><img :src="emoji.url" :alt="emoji.emoji"
/></span>
<span v-else class="emoji">{{ emoji.emoji }}</span>
<span
class="name"
v-html="emoji.name.replace(q, `<b>${q}</b>`)"
></span>
<span v-if="emoji.aliasOf" class="alias"
>({{ emoji.aliasOf }})</span
>
</li>
</ol>
<ol v-else-if="mfmTags.length > 0" ref="suggests" class="mfmTags">
<li
v-for="tag in mfmTags"
tabindex="-1"
@click="complete(type, tag)"
@keydown="onKeydown"
>
<span class="tag">{{ tag }}</span>
</li>
</ol>
</div>
<div
ref="rootEl"
class="swhvrteh _popup _shadow"
:style="{ zIndex }"
@contextmenu.prevent="() => {}"
>
<ol v-if="type === 'user'" ref="suggests" class="users">
<li
v-for="user in users"
tabindex="-1"
class="user"
@click="complete(type, user)"
@keydown="onKeydown"
>
<img class="avatar" :src="user.avatarUrl" />
<span class="name">
<MkUserName :key="user.id" :user="user" />
</span>
<span class="username">@{{ acct(user) }}</span>
</li>
<li
tabindex="-1"
class="choose"
@click="chooseUser()"
@keydown="onKeydown"
>
{{ i18n.ts.selectUser }}
</li>
</ol>
<ol v-else-if="hashtags.length > 0" ref="suggests" class="hashtags">
<li
v-for="hashtag in hashtags"
tabindex="-1"
@click="complete(type, hashtag)"
@keydown="onKeydown"
>
<span class="name">{{ hashtag }}</span>
</li>
</ol>
<ol v-else-if="emojis.length > 0" ref="suggests" class="emojis">
<li
v-for="emoji in emojis"
tabindex="-1"
@click="complete(type, emoji.emoji)"
@keydown="onKeydown"
>
<span v-if="emoji.isCustomEmoji" class="emoji"
><img
:src="
defaultStore.state.disableShowingAnimatedImages
? getStaticImageUrl(emoji.url)
: emoji.url
"
:alt="emoji.emoji"
/></span>
<span
v-else-if="!defaultStore.state.useOsNativeEmojis"
class="emoji"
><img :src="emoji.url" :alt="emoji.emoji"
/></span>
<span v-else class="emoji">{{ emoji.emoji }}</span>
<span
class="name"
v-html="emoji.name.replace(q, `<b>${q}</b>`)"
></span>
<span v-if="emoji.aliasOf" class="alias"
>({{ emoji.aliasOf }})</span
>
</li>
</ol>
<ol v-else-if="mfmTags.length > 0" ref="suggests" class="mfmTags">
<li
v-for="tag in mfmTags"
tabindex="-1"
@click="complete(type, tag)"
@keydown="onKeydown"
>
<span class="tag">{{ tag }}</span>
</li>
</ol>
</div>
</template>
<script lang="ts">
import {
markRaw,
ref,
onUpdated,
onMounted,
onBeforeUnmount,
nextTick,
watch,
markRaw,
ref,
onUpdated,
onMounted,
onBeforeUnmount,
nextTick,
watch,
} from "vue";
import contains from "@/scripts/contains";
import { char2filePath } from "@/scripts/twemoji-base";
@ -104,38 +104,38 @@ import { instance } from "@/instance";
import { i18n } from "@/i18n";
type EmojiDef = {
emoji: string;
name: string;
aliasOf?: string;
url?: string;
isCustomEmoji?: boolean;
emoji: string;
name: string;
aliasOf?: string;
url?: string;
isCustomEmoji?: boolean;
};
const lib = emojilist.filter((x) => x.category !== "flags");
for (const emoji of lib) {
if (emoji.skin_tone_support) {
emoji.emoji = addSkinTone(emoji.emoji);
}
if (emoji.skin_tone_support) {
emoji.emoji = addSkinTone(emoji.emoji);
}
}
const emjdb: EmojiDef[] = lib.map((x) => ({
emoji: x.emoji,
name: x.slug,
url: char2filePath(x.emoji),
emoji: x.emoji,
name: x.slug,
url: char2filePath(x.emoji),
}));
for (const x of lib) {
if (x.keywords) {
for (const k of x.keywords) {
emjdb.push({
emoji: x.emoji,
name: k,
aliasOf: x.slug,
url: char2filePath(x.emoji),
});
}
}
if (x.keywords) {
for (const k of x.keywords) {
emjdb.push({
emoji: x.emoji,
name: k,
aliasOf: x.slug,
url: char2filePath(x.emoji),
});
}
}
}
emjdb.sort((a, b) => a.name.length - b.name.length);
@ -145,24 +145,24 @@ const customEmojis = instance.emojis;
const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) {
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true,
});
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true,
});
if (x.aliases) {
for (const alias of x.aliases) {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true,
});
}
}
if (x.aliases) {
for (const alias of x.aliases) {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true,
});
}
}
}
emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
@ -171,26 +171,26 @@ const emojiDb = markRaw(emojiDefinitions.concat(emjdb));
//#endregion
export default {
emojiDb,
emojiDefinitions,
emojilist,
customEmojis,
emojiDb,
emojiDefinitions,
emojilist,
customEmojis,
};
</script>
<script lang="ts" setup>
const props = defineProps<{
type: string;
q: string | null;
textarea: HTMLTextAreaElement;
close: () => void;
x: number;
y: number;
type: string;
q: string | null;
textarea: HTMLTextAreaElement;
close: () => void;
x: number;
y: number;
}>();
const emit = defineEmits<{
(event: "done", value: { type: string; value: any }): void;
(event: "closed"): void;
(event: "done", value: { type: string; value: any }): void;
(event: "closed"): void;
}>();
const suggests = ref<Element>();
@ -206,359 +206,359 @@ const select = ref(-1);
const zIndex = os.claimZIndex("high");
function complete(type: string, value: any) {
emit("done", { type, value });
emit("closed");
if (type === "emoji") {
let recents = defaultStore.state.recentlyUsedEmojis;
recents = recents.filter((emoji: any) => emoji !== value);
recents.unshift(value);
defaultStore.set("recentlyUsedEmojis", recents.splice(0, 32));
}
emit("done", { type, value });
emit("closed");
if (type === "emoji") {
let recents = defaultStore.state.recentlyUsedEmojis;
recents = recents.filter((emoji: any) => emoji !== value);
recents.unshift(value);
defaultStore.set("recentlyUsedEmojis", recents.splice(0, 32));
}
}
function setPosition() {
if (!rootEl.value) return;
if (props.x + rootEl.value.offsetWidth > window.innerWidth) {
rootEl.value.style.left =
window.innerWidth - rootEl.value.offsetWidth + "px";
} else {
rootEl.value.style.left = `${props.x}px`;
}
if (props.y + rootEl.value.offsetHeight > window.innerHeight) {
rootEl.value.style.top = props.y - rootEl.value.offsetHeight + "px";
rootEl.value.style.marginTop = "0";
} else {
rootEl.value.style.top = props.y + "px";
rootEl.value.style.marginTop = "calc(1em + 8px)";
}
if (!rootEl.value) return;
if (props.x + rootEl.value.offsetWidth > window.innerWidth) {
rootEl.value.style.left =
window.innerWidth - rootEl.value.offsetWidth + "px";
} else {
rootEl.value.style.left = `${props.x}px`;
}
if (props.y + rootEl.value.offsetHeight > window.innerHeight) {
rootEl.value.style.top = props.y - rootEl.value.offsetHeight + "px";
rootEl.value.style.marginTop = "0";
} else {
rootEl.value.style.top = props.y + "px";
rootEl.value.style.marginTop = "calc(1em + 8px)";
}
}
function exec() {
select.value = -1;
if (suggests.value) {
for (const el of Array.from(items.value)) {
el.removeAttribute("data-selected");
}
}
if (props.type === "user") {
if (!props.q) {
users.value = [];
fetching.value = false;
return;
}
select.value = -1;
if (suggests.value) {
for (const el of Array.from(items.value)) {
el.removeAttribute("data-selected");
}
}
if (props.type === "user") {
if (!props.q) {
users.value = [];
fetching.value = false;
return;
}
const cacheKey = `autocomplete:user:${props.q}`;
const cache = sessionStorage.getItem(cacheKey);
const cacheKey = `autocomplete:user:${props.q}`;
const cache = sessionStorage.getItem(cacheKey);
if (cache) {
users.value = JSON.parse(cache);
fetching.value = false;
} else {
os.api("users/search-by-username-and-host", {
username: props.q,
limit: 10,
detail: false,
}).then((searchedUsers) => {
users.value = searchedUsers as any[];
fetching.value = false;
//
sessionStorage.setItem(cacheKey, JSON.stringify(searchedUsers));
});
}
} else if (props.type === "hashtag") {
if (!props.q || props.q === "") {
hashtags.value = JSON.parse(
localStorage.getItem("hashtags") || "[]"
);
fetching.value = false;
} else {
const cacheKey = `autocomplete:hashtag:${props.q}`;
const cache = sessionStorage.getItem(cacheKey);
if (cache) {
const hashtags = JSON.parse(cache);
hashtags.value = hashtags;
fetching.value = false;
} else {
os.api("hashtags/search", {
query: props.q,
limit: 30,
}).then((searchedHashtags) => {
hashtags.value = searchedHashtags as any[];
fetching.value = false;
//
sessionStorage.setItem(
cacheKey,
JSON.stringify(searchedHashtags)
);
});
}
}
} else if (props.type === "emoji") {
if (!props.q || props.q === "") {
// 使
emojis.value = defaultStore.state.recentlyUsedEmojis
.map((emoji) =>
emojiDb.find((dbEmoji) => dbEmoji.emoji === emoji)
)
.filter((x) => x) as EmojiDef[];
return;
}
if (cache) {
users.value = JSON.parse(cache);
fetching.value = false;
} else {
os.api("users/search-by-username-and-host", {
username: props.q,
limit: 10,
detail: false,
}).then((searchedUsers) => {
users.value = searchedUsers as any[];
fetching.value = false;
//
sessionStorage.setItem(cacheKey, JSON.stringify(searchedUsers));
});
}
} else if (props.type === "hashtag") {
if (!props.q || props.q === "") {
hashtags.value = JSON.parse(
localStorage.getItem("hashtags") || "[]"
);
fetching.value = false;
} else {
const cacheKey = `autocomplete:hashtag:${props.q}`;
const cache = sessionStorage.getItem(cacheKey);
if (cache) {
const hashtags = JSON.parse(cache);
hashtags.value = hashtags;
fetching.value = false;
} else {
os.api("hashtags/search", {
query: props.q,
limit: 30,
}).then((searchedHashtags) => {
hashtags.value = searchedHashtags as any[];
fetching.value = false;
//
sessionStorage.setItem(
cacheKey,
JSON.stringify(searchedHashtags)
);
});
}
}
} else if (props.type === "emoji") {
if (!props.q || props.q === "") {
// 使
emojis.value = defaultStore.state.recentlyUsedEmojis
.map((emoji) =>
emojiDb.find((dbEmoji) => dbEmoji.emoji === emoji)
)
.filter((x) => x) as EmojiDef[];
return;
}
const matched: EmojiDef[] = [];
const max = 30;
const matched: EmojiDef[] = [];
const max = 30;
emojiDb.some((x) => {
if (
x.name.startsWith(props.q ?? "") &&
!x.aliasOf &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
emojiDb.some((x) => {
if (
x.name.startsWith(props.q ?? "") &&
!x.aliasOf &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
if (matched.length < max) {
emojiDb.some((x) => {
if (
x.name.startsWith(props.q ?? "") &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
}
if (matched.length < max) {
emojiDb.some((x) => {
if (
x.name.startsWith(props.q ?? "") &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
}
if (matched.length < max) {
emojiDb.some((x) => {
if (
x.name.includes(props.q ?? "") &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
}
if (matched.length < max) {
emojiDb.some((x) => {
if (
x.name.includes(props.q ?? "") &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
}
emojis.value = matched;
} else if (props.type === "mfmTag") {
if (!props.q || props.q === "") {
mfmTags.value = MFM_TAGS;
return;
}
emojis.value = matched;
} else if (props.type === "mfmTag") {
if (!props.q || props.q === "") {
mfmTags.value = MFM_TAGS;
return;
}
mfmTags.value = MFM_TAGS.filter((tag) => tag.startsWith(props.q ?? ""));
}
mfmTags.value = MFM_TAGS.filter((tag) => tag.startsWith(props.q ?? ""));
}
}
function onMousedown(event: Event) {
if (!contains(rootEl.value, event.target) && rootEl.value !== event.target)
props.close();
if (!contains(rootEl.value, event.target) && rootEl.value !== event.target)
props.close();
}
function onKeydown(event: KeyboardEvent) {
const cancel = () => {
event.preventDefault();
event.stopPropagation();
};
const cancel = () => {
event.preventDefault();
event.stopPropagation();
};
switch (event.key) {
case "Enter":
if (select.value !== -1) {
cancel();
(items.value[select.value] as any).click();
} else {
props.close();
}
break;
switch (event.key) {
case "Enter":
if (select.value !== -1) {
cancel();
(items.value[select.value] as any).click();
} else {
props.close();
}
break;
case "Escape":
cancel();
props.close();
break;
case "Escape":
cancel();
props.close();
break;
case "ArrowUp":
if (select.value !== -1) {
cancel();
selectPrev();
} else {
props.close();
}
break;
case "ArrowUp":
if (select.value !== -1) {
cancel();
selectPrev();
} else {
props.close();
}
break;
case "Tab":
case "ArrowDown":
cancel();
selectNext();
break;
case "Tab":
case "ArrowDown":
cancel();
selectNext();
break;
default:
event.stopPropagation();
props.textarea.focus();
}
default:
event.stopPropagation();
props.textarea.focus();
}
}
function selectNext() {
if (++select.value >= items.value.length) select.value = 0;
if (items.value.length === 0) select.value = -1;
applySelect();
if (++select.value >= items.value.length) select.value = 0;
if (items.value.length === 0) select.value = -1;
applySelect();
}
function selectPrev() {
if (--select.value < 0) select.value = items.value.length - 1;
applySelect();
if (--select.value < 0) select.value = items.value.length - 1;
applySelect();
}
function applySelect() {
for (const el of Array.from(items.value)) {
el.removeAttribute("data-selected");
}
for (const el of Array.from(items.value)) {
el.removeAttribute("data-selected");
}
if (select.value !== -1) {
items.value[select.value].setAttribute("data-selected", "true");
(items.value[select.value] as any).focus();
}
if (select.value !== -1) {
items.value[select.value].setAttribute("data-selected", "true");
(items.value[select.value] as any).focus();
}
}
function chooseUser() {
props.close();
os.selectUser().then((user) => {
complete("user", user);
props.textarea.focus();
});
props.close();
os.selectUser().then((user) => {
complete("user", user);
props.textarea.focus();
});
}
onUpdated(() => {
setPosition();
items.value = suggests.value?.children ?? [];
setPosition();
items.value = suggests.value?.children ?? [];
});
onMounted(() => {
setPosition();
setPosition();
props.textarea.addEventListener("keydown", onKeydown);
props.textarea.addEventListener("keydown", onKeydown);
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.addEventListener("mousedown", onMousedown);
}
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.addEventListener("mousedown", onMousedown);
}
nextTick(() => {
exec();
nextTick(() => {
exec();
watch(
() => props.q,
() => {
nextTick(() => {
exec();
});
}
);
});
watch(
() => props.q,
() => {
nextTick(() => {
exec();
});
}
);
});
});
onBeforeUnmount(() => {
props.textarea.removeEventListener("keydown", onKeydown);
props.textarea.removeEventListener("keydown", onKeydown);
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.removeEventListener("mousedown", onMousedown);
}
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.removeEventListener("mousedown", onMousedown);
}
});
</script>
<style lang="scss" scoped>
.swhvrteh {
position: fixed;
max-width: 100%;
margin-top: calc(1em + 8px);
overflow: hidden;
transition: top 0.1s ease, left 0.1s ease;
position: fixed;
max-width: 100%;
margin-top: calc(1em + 8px);
overflow: hidden;
transition: top 0.1s ease, left 0.1s ease;
> ol {
display: block;
margin: 0;
padding: 4px 0;
max-height: 190px;
max-width: 500px;
overflow: auto;
list-style: none;
> ol {
display: block;
margin: 0;
padding: 4px 0;
max-height: 190px;
max-width: 500px;
overflow: auto;
list-style: none;
> li {
display: flex;
align-items: center;
padding: 4px 12px;
white-space: nowrap;
overflow: hidden;
font-size: 0.9em;
cursor: default;
> li {
display: flex;
align-items: center;
padding: 4px 12px;
white-space: nowrap;
overflow: hidden;
font-size: 0.9em;
cursor: default;
&,
* {
user-select: none;
}
&,
* {
user-select: none;
}
* {
overflow: hidden;
text-overflow: ellipsis;
}
* {
overflow: hidden;
text-overflow: ellipsis;
}
&:hover {
background: var(--X3);
}
&:hover {
background: var(--X3);
}
&[data-selected="true"] {
background: var(--accent);
&[data-selected="true"] {
background: var(--accent);
&,
* {
color: #fff !important;
}
}
&,
* {
color: #fff !important;
}
}
&:active {
background: var(--accentDarken);
&:active {
background: var(--accentDarken);
&,
* {
color: #fff !important;
}
}
}
}
&,
* {
color: #fff !important;
}
}
}
}
> .users > li {
.avatar {
min-width: 28px;
min-height: 28px;
max-width: 28px;
max-height: 28px;
margin: 0 8px 0 0;
border-radius: 100%;
}
> .users > li {
.avatar {
min-width: 28px;
min-height: 28px;
max-width: 28px;
max-height: 28px;
margin: 0 8px 0 0;
border-radius: 100%;
}
.name {
margin: 0 8px 0 0;
}
}
.name {
margin: 0 8px 0 0;
}
}
> .emojis > li {
.emoji {
display: inline-block;
margin: 0 4px 0 0;
width: 24px;
> .emojis > li {
.emoji {
display: inline-block;
margin: 0 4px 0 0;
width: 24px;
> img {
width: 24px;
vertical-align: bottom;
}
}
> img {
width: 24px;
vertical-align: bottom;
}
}
.alias {
margin: 0 0 0 8px;
}
}
.alias {
margin: 0 0 0 8px;
}
}
> .mfmTags > li {
.name {
}
}
> .mfmTags > li {
.name {
}
}
}
</style>

View File

@ -1,9 +1,9 @@
<template>
<div class="defgtij">
<div v-for="user in users" :key="user.id" class="avatar-holder">
<MkAvatar :user="user" :show-indicator="true" class="avatar" />
</div>
</div>
<div class="defgtij">
<div v-for="user in users" :key="user.id" class="avatar-holder">
<MkAvatar :user="user" :show-indicator="true" class="avatar" />
</div>
</div>
</template>
<script lang="ts" setup>
@ -11,34 +11,34 @@ import { onMounted, ref } from "vue";
import * as os from "@/os";
const props = defineProps<{
userIds: string[];
userIds: string[];
}>();
const users = ref([]);
onMounted(async () => {
users.value = await os.api("users/show", {
userIds: props.userIds,
});
users.value = await os.api("users/show", {
userIds: props.userIds,
});
});
</script>
<style lang="scss">
.defgtij {
padding: 12px;
grid-gap: 12px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(30px, 40px));
place-content: center;
padding: 12px;
grid-gap: 12px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(30px, 40px));
place-content: center;
> .avatar-holder {
aspect-ratio: 1;
> .avatar-holder {
aspect-ratio: 1;
> .avatar {
width: 100%;
height: 100%;
aspect-ratio: 1;
}
}
> .avatar {
width: 100%;
height: 100%;
aspect-ratio: 1;
}
}
}
</style>

View File

@ -1,254 +1,254 @@
<template>
<button
v-if="!link"
class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full, mini, chip }"
:type="type"
@click="emit('click', $event)"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</button>
<MkA
v-else
class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full, mini }"
:to="to"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</MkA>
<button
v-if="!link"
class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full, mini, chip }"
:type="type"
@click="emit('click', $event)"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</button>
<MkA
v-else
class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full, mini }"
:to="to"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</MkA>
</template>
<script lang="ts" setup>
import { nextTick, onMounted } from "vue";
const props = defineProps<{
type?: "button" | "submit" | "reset";
primary?: boolean;
gradate?: boolean;
rounded?: boolean;
inline?: boolean;
link?: boolean;
to?: string;
autofocus?: boolean;
wait?: boolean;
danger?: boolean;
full?: boolean;
mini?: boolean;
chip?: boolean;
type?: "button" | "submit" | "reset";
primary?: boolean;
gradate?: boolean;
rounded?: boolean;
inline?: boolean;
link?: boolean;
to?: string;
autofocus?: boolean;
wait?: boolean;
danger?: boolean;
full?: boolean;
mini?: boolean;
chip?: boolean;
}>();
const emit = defineEmits<{
(ev: "click", payload: MouseEvent): void;
(ev: "click", payload: MouseEvent): void;
}>();
let el = $ref<HTMLElement | null>(null);
let ripples = $ref<HTMLElement | null>(null);
onMounted(() => {
if (props.autofocus) {
nextTick(() => {
el!.focus();
});
}
if (props.autofocus) {
nextTick(() => {
el!.focus();
});
}
});
function distance(p, q): number {
return Math.hypot(p.x - q.x, p.y - q.y);
return Math.hypot(p.x - q.x, p.y - q.y);
}
function calcCircleScale(boxW, boxH, circleCenterX, circleCenterY): number {
const origin = { x: circleCenterX, y: circleCenterY };
const dist1 = distance({ x: 0, y: 0 }, origin);
const dist2 = distance({ x: boxW, y: 0 }, origin);
const dist3 = distance({ x: 0, y: boxH }, origin);
const dist4 = distance({ x: boxW, y: boxH }, origin);
return Math.max(dist1, dist2, dist3, dist4) * 2;
const origin = { x: circleCenterX, y: circleCenterY };
const dist1 = distance({ x: 0, y: 0 }, origin);
const dist2 = distance({ x: boxW, y: 0 }, origin);
const dist3 = distance({ x: 0, y: boxH }, origin);
const dist4 = distance({ x: boxW, y: boxH }, origin);
return Math.max(dist1, dist2, dist3, dist4) * 2;
}
function onMousedown(evt: MouseEvent): void {
const target = evt.target! as HTMLElement;
const rect = target.getBoundingClientRect();
const target = evt.target! as HTMLElement;
const rect = target.getBoundingClientRect();
const ripple = document.createElement("div");
ripple.style.top = (evt.clientY - rect.top - 1).toString() + "px";
ripple.style.left = (evt.clientX - rect.left - 1).toString() + "px";
const ripple = document.createElement("div");
ripple.style.top = (evt.clientY - rect.top - 1).toString() + "px";
ripple.style.left = (evt.clientX - rect.left - 1).toString() + "px";
ripples!.appendChild(ripple);
ripples!.appendChild(ripple);
const circleCenterX = evt.clientX - rect.left;
const circleCenterY = evt.clientY - rect.top;
const circleCenterX = evt.clientX - rect.left;
const circleCenterY = evt.clientY - rect.top;
const scale = calcCircleScale(
target.clientWidth,
target.clientHeight,
circleCenterX,
circleCenterY
);
const scale = calcCircleScale(
target.clientWidth,
target.clientHeight,
circleCenterX,
circleCenterY
);
window.setTimeout(() => {
ripple.style.transform = "scale(" + scale / 2 + ")";
}, 1);
window.setTimeout(() => {
ripple.style.transition = "all 1s ease";
ripple.style.opacity = "0";
}, 1000);
window.setTimeout(() => {
if (ripples) ripples.removeChild(ripple);
}, 2000);
window.setTimeout(() => {
ripple.style.transform = "scale(" + scale / 2 + ")";
}, 1);
window.setTimeout(() => {
ripple.style.transition = "all 1s ease";
ripple.style.opacity = "0";
}, 1000);
window.setTimeout(() => {
if (ripples) ripples.removeChild(ripple);
}, 2000);
}
</script>
<style lang="scss" scoped>
.bghgjjyj {
position: relative;
z-index: 1; // box-shadow
display: block;
min-width: 100px;
min-height: 35px;
width: max-content;
padding: 8px 16px;
text-align: center;
font-weight: normal;
font-size: max(12px, 1em);
box-shadow: none;
text-decoration: none;
background: var(--buttonBg);
border-radius: 5px;
overflow: clip;
box-sizing: border-box;
transition: background 0.1s ease;
margin-right: 0.2rem;
margin-left: 0.2rem;
position: relative;
z-index: 1; // box-shadow
display: block;
min-width: 100px;
min-height: 35px;
width: max-content;
padding: 8px 16px;
text-align: center;
font-weight: normal;
font-size: max(12px, 1em);
box-shadow: none;
text-decoration: none;
background: var(--buttonBg);
border-radius: 5px;
overflow: clip;
box-sizing: border-box;
transition: background 0.1s ease;
margin-right: 0.2rem;
margin-left: 0.2rem;
&:not(:disabled):hover {
background: var(--buttonHoverBg);
}
&:not(:disabled):hover {
background: var(--buttonHoverBg);
}
&:not(:disabled):active {
background: var(--buttonHoverBg);
}
&:not(:disabled):active {
background: var(--buttonHoverBg);
}
&.full {
width: 100%;
}
&.full {
width: 100%;
}
&.rounded {
border-radius: 999px;
}
&.rounded {
border-radius: 999px;
}
&.primary {
font-weight: bold;
color: var(--fgOnAccent) !important;
background: var(--accent);
&.primary {
font-weight: bold;
color: var(--fgOnAccent) !important;
background: var(--accent);
&:not(:disabled):hover {
background: var(--X8);
}
&:not(:disabled):hover {
background: var(--X8);
}
&:not(:disabled):active {
background: var(--X8);
}
}
&:not(:disabled):active {
background: var(--X8);
}
}
&.gradate {
font-weight: bold;
color: var(--fgOnAccent) !important;
background: linear-gradient(
90deg,
var(--buttonGradateA),
var(--buttonGradateB)
);
&.gradate {
font-weight: bold;
color: var(--fgOnAccent) !important;
background: linear-gradient(
90deg,
var(--buttonGradateA),
var(--buttonGradateB)
);
&:not(:disabled):hover {
background: linear-gradient(90deg, var(--X8), var(--X8));
}
&:not(:disabled):hover {
background: linear-gradient(90deg, var(--X8), var(--X8));
}
&:not(:disabled):active {
background: linear-gradient(90deg, var(--X8), var(--X8));
}
}
&:not(:disabled):active {
background: linear-gradient(90deg, var(--X8), var(--X8));
}
}
&.danger {
color: #eb6f92;
&.danger {
color: #eb6f92;
&.primary {
color: #e0def4;
background: #eb6f92;
&.primary {
color: #e0def4;
background: #eb6f92;
&:not(:disabled):hover {
background: #eb6f92;
}
&:not(:disabled):hover {
background: #eb6f92;
}
&:not(:disabled):active {
background: #b4637a;
}
}
}
&:not(:disabled):active {
background: #b4637a;
}
}
}
&.mini {
padding: 4px 8px;
font-size: max(12px, 0.9em);
border-radius: 100px;
}
&.mini {
padding: 4px 8px;
font-size: max(12px, 0.9em);
border-radius: 100px;
}
&.chip {
padding: 4px 12px;
font-size: max(12px, 0.9em);
min-width: unset;
border-radius: 100px;
}
&.chip {
padding: 4px 12px;
font-size: max(12px, 0.9em);
min-width: unset;
border-radius: 100px;
}
&:disabled {
opacity: 0.7;
}
&:disabled {
opacity: 0.7;
}
&:focus-visible {
outline: auto;
}
&:focus-visible {
outline: auto;
}
&.inline {
display: inline-block;
width: auto;
min-width: 100px;
}
&.inline {
display: inline-block;
width: auto;
min-width: 100px;
}
> .ripples {
position: absolute;
z-index: 0;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 6px;
overflow: hidden;
> .ripples {
position: absolute;
z-index: 0;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 6px;
overflow: hidden;
::v-deep(div) {
position: absolute;
width: 2px;
height: 2px;
border-radius: 100%;
background: rgba(0, 0, 0, 0.1);
opacity: 1;
transform: scale(1);
transition: all 0.5s cubic-bezier(0, 0.5, 0, 1);
}
}
::v-deep(div) {
position: absolute;
width: 2px;
height: 2px;
border-radius: 100%;
background: rgba(0, 0, 0, 0.1);
opacity: 1;
transform: scale(1);
transition: all 0.5s cubic-bezier(0, 0.5, 0, 1);
}
}
&.primary > .ripples ::v-deep(div) {
background: rgba(0, 0, 0, 0.15);
}
&.primary > .ripples ::v-deep(div) {
background: rgba(0, 0, 0, 0.15);
}
> .content {
position: relative;
z-index: 1;
}
> .content {
position: relative;
z-index: 1;
}
}
</style>

View File

@ -1,8 +1,8 @@
<template>
<div>
<span v-if="!available">{{ i18n.ts.waiting }}<MkEllipsis /></span>
<div ref="captchaEl"></div>
</div>
<div>
<span v-if="!available">{{ i18n.ts.waiting }}<MkEllipsis /></span>
<div ref="captchaEl"></div>
</div>
</template>
<script lang="ts" setup>
@ -11,46 +11,46 @@ import { defaultStore } from "@/store";
import { i18n } from "@/i18n";
type Captcha = {
render(
container: string | Node,
options: {
readonly [_ in
| "sitekey"
| "theme"
| "type"
| "size"
| "tabindex"
| "callback"
| "expired"
| "expired-callback"
| "error-callback"
| "endpoint"]?: unknown;
}
): string;
remove(id: string): void;
execute(id: string): void;
reset(id?: string): void;
getResponse(id: string): string;
render(
container: string | Node,
options: {
readonly [_ in
| "sitekey"
| "theme"
| "type"
| "size"
| "tabindex"
| "callback"
| "expired"
| "expired-callback"
| "error-callback"
| "endpoint"]?: unknown;
}
): string;
remove(id: string): void;
execute(id: string): void;
reset(id?: string): void;
getResponse(id: string): string;
};
type CaptchaProvider = "hcaptcha" | "recaptcha";
type CaptchaContainer = {
readonly [_ in CaptchaProvider]?: Captcha;
readonly [_ in CaptchaProvider]?: Captcha;
};
declare global {
interface Window extends CaptchaContainer {}
interface Window extends CaptchaContainer {}
}
const props = defineProps<{
provider: CaptchaProvider;
sitekey: string;
modelValue?: string | null;
provider: CaptchaProvider;
sitekey: string;
modelValue?: string | null;
}>();
const emit = defineEmits<{
(ev: "update:modelValue", v: string | null): void;
(ev: "update:modelValue", v: string | null): void;
}>();
const available = ref(false);
@ -58,79 +58,79 @@ const available = ref(false);
const captchaEl = ref<HTMLDivElement | undefined>();
const variable = computed(() => {
switch (props.provider) {
case "hcaptcha":
return "hcaptcha";
case "recaptcha":
return "grecaptcha";
}
switch (props.provider) {
case "hcaptcha":
return "hcaptcha";
case "recaptcha":
return "grecaptcha";
}
});
const loaded = !!window[variable.value];
const src = computed(() => {
switch (props.provider) {
case "hcaptcha":
return "https://js.hcaptcha.com/1/api.js?render=explicit&recaptchacompat=off";
case "recaptcha":
return "https://www.recaptcha.net/recaptcha/api.js?render=explicit";
}
switch (props.provider) {
case "hcaptcha":
return "https://js.hcaptcha.com/1/api.js?render=explicit&recaptchacompat=off";
case "recaptcha":
return "https://www.recaptcha.net/recaptcha/api.js?render=explicit";
}
});
const captcha = computed<Captcha>(
() => window[variable.value] || ({} as unknown as Captcha)
() => window[variable.value] || ({} as unknown as Captcha)
);
if (loaded) {
available.value = true;
available.value = true;
} else {
(
document.getElementById(props.provider) ||
document.head.appendChild(
Object.assign(document.createElement("script"), {
async: true,
id: props.provider,
src: src.value,
})
)
).addEventListener("load", () => (available.value = true));
(
document.getElementById(props.provider) ||
document.head.appendChild(
Object.assign(document.createElement("script"), {
async: true,
id: props.provider,
src: src.value,
})
)
).addEventListener("load", () => (available.value = true));
}
function reset() {
if (captcha.value.reset) captcha.value.reset();
if (captcha.value.reset) captcha.value.reset();
}
function requestRender() {
if (captcha.value.render && captchaEl.value instanceof Element) {
captcha.value.render(captchaEl.value, {
sitekey: props.sitekey,
theme: defaultStore.state.darkMode ? "dark" : "light",
callback: callback,
"expired-callback": callback,
"error-callback": callback,
});
} else {
window.setTimeout(requestRender, 1);
}
if (captcha.value.render && captchaEl.value instanceof Element) {
captcha.value.render(captchaEl.value, {
sitekey: props.sitekey,
theme: defaultStore.state.darkMode ? "dark" : "light",
callback: callback,
"expired-callback": callback,
"error-callback": callback,
});
} else {
window.setTimeout(requestRender, 1);
}
}
function callback(response?: string) {
emit("update:modelValue", typeof response === "string" ? response : null);
emit("update:modelValue", typeof response === "string" ? response : null);
}
onMounted(() => {
if (available.value) {
requestRender();
} else {
watch(available, requestRender);
}
if (available.value) {
requestRender();
} else {
watch(available, requestRender);
}
});
onBeforeUnmount(() => {
reset();
reset();
});
defineExpose({
reset,
reset,
});
</script>

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,30 @@
<template>
<MkTooltip
ref="tooltip"
:showing="showing"
:x="x"
:y="y"
:max-width="340"
:direction="'top'"
:inner-margin="16"
@closed="emit('closed')"
>
<div v-if="title || series" class="qpcyisrl">
<div v-if="title" class="title">{{ title }}</div>
<template v-if="series">
<div v-for="x in series" class="series">
<span
class="color"
:style="{
background: x.backgroundColor,
borderColor: x.borderColor,
}"
></span>
<span>{{ x.text }}</span>
</div>
</template>
</div>
</MkTooltip>
<MkTooltip
ref="tooltip"
:showing="showing"
:x="x"
:y="y"
:max-width="340"
:direction="'top'"
:inner-margin="16"
@closed="emit('closed')"
>
<div v-if="title || series" class="qpcyisrl">
<div v-if="title" class="title">{{ title }}</div>
<template v-if="series">
<div v-for="x in series" class="series">
<span
class="color"
:style="{
background: x.backgroundColor,
borderColor: x.borderColor,
}"
></span>
<span>{{ x.text }}</span>
</div>
</template>
</div>
</MkTooltip>
</template>
<script lang="ts" setup>
@ -32,37 +32,37 @@ import {} from "vue";
import MkTooltip from "./MkTooltip.vue";
const props = defineProps<{
showing: boolean;
x: number;
y: number;
title?: string;
series?: {
backgroundColor: string;
borderColor: string;
text: string;
}[];
showing: boolean;
x: number;
y: number;
title?: string;
series?: {
backgroundColor: string;
borderColor: string;
text: string;
}[];
}>();
const emit = defineEmits<{
(ev: "closed"): void;
(ev: "closed"): void;
}>();
</script>
<style lang="scss" scoped>
.qpcyisrl {
> .title {
margin-bottom: 4px;
}
> .title {
margin-bottom: 4px;
}
> .series {
> .color {
display: inline-block;
width: 8px;
height: 8px;
border-width: 1px;
border-style: solid;
margin-right: 8px;
}
}
> .series {
> .color {
display: inline-block;
width: 8px;
height: 8px;
border-width: 1px;
border-style: solid;
margin-right: 8px;
}
}
}
</style>

View File

@ -1,13 +1,13 @@
<template>
<XModalWindow
ref="dialog"
:width="600"
@close="dialog?.close()"
@closed="$emit('closed')"
>
<template #header>{{ i18n.ts._mfm.cheatSheet }}</template>
<XCheatSheet :popup="true" style="background: var(--bg)" />
</XModalWindow>
<XModalWindow
ref="dialog"
:width="600"
@close="dialog?.close()"
@closed="$emit('closed')"
>
<template #header>{{ i18n.ts._mfm.cheatSheet }}</template>
<XCheatSheet :popup="true" style="background: var(--bg)" />
</XModalWindow>
</template>
<script lang="ts" setup>
@ -16,24 +16,24 @@ import XCheatSheet from "@/pages/mfm-cheat-sheet.vue";
import { i18n } from "@/i18n";
const emit = defineEmits<{
(ev: "done"): void;
(ev: "closed"): void;
(ev: "done"): void;
(ev: "closed"): void;
}>();
const dialog = $ref<InstanceType<typeof XModalWindow>>();
function close(res) {
dialog.close();
dialog.close();
}
</script>
<style lang="scss" scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease-in-out;
transition: opacity 0.2s ease-in-out;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
opacity: 0;
}
</style>

View File

@ -1,9 +1,9 @@
<template>
<code v-if="inline" :class="`language-${prismLang}`" v-html="html"></code>
<pre
v-else
:class="`language-${prismLang}`"
><code :class="`language-${prismLang}`" v-html="html"></code></pre>
<code v-if="inline" :class="`language-${prismLang}`" v-html="html"></code>
<pre
v-else
:class="`language-${prismLang}`"
><code :class="`language-${prismLang}`" v-html="html"></code></pre>
</template>
<script lang="ts" setup>
@ -12,19 +12,19 @@ import Prism from "prismjs";
import "prismjs/themes/prism-okaidia.css";
const props = defineProps<{
code: string;
lang?: string;
inline?: boolean;
code: string;
lang?: string;
inline?: boolean;
}>();
const prismLang = computed(() =>
Prism.languages[props.lang] ? props.lang : "js"
Prism.languages[props.lang] ? props.lang : "js"
);
const html = computed(() =>
Prism.highlight(
props.code,
Prism.languages[prismLang.value],
prismLang.value
)
Prism.highlight(
props.code,
Prism.languages[prismLang.value],
prismLang.value
)
);
</script>

View File

@ -1,17 +1,17 @@
<template>
<XCode :code="code" :lang="lang" :inline="inline" />
<XCode :code="code" :lang="lang" :inline="inline" />
</template>
<script lang="ts" setup>
import { defineAsyncComponent } from "vue";
defineProps<{
code: string;
lang?: string;
inline?: boolean;
code: string;
lang?: string;
inline?: boolean;
}>();
const XCode = defineAsyncComponent(
() => import("@/components/MkCode.core.vue")
() => import("@/components/MkCode.core.vue")
);
</script>

View File

@ -1,62 +1,62 @@
<template>
<div
v-size="{ max: [380] }"
class="ukygtjoj _panel"
:class="{
naked,
thin,
hideHeader: !showHeader,
scrollable,
closed: !showBody,
}"
>
<header v-if="showHeader" ref="header">
<div class="title"><slot name="header"></slot></div>
<div class="sub">
<slot name="func"></slot>
<button
v-if="foldable"
class="_button"
@click="() => (showBody = !showBody)"
>
<template v-if="showBody"
><i class="ph-caret-up ph-bold ph-lg"></i
></template>
<template v-else
><i class="ph-caret-down ph-bold ph-lg"></i
></template>
</button>
</div>
</header>
<transition
:name="$store.state.animation ? 'container-toggle' : ''"
@enter="enter"
@after-enter="afterEnter"
@leave="leave"
@after-leave="afterLeave"
>
<div
v-show="showBody"
ref="content"
class="content"
:class="{ omitted }"
>
<slot></slot>
<button
v-if="omitted"
class="fade _button"
@click="
() => {
ignoreOmit = true;
omitted = false;
}
"
>
<span>{{ i18n.ts.showMore }}</span>
</button>
</div>
</transition>
</div>
<div
v-size="{ max: [380] }"
class="ukygtjoj _panel"
:class="{
naked,
thin,
hideHeader: !showHeader,
scrollable,
closed: !showBody,
}"
>
<header v-if="showHeader" ref="header">
<div class="title"><slot name="header"></slot></div>
<div class="sub">
<slot name="func"></slot>
<button
v-if="foldable"
class="_button"
@click="() => (showBody = !showBody)"
>
<template v-if="showBody"
><i class="ph-caret-up ph-bold ph-lg"></i
></template>
<template v-else
><i class="ph-caret-down ph-bold ph-lg"></i
></template>
</button>
</div>
</header>
<transition
:name="$store.state.animation ? 'container-toggle' : ''"
@enter="enter"
@after-enter="afterEnter"
@leave="leave"
@after-leave="afterLeave"
>
<div
v-show="showBody"
ref="content"
class="content"
:class="{ omitted }"
>
<slot></slot>
<button
v-if="omitted"
class="fade _button"
@click="
() => {
ignoreOmit = true;
omitted = false;
}
"
>
<span>{{ i18n.ts.showMore }}</span>
</button>
</div>
</transition>
</div>
</template>
<script lang="ts">
@ -64,245 +64,245 @@ import { defineComponent } from "vue";
import { i18n } from "@/i18n";
export default defineComponent({
props: {
showHeader: {
type: Boolean,
required: false,
default: true,
},
thin: {
type: Boolean,
required: false,
default: false,
},
naked: {
type: Boolean,
required: false,
default: false,
},
foldable: {
type: Boolean,
required: false,
default: false,
},
expanded: {
type: Boolean,
required: false,
default: true,
},
scrollable: {
type: Boolean,
required: false,
default: false,
},
maxHeight: {
type: Number,
required: false,
default: null,
},
},
data() {
return {
showBody: this.expanded,
omitted: null,
ignoreOmit: false,
i18n,
};
},
mounted() {
this.$watch(
"showBody",
(showBody) => {
const headerHeight = this.showHeader
? this.$refs.header.offsetHeight
: 0;
this.$el.style.minHeight = `${headerHeight}px`;
if (showBody) {
this.$el.style.flexBasis = "auto";
} else {
this.$el.style.flexBasis = `${headerHeight}px`;
}
},
{
immediate: true,
}
);
props: {
showHeader: {
type: Boolean,
required: false,
default: true,
},
thin: {
type: Boolean,
required: false,
default: false,
},
naked: {
type: Boolean,
required: false,
default: false,
},
foldable: {
type: Boolean,
required: false,
default: false,
},
expanded: {
type: Boolean,
required: false,
default: true,
},
scrollable: {
type: Boolean,
required: false,
default: false,
},
maxHeight: {
type: Number,
required: false,
default: null,
},
},
data() {
return {
showBody: this.expanded,
omitted: null,
ignoreOmit: false,
i18n,
};
},
mounted() {
this.$watch(
"showBody",
(showBody) => {
const headerHeight = this.showHeader
? this.$refs.header.offsetHeight
: 0;
this.$el.style.minHeight = `${headerHeight}px`;
if (showBody) {
this.$el.style.flexBasis = "auto";
} else {
this.$el.style.flexBasis = `${headerHeight}px`;
}
},
{
immediate: true,
}
);
this.$el.style.setProperty("--maxHeight", this.maxHeight + "px");
this.$el.style.setProperty("--maxHeight", this.maxHeight + "px");
const calcOmit = () => {
if (this.omitted || this.ignoreOmit || this.maxHeight == null)
return;
const height = this.$refs.content.offsetHeight;
this.omitted = height > this.maxHeight;
};
const calcOmit = () => {
if (this.omitted || this.ignoreOmit || this.maxHeight == null)
return;
const height = this.$refs.content.offsetHeight;
this.omitted = height > this.maxHeight;
};
calcOmit();
new ResizeObserver((entries, observer) => {
calcOmit();
}).observe(this.$refs.content);
},
methods: {
toggleContent(show: boolean) {
if (!this.foldable) return;
this.showBody = show;
},
calcOmit();
new ResizeObserver((entries, observer) => {
calcOmit();
}).observe(this.$refs.content);
},
methods: {
toggleContent(show: boolean) {
if (!this.foldable) return;
this.showBody = show;
},
enter(el) {
const elementHeight = el.getBoundingClientRect().height;
el.style.height = 0;
el.offsetHeight; // reflow
el.style.height = elementHeight + "px";
},
afterEnter(el) {
el.style.height = null;
},
leave(el) {
const elementHeight = el.getBoundingClientRect().height;
el.style.height = elementHeight + "px";
el.offsetHeight; // reflow
el.style.height = 0;
},
afterLeave(el) {
el.style.height = null;
},
},
enter(el) {
const elementHeight = el.getBoundingClientRect().height;
el.style.height = 0;
el.offsetHeight; // reflow
el.style.height = elementHeight + "px";
},
afterEnter(el) {
el.style.height = null;
},
leave(el) {
const elementHeight = el.getBoundingClientRect().height;
el.style.height = elementHeight + "px";
el.offsetHeight; // reflow
el.style.height = 0;
},
afterLeave(el) {
el.style.height = null;
},
},
});
</script>
<style lang="scss" scoped>
.container-toggle-enter-active,
.container-toggle-leave-active {
overflow-y: hidden;
transition: opacity 0.5s, height 0.5s !important;
overflow-y: hidden;
transition: opacity 0.5s, height 0.5s !important;
}
.container-toggle-enter-from {
opacity: 0;
opacity: 0;
}
.container-toggle-leave-to {
opacity: 0;
opacity: 0;
}
.ukygtjoj {
position: relative;
overflow: clip;
contain: content;
position: relative;
overflow: clip;
contain: content;
&.naked {
background: transparent !important;
box-shadow: none !important;
}
&.naked {
background: transparent !important;
box-shadow: none !important;
}
&.scrollable {
display: flex;
flex-direction: column;
&.scrollable {
display: flex;
flex-direction: column;
> .content {
overflow: auto;
}
}
> .content {
overflow: auto;
}
}
> header {
position: sticky;
top: var(--stickyTop, 0px);
left: 0;
color: var(--panelHeaderFg);
background: var(--panelHeaderBg);
border-bottom: solid 0.5px var(--panelHeaderDivider);
z-index: 2;
line-height: 1.4em;
> header {
position: sticky;
top: var(--stickyTop, 0px);
left: 0;
color: var(--panelHeaderFg);
background: var(--panelHeaderBg);
border-bottom: solid 0.5px var(--panelHeaderDivider);
z-index: 2;
line-height: 1.4em;
> .title {
margin: 0;
padding: 12px 16px;
> .title {
margin: 0;
padding: 12px 16px;
> ::v-deep(i) {
margin-right: 6px;
transform: translateY(0.1em);
}
> ::v-deep(i) {
margin-right: 6px;
transform: translateY(0.1em);
}
&:empty {
display: none;
}
}
&:empty {
display: none;
}
}
> .sub {
position: absolute;
z-index: 2;
top: 0;
right: 0;
height: 100%;
> .sub {
position: absolute;
z-index: 2;
top: 0;
right: 0;
height: 100%;
> ::v-deep(button) {
width: 42px;
height: 100%;
}
}
}
> ::v-deep(button) {
width: 42px;
height: 100%;
}
}
}
> .content {
--stickyTop: 0px;
> .content {
--stickyTop: 0px;
&.omitted {
position: relative;
max-height: var(--maxHeight);
overflow: hidden;
&.omitted {
position: relative;
max-height: var(--maxHeight);
overflow: hidden;
> .fade {
display: block;
position: absolute;
z-index: 10;
bottom: 0;
left: 0;
width: 100%;
height: 64px;
background: linear-gradient(0deg, var(--panel), var(--X15));
> .fade {
display: block;
position: absolute;
z-index: 10;
bottom: 0;
left: 0;
width: 100%;
height: 64px;
background: linear-gradient(0deg, var(--panel), var(--X15));
> span {
display: inline-block;
background: var(--panel);
padding: 6px 10px;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
}
> span {
display: inline-block;
background: var(--panel);
padding: 6px 10px;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
}
&:hover {
> span {
background: var(--panelHighlight);
}
}
}
}
}
&:hover {
> span {
background: var(--panelHighlight);
}
}
}
}
}
&.max-width_380px,
&.thin {
> header {
> .title {
padding: 8px 10px;
font-size: 0.9em;
}
}
&.max-width_380px,
&.thin {
> header {
> .title {
padding: 8px 10px;
font-size: 0.9em;
}
}
> .content {
}
}
> .content {
}
}
}
._forceContainerFull_ .ukygtjoj {
> header {
> .title {
padding: 12px 16px !important;
}
}
> header {
> .title {
padding: 12px 16px !important;
}
}
}
._forceContainerFull_.ukygtjoj {
> header {
> .title {
padding: 12px 16px !important;
}
}
> header {
> .title {
padding: 12px 16px !important;
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More