generated from mirzaev/pot
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
8627411c8e | |||
47687e75b1 | |||
2f1c412795 |
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
2
asdasd
2
asdasd
Submodule asdasd updated: c18318f5de...07b2c6ecfc
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"require": {
|
||||
"php": "~8.3",
|
||||
"ext-openswoole": "~20230831",
|
||||
"ext-sodium": "~8.3",
|
||||
"mirzaev/minimal": "^2.2.0",
|
||||
"twig/twig": "^3.4"
|
||||
},
|
||||
|
0
mirzaev/notchat/system/controllers/core.php
Normal file → Executable file
0
mirzaev/notchat/system/controllers/core.php
Normal file → Executable file
40
mirzaev/notchat/system/controllers/index.php
Normal file → Executable file
40
mirzaev/notchat/system/controllers/index.php
Normal file → Executable file
@@ -5,7 +5,8 @@ declare(strict_types=1);
|
||||
namespace mirzaev\notchat\controllers;
|
||||
|
||||
// Files of the project
|
||||
use mirzaev\notchat\controllers\core;
|
||||
use mirzaev\notchat\controllers\core,
|
||||
mirzaev\notchat\models\server;
|
||||
|
||||
/**
|
||||
* Index controller
|
||||
@@ -29,4 +30,41 @@ final class index extends core
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the servers section
|
||||
*
|
||||
* @param array $parameters Parameters of the request (POST + GET)
|
||||
*
|
||||
* @return void Generated JSON to the output buffer
|
||||
*/
|
||||
public function servers(array $parameters = []): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// POST
|
||||
|
||||
// Initializing a response headers
|
||||
header('Content-Type: application/json');
|
||||
header('Content-Encoding: none');
|
||||
header('X-Accel-Buffering: no');
|
||||
|
||||
// Initializing of the output buffer
|
||||
ob_start();
|
||||
|
||||
// Generating the reponse
|
||||
echo json_encode(
|
||||
[
|
||||
'html' => $this->view->render('sections/servers.html', ['current' => isset($parameters['server']) ? server::read($parameters['server'], errors: $this->errors) : null, 'servers' => server::all(100, errors: $this->errors) ?? []]),
|
||||
'errors' => null
|
||||
]
|
||||
);
|
||||
|
||||
// Initializing a response headers
|
||||
header('Content-Length: ' . ob_get_length());
|
||||
|
||||
// Sending and deinitializing of the output buffer
|
||||
ob_end_flush();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
107
mirzaev/notchat/system/controllers/server.php
Executable file
107
mirzaev/notchat/system/controllers/server.php
Executable file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\notchat\controllers;
|
||||
|
||||
// Files of the project
|
||||
use mirzaev\notchat\controllers\core,
|
||||
mirzaev\notchat\controllers\traits\errors,
|
||||
mirzaev\notchat\models\server as model;
|
||||
|
||||
/**
|
||||
* Server controller
|
||||
*
|
||||
* @package mirzaev\notchat\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class server extends core
|
||||
{
|
||||
use errors;
|
||||
|
||||
/**
|
||||
* Write the server
|
||||
*
|
||||
* API for server registration
|
||||
*
|
||||
* @param array $parameters Parameters of the request (POST + GET)
|
||||
*
|
||||
* @return void Generated JSON to the output buffer
|
||||
*/
|
||||
public function write(array $parameters = []): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// POST
|
||||
|
||||
// Create a file with server data
|
||||
model::write($parameters['domain'], file_get_contents('php://input'), $this->errors);
|
||||
|
||||
// Initializing a response headers
|
||||
header('Content-Type: application/json');
|
||||
header('Content-Encoding: none');
|
||||
header('X-Accel-Buffering: no');
|
||||
|
||||
// Initializing of the output buffer
|
||||
ob_start();
|
||||
|
||||
// Generating the reponse
|
||||
echo json_encode(
|
||||
[
|
||||
'errors' => static::text($this->errors)
|
||||
]
|
||||
);
|
||||
|
||||
// Initializing a response headers
|
||||
header('Content-Length: ' . ob_get_length());
|
||||
|
||||
// Sending and deinitializing of the output buffer
|
||||
ob_end_flush();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the server
|
||||
*
|
||||
* API for server reading
|
||||
*
|
||||
* @param array $parameters Parameters of the request (POST + GET)
|
||||
*
|
||||
* @return void Generated JSON to the output buffer
|
||||
*/
|
||||
public function read(array $parameters = []): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// POST
|
||||
|
||||
// Read a file with server data
|
||||
$server = json_decode(model::read(model::domain($parameters['server']), $this->errors), true, 8);
|
||||
|
||||
// Remove protected parameters
|
||||
unset($server['key']);
|
||||
|
||||
// Initializing a response headers
|
||||
header('Content-Type: application/json');
|
||||
header('Content-Encoding: none');
|
||||
header('X-Accel-Buffering: no');
|
||||
|
||||
// Initializing of the output buffer
|
||||
ob_start();
|
||||
|
||||
// Generating the reponse
|
||||
echo json_encode(
|
||||
[
|
||||
'server' => $server,
|
||||
'errors' => static::text($this->errors)
|
||||
]
|
||||
);
|
||||
|
||||
// Initializing a response headers
|
||||
header('Content-Length: ' . ob_get_length());
|
||||
|
||||
// Sending and deinitializing of the output buffer
|
||||
ob_end_flush();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
}
|
31
mirzaev/notchat/system/controllers/traits/errors.php
Executable file
31
mirzaev/notchat/system/controllers/traits/errors.php
Executable file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\notchat\controllers\traits;
|
||||
|
||||
/**
|
||||
* Trait of handler of errors
|
||||
*
|
||||
* @package mirzaev\notchat\controllers\traits
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
trait errors
|
||||
{
|
||||
private static function text(array $errors): array
|
||||
{
|
||||
// Initializing of output buffer
|
||||
$buffer = [];
|
||||
|
||||
foreach ($errors as $offset => $error) {
|
||||
// Iterating through errors
|
||||
|
||||
// Checking for nesting and writing to the output buffer (entry into recursion)
|
||||
if (isset($error['text'])) $buffer[] = $error['text'];
|
||||
else if (is_array($error) && count($error) > 0) $buffer[$offset] = static::text($error);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
||||
|
6
mirzaev/notchat/system/models/core.php
Normal file → Executable file
6
mirzaev/notchat/system/models/core.php
Normal file → Executable file
@@ -23,6 +23,11 @@ class core extends model
|
||||
*/
|
||||
final public const POSTFIX = '';
|
||||
|
||||
/**
|
||||
* Path to storage
|
||||
*/
|
||||
final public const STORAGE = '..' . DIRECTORY_SEPARATOR . 'storage';
|
||||
|
||||
/**
|
||||
* Constructor of an instance
|
||||
*
|
||||
@@ -108,4 +113,3 @@ class core extends model
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
231
mirzaev/notchat/system/models/dns.php
Executable file
231
mirzaev/notchat/system/models/dns.php
Executable file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\notchat\models;
|
||||
|
||||
// Framework for PHP
|
||||
use mirzaev\minimal\model;
|
||||
|
||||
// Built-in libraries
|
||||
use exception,
|
||||
DirectoryIterator as parser;
|
||||
|
||||
/**
|
||||
* Core of DNS registry
|
||||
*
|
||||
* @package mirzaev\notchat\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
class dns extends core
|
||||
{
|
||||
/**
|
||||
* Path to DNS of storaged servers
|
||||
*/
|
||||
final public const DNS = core::STORAGE . DIRECTORY_SEPARATOR . 'servers' . DIRECTORY_SEPARATOR . 'dns.txt';
|
||||
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* Find and read server data from DNS registry by one of the values
|
||||
*
|
||||
* @param string|null $domain Domain of the server
|
||||
* @param string|null $ip IP-address of the server
|
||||
* @param string|int|null $port Port of the server
|
||||
* @param int $line Line number on which the search will be stopped
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return array|null Found DNS record of the server
|
||||
*/
|
||||
public static function read(?string $domain = null, ?string $ip = null, ?string $port = null, int $line = 0, &$errors = []): ?array
|
||||
{
|
||||
try {
|
||||
// Open file with DNS records
|
||||
$dns = fopen(static::DNS, 'r');
|
||||
|
||||
while (($row = fgets($dns)) !== false) {
|
||||
// Iterate over rows
|
||||
|
||||
// Initializing values of the server data
|
||||
$record = [$_domain, $_ip, $_port] = explode(' ', $row);
|
||||
|
||||
// Incrementing the line read counter
|
||||
++$line;
|
||||
|
||||
if ($domain === $_domain || $ip === $_ip || $port === $_port) {
|
||||
// Server found
|
||||
|
||||
// Close file with DNS
|
||||
fclose($dns);
|
||||
|
||||
// Exit (success)
|
||||
return $record;
|
||||
}
|
||||
}
|
||||
|
||||
// Close file with DNS
|
||||
fclose($dns);
|
||||
} catch (exception $e) {
|
||||
// Write to buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write
|
||||
*
|
||||
* Write server data to the end of DNS registry
|
||||
*
|
||||
* @param string $domain Domain of the server
|
||||
* @param string $ip IP-address of the server
|
||||
* @param string|int $port Port of the server
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function write(string $domain, string $ip, string|int $port, &$errors = []): void
|
||||
{
|
||||
try {
|
||||
// Initializing part the file buffer (rows before target)
|
||||
$before = [];
|
||||
|
||||
// Initializing part the file buffer (rows before target)
|
||||
$after = [];
|
||||
|
||||
if (file_exists(static::DNS) && filesize(static::DNS) > 0) {
|
||||
// File exists and not empty
|
||||
|
||||
// Initializing the status that the DNS record has been found
|
||||
$found = false;
|
||||
|
||||
// Open file with DNS records
|
||||
$dns = fopen(static::DNS, 'r');
|
||||
|
||||
while (($row = fgets($dns)) !== false) {
|
||||
// Iterate over rows
|
||||
|
||||
// Initializing values of the server data
|
||||
[$_domain] = explode(' ', $row);
|
||||
|
||||
// Writing the row to the file buffer (except the target record)
|
||||
if ($domain === $_domain) $found = true;
|
||||
else ${$found ? 'after' : 'before'}[] = $row;
|
||||
}
|
||||
|
||||
// Close file with DNS records
|
||||
fclose($dns);
|
||||
}
|
||||
|
||||
// Open file with DNS records
|
||||
$dns = fopen(static::DNS, 'c');
|
||||
|
||||
if (flock($dns, LOCK_EX)) {
|
||||
// File locked
|
||||
|
||||
// Clear file
|
||||
ftruncate($dns, 0);
|
||||
|
||||
// Write a new record to the DNS registry
|
||||
fwrite($dns, trim(implode("", $before)) . "\n$domain $ip $port\n" . trim(implode("", $after)));
|
||||
|
||||
// Apply changes
|
||||
fflush($dns);
|
||||
|
||||
// Unlock file
|
||||
flock($dns, LOCK_UN);
|
||||
}
|
||||
} catch (exception $e) {
|
||||
// Write to buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain
|
||||
*
|
||||
* Convert domain or IP-address to domain
|
||||
*
|
||||
* @param string $server Domain or IP-address of the server
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return string|null Domain of the server
|
||||
*/
|
||||
public static function domain(string $server, &$errors = []): ?string
|
||||
{
|
||||
try {
|
||||
if (preg_match('/^(https:\/\/)?\d+\..*\d\/?$/', $server) === 1) {
|
||||
// IP-address
|
||||
|
||||
// Exit (success)
|
||||
return static::read(ip: $server, errors: $errors)['domain'];
|
||||
} else {
|
||||
// Domain (implied)
|
||||
|
||||
// Exit (success)
|
||||
return $server;
|
||||
}
|
||||
} catch (exception $e) {
|
||||
// Write to buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* IP-address
|
||||
*
|
||||
* Convert domain or IP-address to IP-address
|
||||
*
|
||||
* @param string $server Domain or IP-address of the server
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return string|null IP-address of the server
|
||||
*/
|
||||
public static function ip(string $server, &$errors = []): ?string
|
||||
{
|
||||
try {
|
||||
if (preg_match('/^(https:\/\/)?\d+\..*\d\/?$/', $server) === 1) {
|
||||
// IP-address
|
||||
|
||||
// Exit (success)
|
||||
return $server;
|
||||
} else {
|
||||
// Domain (implied)
|
||||
|
||||
// Exit (success)
|
||||
return static::read(domain: $server, errors: $errors)['ip'];
|
||||
}
|
||||
} catch (exception $e) {
|
||||
// Write to buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
}
|
215
mirzaev/notchat/system/models/server.php
Executable file
215
mirzaev/notchat/system/models/server.php
Executable file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\notchat\models;
|
||||
|
||||
// Framework for PHP
|
||||
use mirzaev\minimal\model;
|
||||
|
||||
// Built-in libraries
|
||||
use exception,
|
||||
DirectoryIterator as parser;
|
||||
|
||||
/**
|
||||
* Core of models
|
||||
*
|
||||
* @package mirzaev\notchat\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
class server extends core
|
||||
{
|
||||
/**
|
||||
* Path to storage of servers
|
||||
*/
|
||||
final public const SERVERS = core::STORAGE . DIRECTORY_SEPARATOR . 'servers';
|
||||
|
||||
/**
|
||||
* Write
|
||||
*
|
||||
* Create the file with server settings
|
||||
*
|
||||
* @param string $domain Domain of the server (unique)
|
||||
* @param string $json Data of the server with JSON format
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function write(string $domain, string $json = '', array &$errors = []): void
|
||||
{
|
||||
try {
|
||||
if (strlen($domain) > 32) throw new exception('Domain cannot be longer than 32 characters');
|
||||
|
||||
// Initializing of path to file
|
||||
$path = static::SERVERS . DIRECTORY_SEPARATOR . "$domain.json";
|
||||
|
||||
// Initializing of host parameter
|
||||
$host = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
if (empty($host)) throw new exception('ты что дохуя фокусник блять');
|
||||
|
||||
// Initializing of data of server
|
||||
$new = ['domain' => $domain, 'ip' => $host] + json_decode($json, true, 8);
|
||||
|
||||
if (strlen($new['key']) > 512) throw new exception('Public key cannot be longer than 512 characters');
|
||||
|
||||
if (file_exists($path)) {
|
||||
// File found
|
||||
|
||||
// Open file with server data
|
||||
$file = fopen($path, "r");
|
||||
|
||||
// Read server data
|
||||
$old = json_decode(fread($file, filesize($path)), true, 8);
|
||||
|
||||
// Close file with server data
|
||||
fclose($file);
|
||||
|
||||
if ($new['key'] === $old['key'] || time() - filectime($path) > 259200) {
|
||||
// The keys match or the file has not been updated for more than 3 days
|
||||
|
||||
// Open file with server data
|
||||
$file = fopen($path, "w");
|
||||
|
||||
// Write server data
|
||||
fwrite($file, json_encode($new));
|
||||
|
||||
// Close file with server data
|
||||
fclose($file);
|
||||
|
||||
// Write DNS record
|
||||
dns::write(domain: $new['domain'], ip: $new['ip'], port: $new['port'], errors: $errors);
|
||||
} else throw new exception('Public keys do not match');
|
||||
} else {
|
||||
// File is not found
|
||||
|
||||
// Open file with server data
|
||||
$file = fopen($path, "w");
|
||||
|
||||
// Write server data
|
||||
fwrite($file, json_encode($new));
|
||||
|
||||
// Close file with server data
|
||||
fclose($file);
|
||||
|
||||
// Write DNS record
|
||||
dns::write(domain: $new['domain'], ip: $new['ip'], port: $new['port'], errors: $errors);
|
||||
}
|
||||
} catch (exception $e) {
|
||||
// Write to buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* Read JSON from file of server
|
||||
*
|
||||
* @param string $domain Domain of the server
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return string|null JSON with data of the server
|
||||
*/
|
||||
public static function read(string $domain, &$errors = []): ?string
|
||||
{
|
||||
try {
|
||||
// Initializing of path to file
|
||||
$path = static::SERVERS . DIRECTORY_SEPARATOR . "$domain.json";
|
||||
|
||||
// Open file with server data
|
||||
$file = fopen($path, "r");
|
||||
|
||||
// Read server data
|
||||
$server = fread($file, filesize($path));
|
||||
|
||||
// Close file with server data
|
||||
fclose($file);
|
||||
|
||||
// Exit (success)
|
||||
return $server;
|
||||
} catch (exception $e) {
|
||||
// Write to buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all
|
||||
*
|
||||
* Read JSON from all files of servers
|
||||
*
|
||||
* @param int $amount Number of servers per page
|
||||
* @param int $page Page of list of servers
|
||||
* @param int $time Number of seconds since the file was last edited (86400 seconds is 1 day)
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return array|null Array with JSON entries, if found
|
||||
*/
|
||||
public static function all(int $amount = 100, int $page = 1, int $time = 86400, array &$errors = []): ?array
|
||||
{
|
||||
try {
|
||||
// Initializing of the output buffer
|
||||
$buffer = [];
|
||||
|
||||
// Initializing the minimum value of amount
|
||||
if ($amount < 1) $amount = 1;
|
||||
|
||||
// Initializing the minimum value of page
|
||||
if ($page < 1) $page = 1;
|
||||
|
||||
// Initializing of amount to skip
|
||||
$skip = $page * $amount;
|
||||
|
||||
foreach (new parser(static::SERVERS) as $file) {
|
||||
// Skipping unnecessary files
|
||||
if (--$skip > $amount) continue;
|
||||
|
||||
// Skipping system shortcuts
|
||||
if ($file->isDot()) continue;
|
||||
|
||||
if (time() - $file->getCTime() < $time && $file->isReadable()) {
|
||||
// The file is actual (3 days by default) and writable
|
||||
|
||||
// Open file with server data
|
||||
$server = $file->openFile('r');
|
||||
|
||||
// Write server data to the output buffer
|
||||
$buffer[] = json_decode($server->fread($file->getSize()));
|
||||
|
||||
// Close file with server data
|
||||
unset($file);
|
||||
}
|
||||
|
||||
if (--$amount < 1) break;
|
||||
}
|
||||
|
||||
// Exit (success)
|
||||
return $buffer;
|
||||
} catch (exception $e) {
|
||||
// Write to buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
}
|
3
mirzaev/notchat/system/public/index.php
Normal file → Executable file
3
mirzaev/notchat/system/public/index.php
Normal file → Executable file
@@ -34,6 +34,9 @@ $router = new router;
|
||||
|
||||
// Запись маршрутов
|
||||
$router->write('/', 'index', 'index');
|
||||
$router->write('/server/read/$server', 'server', 'read', 'POST');
|
||||
$router->write('/servers', 'index', 'servers', 'POST');
|
||||
$router->write('/servers/connect/$domain', 'server', 'write', 'POST');
|
||||
|
||||
// Инициализация ядра
|
||||
$core = new core(namespace: __NAMESPACE__, router: $router, controller: new controller(false), model: new model(false));
|
||||
|
0
mirzaev/notchat/system/public/js/adapter.js
Normal file → Executable file
0
mirzaev/notchat/system/public/js/adapter.js
Normal file → Executable file
99
mirzaev/notchat/system/public/js/chats.js
Executable file
99
mirzaev/notchat/system/public/js/chats.js
Executable file
@@ -0,0 +1,99 @@
|
||||
"use strict";
|
||||
|
||||
if (typeof window.chats !== "function") {
|
||||
// Not initialized
|
||||
|
||||
// Initialize of the class in global namespace
|
||||
window.chats = class chats {
|
||||
/**
|
||||
* Server
|
||||
*/
|
||||
static server = {
|
||||
/**
|
||||
* Select server
|
||||
*
|
||||
* @param {string} server Domain or IP-address of the server (from cache by default)
|
||||
*
|
||||
* @return {void} Into the document will be generated and injected an HTML-element
|
||||
*/
|
||||
select(server = localStorage.server_ip ?? localStorage.server_domain) {
|
||||
if (typeof server === "string" && server.length > 0) {
|
||||
if (core.servers instanceof HTMLElement) {
|
||||
core.request(`/server/read/${server}`).then((json) => {
|
||||
if (
|
||||
json.errors !== null && typeof json.errors === "object" &&
|
||||
json.errors.length > 0
|
||||
) {} else {
|
||||
document.querySelector('figcaption[data-server="ip"]').innerText = `${json.ip}:${json.port}`;
|
||||
document.querySelector('figcaption[data-server="description"]').innerText = `${json.description}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Generators
|
||||
*/
|
||||
static generate = {
|
||||
/**
|
||||
* HTML-element with a server selection form
|
||||
*
|
||||
* @param {string} server Domain or IP-address of the server (from cache by default)
|
||||
*
|
||||
* @return {void} Into the document will be generated and injected an HTML-element
|
||||
*/
|
||||
servers(server = localStorage.server_ip ?? localStorage.server_domain) {
|
||||
core.request(
|
||||
"/servers",
|
||||
typeof server === "string" && server.length > 0
|
||||
? `server=${server}}`
|
||||
: "",
|
||||
).then((json) => {
|
||||
if (core.servers instanceof HTMLElement) core.servers.remove();
|
||||
if (
|
||||
json.errors !== null && typeof json.errors === "object" &&
|
||||
json.errors.length > 0
|
||||
) {} else {
|
||||
const element = document.createElement("div");
|
||||
core.header.after(element);
|
||||
element.outerHTML = json.html;
|
||||
|
||||
core.servers = document.body.querySelector(
|
||||
"section[data-section='servers']",
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string}
|
||||
*
|
||||
* @return {void} Into the document will be generated and injected an HTML-element
|
||||
*/
|
||||
chat() {
|
||||
core.request("/chat").then((json) => {
|
||||
if (
|
||||
json.errors !== null && typeof json.errors === "object" &&
|
||||
json.errors.length > 0
|
||||
) {} else {
|
||||
const element = document.createElement("div");
|
||||
const position = core.main.children.length;
|
||||
element.style.setProperty("--position", position);
|
||||
core.main.append(element);
|
||||
core.main.style.setProperty("--elements", position + 1);
|
||||
element.innerHTML = json.html;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Dispatch event: "initialized"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("chats.initialized", {
|
||||
detail: { chats: window.chats },
|
||||
}),
|
||||
);
|
57
mirzaev/notchat/system/public/js/core.js
Executable file
57
mirzaev/notchat/system/public/js/core.js
Executable file
@@ -0,0 +1,57 @@
|
||||
"use strict";
|
||||
|
||||
if (typeof window.core !== "function") {
|
||||
// Not initialized
|
||||
|
||||
// Initialize of the class in global namespace
|
||||
window.core = class core {
|
||||
// Label for the <main> element
|
||||
static main = document.body.getElementsByTagName('main')[0];
|
||||
|
||||
// Label for the <header> element
|
||||
static header = document.body.getElementsByTagName('header')[0];
|
||||
|
||||
// Label for the <aside> element
|
||||
static aside = document.body.getElementsByTagName('aside')[0];
|
||||
|
||||
// Label for the "servers" element
|
||||
static servers = document.body.querySelector("section[data-section='servers']");
|
||||
|
||||
// Label for the "chats" element
|
||||
static chats = document.body.querySelector("section[data-section='chats']");
|
||||
|
||||
// Label for the <footer> element
|
||||
static footer = document.body.getElementsByTagName('footer')[0];
|
||||
|
||||
/**
|
||||
* Request
|
||||
*
|
||||
* @param {string} address
|
||||
* @param {string} body
|
||||
* @param {string} method POST, GET...
|
||||
* @param {object} headers
|
||||
* @param {string} type Format of response (json, text...)
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
static async request(
|
||||
address = '/',
|
||||
body,
|
||||
method = "POST",
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
type = "json",
|
||||
) {
|
||||
return await fetch(address, { method, headers, body })
|
||||
.then((response) => response[type]());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Dispatch event: "initialized"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("core.initialized", {
|
||||
detail: { core: window.core },
|
||||
}),
|
||||
);
|
0
mirzaev/notchat/system/public/js/notchat.js
Normal file → Executable file
0
mirzaev/notchat/system/public/js/notchat.js
Normal file → Executable file
7
mirzaev/notchat/system/public/js/pages/chat.js
Normal file → Executable file
7
mirzaev/notchat/system/public/js/pages/chat.js
Normal file → Executable file
@@ -37,3 +37,10 @@ if (typeof window.asdasd === "function") (() => init_asdasd(asdasd))();
|
||||
else {document.addEventListener("asdasd.initialized", (e) =>
|
||||
init_asdasd(e.asdasd));}
|
||||
|
||||
function init(chats) {
|
||||
chats.generate.servers();
|
||||
}
|
||||
|
||||
if (typeof window.chats === "function") (() => init(chats))();
|
||||
else {document.addEventListener("chats.initialized", (e) =>
|
||||
init(e.chats));}
|
||||
|
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace mirzaev\notchat;
|
||||
|
||||
use OpenSwoole\Server,
|
||||
OpenSwoole\WebSocket\Server as websocket,
|
||||
OpenSwoole\Http\Request,
|
||||
OpenSwoole\WebSocket\Frame,
|
||||
OpenSwoole\Constant;
|
||||
|
||||
$server = new websocket("0.0.0.0", 2024, Server::POOL_MODE, Constant::SOCK_TCP | Constant::SSL);
|
||||
|
||||
$server->set([
|
||||
'ssl_cert_file' => '/etc/letsencrypt/live/mirzaev.sexy/fullchain.pem',
|
||||
'ssl_key_file' => '/etc/letsencrypt/live/mirzaev.sexy/privkey.pem'
|
||||
]);
|
||||
|
||||
$server->on("Start", function (Server $server) {
|
||||
echo "OpenSwoole WebSocket Server is started at http://127.0.0.1:2024\n";
|
||||
});
|
||||
|
||||
$server->on('Open', function (Server $server, Request $request) {
|
||||
echo "connection open: {$request->fd}\n";
|
||||
|
||||
$server->tick(1000, function () use ($server, $request) {
|
||||
$server->push($request->fd, json_encode(["hello", time()]));
|
||||
});
|
||||
});
|
||||
|
||||
$server->on('Message', function (Server $server, Frame $frame) {
|
||||
echo "received message: {$frame->data}\n";
|
||||
$server->push($frame->fd, json_encode(["hello", time()]));
|
||||
});
|
||||
|
||||
$server->on('Close', function (Server $server, int $fd) {
|
||||
echo "connection close: {$fd}\n";
|
||||
});
|
||||
|
||||
$server->on('Disconnect', function (Server $server, int $fd) {
|
||||
echo "connection disconnect: {$fd}\n";
|
||||
});
|
||||
|
||||
$server->start();
|
30
mirzaev/notchat/system/public/themes/default/css/animations.css
Executable file
30
mirzaev/notchat/system/public/themes/default/css/animations.css
Executable file
@@ -0,0 +1,30 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
@keyframes uprise {
|
||||
0% {
|
||||
opacity: 0;
|
||||
filter: blur(2px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
filter: blur(0px);
|
||||
}
|
||||
}
|
||||
|
||||
.animation.uprise {
|
||||
animation-duration: 0.1s;
|
||||
animation-name: uprise;
|
||||
animation-fill-mode: forwards;
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
|
||||
|
||||
@keyframes marquee {
|
||||
0% { left: 0; }
|
||||
100% { left: -100%; }
|
||||
}
|
||||
|
||||
.animation.marquee {
|
||||
animation: marquee var(--speed, 3s) linear infinite;
|
||||
}
|
9
mirzaev/notchat/system/public/themes/default/css/fonts.css
Executable file
9
mirzaev/notchat/system/public/themes/default/css/fonts.css
Executable file
@@ -0,0 +1,9 @@
|
||||
@import url('/themes/default/css/fonts/fira.css');
|
||||
@import url('/themes/default/css/fonts/hack.css');
|
||||
@import url('/themes/default/css/fonts/dejavu.css');
|
||||
|
||||
@font-face {
|
||||
font-family: 'Commissioner';
|
||||
src: url('/themes/default/fonts/commissioner.ttf');
|
||||
font-weight: 400;
|
||||
}
|
34
mirzaev/notchat/system/public/themes/default/css/fonts/dejavu.css
Executable file
34
mirzaev/notchat/system/public/themes/default/css/fonts/dejavu.css
Executable file
@@ -0,0 +1,34 @@
|
||||
@font-face {
|
||||
font-family: 'DejaVu';
|
||||
src: url("/themes/default/fonts/dejavu/DejaVuLGCSans-ExtraLight.ttf");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu';
|
||||
src: url("/themes/default/fonts/dejavu/DejaVuLGCSans.ttf");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu';
|
||||
src: url("/themes/default/fonts/dejavu/DejaVuLGCSans-Oblique.ttf");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu';
|
||||
src: url("/themes/default/fonts/dejavu/DejaVuLGCSans-Bold.ttf");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu';
|
||||
src: url("/themes/default/fonts/dejavu/DejaVuLGCSans-BoldOblique.ttf");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
139
mirzaev/notchat/system/public/themes/default/css/fonts/fira.css
Executable file
139
mirzaev/notchat/system/public/themes/default/css/fonts/fira.css
Executable file
@@ -0,0 +1,139 @@
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-Hair.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-Hair.woff') format('woff');
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-HairItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-HairItalic.woff') format('woff');
|
||||
font-weight: 100;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-UltraLight.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-UltraLight.woff') format('woff');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-UltraLightItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-UltraLightItalic.woff') format('woff');
|
||||
font-weight: 200;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-Light.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-Light.woff') format('woff');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-LightItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-LightItalic.woff') format('woff');
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-Regular.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-Regular.woff') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-Italic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-Italic.woff') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraMono-Medium.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraMono-Medium.woff') format('woff');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-MediumItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-MediumItalic.woff') format('woff');
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-SemiBold.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-SemiBold.woff') format('woff');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-SemiBoldItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-SemiBoldItalic.woff') format('woff');
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-Bold.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-Bold.woff') format('woff');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-BoldItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-BoldItalic.woff') format('woff');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-ExtraBold.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-ExtraBold.woff') format('woff');
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-ExtraBoldItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-ExtraBoldItalic.woff') format('woff');
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-Heavy.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-Heavy.woff') format('woff');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira';
|
||||
src: url('/themes/default/fonts/fira/FiraSans-HeavyItalic.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraSans-HeavyItalic.woff') format('woff');
|
||||
font-weight: 900;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira' Mono;
|
||||
src: url('/themes/default/fonts/fira/FiraMono-Regular.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraMono-Regular.woff') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira' Mono;
|
||||
src: url('/themes/default/fonts/fira/FiraMono-Bold.woff2') format('woff2'), url('/themes/default/fonts/fira/FiraMono-Bold.woff') format('woff');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
31
mirzaev/notchat/system/public/themes/default/css/fonts/hack.css
Executable file
31
mirzaev/notchat/system/public/themes/default/css/fonts/hack.css
Executable file
@@ -0,0 +1,31 @@
|
||||
@font-face {
|
||||
font-family: 'Hack';
|
||||
src: url('/themes/default/fonts/hack/hack-regular.woff2?sha=3114f1256') format('woff2'), url('/themes/default/fonts/hack/hack-regular.woff?sha=3114f1256') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Hack';
|
||||
src: url('/themes/default/fonts/hack/hack-bold.woff2?sha=3114f1256') format('woff2'), url('/themes/default/fonts/hack/hack-bold.woff?sha=3114f1256') format('woff');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Hack';
|
||||
src: url('/themes/default/fonts/hack/hack-italic.woff2?sha=3114f1256') format('woff2'), url('/themes/default/fonts/hack/hack-italic.woff?sha=3114f1256') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Hack';
|
||||
src: url('/themes/default/fonts/hack/hack-bolditalic.woff2?sha=3114f1256') format('woff2'), url('/themes/default/fonts/hack/hack-bolditalic.woff?sha=3114f1256') format('woff');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
51
mirzaev/notchat/system/public/themes/default/css/icons/data.css
Executable file
51
mirzaev/notchat/system/public/themes/default/css/icons/data.css
Executable file
@@ -0,0 +1,51 @@
|
||||
i.icon.data {
|
||||
--width: 14px;
|
||||
--height: 14px;
|
||||
position: relative;
|
||||
width: var(--width);
|
||||
height: var(--height);
|
||||
}
|
||||
|
||||
i.icon.data,
|
||||
i.icon.data::after,
|
||||
i.icon.data::before {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
border: 2px solid;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
i.icon.data::before {
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
i.icon.data::after {
|
||||
left: -6px;
|
||||
top: -6px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background: linear-gradient(to left, currentColor 8px, transparent 0) no-repeat bottom center/2px 8px;
|
||||
}
|
||||
|
||||
i.icon.data::after,
|
||||
i.icon.data::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
i.icon.data,
|
||||
i.icon.data::after {
|
||||
border-top-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
label>i.icon.data:first-of-type {
|
||||
left: 13px;
|
||||
}
|
||||
|
||||
label>i.icon.data+input {
|
||||
padding-left: 38px !important;
|
||||
}
|
39
mirzaev/notchat/system/public/css/themes/default/main.css → mirzaev/notchat/system/public/themes/default/css/main.css
Normal file → Executable file
39
mirzaev/notchat/system/public/css/themes/default/main.css → mirzaev/notchat/system/public/themes/default/css/main.css
Normal file → Executable file
@@ -11,6 +11,10 @@
|
||||
--red: #4d2d2d;
|
||||
--green: #415e53;
|
||||
--blue: #243b4f;
|
||||
|
||||
/* --input-servers: #898c25; очень крутой зелёно говняный цвет */
|
||||
--input-servers-text: #083932;
|
||||
--input-servers-background: #109386;
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -18,7 +22,8 @@
|
||||
outline: none;
|
||||
border: none;
|
||||
/* font-family: , system-ui, sans-serif; */
|
||||
font-family: "dejavu";
|
||||
/* font-family: "dejavu"; */
|
||||
font-family: 'DejaVu', sans-serif;
|
||||
transition: 0.1s ease-out;
|
||||
}
|
||||
|
||||
@@ -31,7 +36,7 @@ body {
|
||||
height: 100vh;
|
||||
display: grid;
|
||||
grid-template-columns: [header] 220px [settings] 320px [main] auto [footer] 180px;
|
||||
grid-template-rows: [aside] var(--row-aside, 200px) [settings] var(--row-settings, 100px) [main] auto;
|
||||
grid-template-rows: [aside] var(--row-aside, 200px) [settings] var(--row-settings, 100px) [main] calc(100vh - var(--row-aside) - var(--gap) - var(--row-settings) - var(--gap)) auto;
|
||||
gap: var(--gap, 16px);
|
||||
padding: 0;
|
||||
overflow-x: scroll;
|
||||
@@ -65,9 +70,37 @@ header>section[data-section="main"] {
|
||||
|
||||
section[data-section="servers"] {
|
||||
z-index: 250;
|
||||
padding: 14px 15px;
|
||||
grid-row: settings;
|
||||
background-color: var(--important);
|
||||
border-radius: 5px;
|
||||
background-color: var(--important);
|
||||
}
|
||||
|
||||
section[data-section="servers"]>search {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
section[data-section="servers"]>search>label {
|
||||
position: relative;
|
||||
height: 1.9rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--input-servers-text);
|
||||
}
|
||||
|
||||
section[data-section="servers"]>search>label>i:first-child:first-of-type {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
section[data-section="servers"]>search>label>i:first-child:first-of-type+input:first-of-type {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 10px;
|
||||
font-weight: 500;
|
||||
border-radius: 3px;
|
||||
color: var(--input-servers-text);
|
||||
background-color: var(--input-servers-background);
|
||||
}
|
||||
|
||||
section[data-section="chats"] {
|
BIN
mirzaev/notchat/system/public/themes/default/fonts/commissioner.ttf
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/commissioner.ttf
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSans-Bold.ttf
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSans-Bold.ttf
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSans.ttf
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSans.ttf
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSansMono.ttf
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSansMono.ttf
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSerif.ttf
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/dejavu/DejaVuLGCSerif.ttf
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Bold.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Bold.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Bold.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Bold.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Medium.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Medium.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Medium.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Medium.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Regular.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Regular.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Regular.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraMono-Regular.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Bold.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Bold.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Bold.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Bold.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-BoldItalic.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-BoldItalic.woff
Executable file
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Book.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Book.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Book.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Book.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-BookItalic.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-BookItalic.woff
Executable file
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Eight.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Eight.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Eight.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Eight.woff2
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-ExtraBold.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-ExtraBold.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-ExtraBold.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-ExtraBold.woff2
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-ExtraLight.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-ExtraLight.woff
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Four.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Four.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Four.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Four.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-FourItalic.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-FourItalic.woff
Executable file
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Hair.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Hair.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Hair.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Hair.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-HairItalic.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-HairItalic.woff
Executable file
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Heavy.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Heavy.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Heavy.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Heavy.woff2
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Italic.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Italic.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Italic.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Italic.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Light.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Light.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Light.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Light.woff2
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Medium.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Medium.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Medium.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Medium.woff2
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Regular.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Regular.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Regular.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-Regular.woff2
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-SemiBold.woff
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-SemiBold.woff
Executable file
Binary file not shown.
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-SemiBold.woff2
Executable file
BIN
mirzaev/notchat/system/public/themes/default/fonts/fira/FiraSans-SemiBold.woff2
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user