mirror of
https://github.com/openvk/openvk
synced 2024-11-15 03:31:18 +03:00
Merge branch 'master' into ignored-sources
This commit is contained in:
commit
a99ffbdafe
139 changed files with 7152 additions and 2180 deletions
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
@ -1 +1 @@
|
||||||
custom: "https://openvk.su/donate"
|
custom: "https://ovk.to/donate"
|
||||||
|
|
20
.github/workflows/build-base.yaml
vendored
20
.github/workflows/build-base.yaml
vendored
|
@ -6,7 +6,7 @@ on:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BASE_IMAGE_NAME: php
|
BASE_IMAGE_NAME: php
|
||||||
BASE_IMAGE_VERSION: "8.1"
|
BASE_IMAGE_VERSION: "8.2"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-cli:
|
build-cli:
|
||||||
|
@ -24,12 +24,18 @@ jobs:
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Change repository string to lowercase
|
||||||
|
id: repositorystring
|
||||||
|
uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0
|
||||||
|
with:
|
||||||
|
string: ${{ github.repository }}
|
||||||
|
|
||||||
- name: Log into registry
|
- name: Log into registry
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||||
|
|
||||||
- name: Build cli image
|
- name: Build cli image
|
||||||
run: |
|
run: |
|
||||||
IMAGE_NAME=ghcr.io/${{ github.repository }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-cli
|
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-cli
|
||||||
|
|
||||||
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/base-php-cli.Dockerfile --build-arg VERSION=$BASE_IMAGE_VERSION
|
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/base-php-cli.Dockerfile --build-arg VERSION=$BASE_IMAGE_VERSION
|
||||||
|
|
||||||
|
@ -47,12 +53,18 @@ jobs:
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Change repository string to lowercase
|
||||||
|
id: repositorystring
|
||||||
|
uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0
|
||||||
|
with:
|
||||||
|
string: ${{ github.repository }}
|
||||||
|
|
||||||
- name: Log into registry
|
- name: Log into registry
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||||
|
|
||||||
- name: Build apache image
|
- name: Build apache image
|
||||||
run: |
|
run: |
|
||||||
IMAGE_NAME=ghcr.io/${{ github.repository }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-apache
|
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-apache
|
||||||
|
|
||||||
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/base-php-apache.Dockerfile --build-arg VERSION=$BASE_IMAGE_VERSION
|
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/base-php-apache.Dockerfile --build-arg VERSION=$BASE_IMAGE_VERSION
|
||||||
|
|
14
.github/workflows/build.yaml
vendored
14
.github/workflows/build.yaml
vendored
|
@ -36,12 +36,18 @@ jobs:
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Change repository string to lowercase
|
||||||
|
id: repositorystring
|
||||||
|
uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0
|
||||||
|
with:
|
||||||
|
string: ${{ github.repository }}
|
||||||
|
|
||||||
- name: Log into registry
|
- name: Log into registry
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||||
|
|
||||||
- name: Build base image
|
- name: Build base image
|
||||||
run: |
|
run: |
|
||||||
IMAGE_ID=ghcr.io/${{ github.repository }}/$BASE_IMAGE_NAME
|
IMAGE_ID=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$BASE_IMAGE_NAME
|
||||||
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
|
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
|
||||||
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
|
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
|
||||||
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
|
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
|
||||||
|
@ -49,16 +55,16 @@ jobs:
|
||||||
echo IMAGE_ID=$IMAGE_ID
|
echo IMAGE_ID=$IMAGE_ID
|
||||||
echo VERSION=$VERSION
|
echo VERSION=$VERSION
|
||||||
|
|
||||||
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_ID:$VERSION . --push -f install/automated/docker/openvk.Dockerfile --build-arg GITREPO=${{ github.repository }}
|
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_ID:$VERSION . --push -f install/automated/docker/openvk.Dockerfile --build-arg GITREPO=${{ steps.repositorystring.outputs.lowercase }}
|
||||||
|
|
||||||
- name: Build MariaDB primary image
|
- name: Build MariaDB primary image
|
||||||
run: |
|
run: |
|
||||||
IMAGE_NAME=ghcr.io/${{ github.repository }}/$DB_IMAGE_NAME:$DB_VERSION-primary
|
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$DB_IMAGE_NAME:$DB_VERSION-primary
|
||||||
|
|
||||||
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/mariadb-primary.Dockerfile --build-arg VERSION=$DB_VERSION
|
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/mariadb-primary.Dockerfile --build-arg VERSION=$DB_VERSION
|
||||||
|
|
||||||
- name: Build MariaDB event image
|
- name: Build MariaDB event image
|
||||||
run: |
|
run: |
|
||||||
IMAGE_NAME=ghcr.io/${{ github.repository }}/$EVENT_IMAGE_NAME:$DB_VERSION-eventdb
|
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$EVENT_IMAGE_NAME:$DB_VERSION-eventdb
|
||||||
|
|
||||||
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/mariadb-eventdb.Dockerfile --build-arg VERSION=$DB_VERSION
|
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/mariadb-eventdb.Dockerfile --build-arg VERSION=$DB_VERSION
|
|
@ -12,7 +12,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td class="float-center" align="center" valign="top">
|
<td class="float-center" align="center" valign="top">
|
||||||
<center>
|
<center>
|
||||||
Добро пожаловать в OpenVK! Приятного времяприпровождения, надеюсь вам понравится.<br><br>Если появились вопросы, касаемые нашего сайта, пишите <a href="https://openvk.su/support?act=new">сюда</a>
|
Добро пожаловать в OpenVK! Приятного времяприпровождения, надеюсь вам понравится.<br><br>Если появились вопросы, касаемые нашего сайта, пишите <a href="https://ovk.to/support?act=new">сюда</a>
|
||||||
</center>
|
</center>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
18
README.md
18
README.md
|
@ -1,4 +1,4 @@
|
||||||
# <img align="right" src="https://github.com/openvk/openvk/raw/master/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
|
# <img align="right" src="/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
|
||||||
|
|
||||||
_[Русский](README_RU.md)_
|
_[Русский](README_RU.md)_
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ _[Русский](README_RU.md)_
|
||||||
|
|
||||||
VKontakte belongs to Pavel Durov and VK Group.
|
VKontakte belongs to Pavel Durov and VK Group.
|
||||||
|
|
||||||
To be honest, we don't know whether if it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://openvk.su/support?act=new) (you will need an OpenVK account for this).
|
To be honest, we don't know whether if it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://ovk.to/support?act=new) (you will need an OpenVK account for this).
|
||||||
|
|
||||||
## When's the release?
|
## When's the release?
|
||||||
|
|
||||||
|
@ -26,6 +26,14 @@ However, OVK makes use of Chandler Application Server. This software requires ex
|
||||||
|
|
||||||
If you want, you can add your instance to the list above so that people can register there.
|
If you want, you can add your instance to the list above so that people can register there.
|
||||||
|
|
||||||
|
### System requirements
|
||||||
|
|
||||||
|
Here is our minimum hardware recommendation:
|
||||||
|
|
||||||
|
* **CPU: Recent** (AMD Zen2 or equivalent) quad-core 2GHz+ CPU
|
||||||
|
* **RAM:** At least 2GB RAM (we recommend 6GB or 8GB for OpenVK with Kafka)
|
||||||
|
* **Minimum database space:** 10GB
|
||||||
|
|
||||||
### Installation procedure
|
### Installation procedure
|
||||||
|
|
||||||
1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler)
|
1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler)
|
||||||
|
@ -66,12 +74,12 @@ Once you are done, you can login as a system administrator on the network itself
|
||||||
* **Password**: `admin`
|
* **Password**: `admin`
|
||||||
* It is recommended to change the password of the built-in account or disable it.
|
* It is recommended to change the password of the built-in account or disable it.
|
||||||
|
|
||||||
💡Confused? Full installation walkthrough is available [here](https://docs.openvk.uk/openvk_engine/centos8_installation/) (CentOS 8 [and](https://almalinux.org/) [family](https://yum.oracle.com/oracle-linux-isos.html)).
|
💡 Confused? Full installation walkthrough is available [here](https://docs.ovk.to/openvk_engine/centos8_installation/) (CentOS 8 [and](https://almalinux.org/) [family](https://yum.oracle.com/oracle-linux-isos.html)).
|
||||||
|
|
||||||
### Looking for Docker or Kubernetes deployment?
|
### Looking for Docker or Kubernetes deployment?
|
||||||
See `install/automated/docker/README.md` and `install/automated/kubernetes/README.md` for Docker and Kubernetes deployment instructions.
|
See `install/automated/docker/README.md` and `install/automated/kubernetes/README.md` for Docker and Kubernetes deployment instructions.
|
||||||
|
|
||||||
### If my website uses OpenVK, should I release it's sources?
|
### If my website uses OpenVK, should I release its sources?
|
||||||
|
|
||||||
It depends. You can keep the sources to yourself if you do not plan to distribute your website binaries. If your website software must be distributed, it can stay non-OSS provided the OpenVK is not used as a primary application and is not modified. If you modified OpenVK for your needs or your work is based on it and you are planning to redistribute this, then you should license it under terms of any LGPL-compatible license (like OSL, GPL, LGPL etc).
|
It depends. You can keep the sources to yourself if you do not plan to distribute your website binaries. If your website software must be distributed, it can stay non-OSS provided the OpenVK is not used as a primary application and is not modified. If you modified OpenVK for your needs or your work is based on it and you are planning to redistribute this, then you should license it under terms of any LGPL-compatible license (like OSL, GPL, LGPL etc).
|
||||||
|
|
||||||
|
@ -80,7 +88,7 @@ It depends. You can keep the sources to yourself if you do not plan to distribut
|
||||||
You may reach out to us via:
|
You may reach out to us via:
|
||||||
|
|
||||||
* [Bug Tracker](https://github.com/openvk/openvk/projects/1)
|
* [Bug Tracker](https://github.com/openvk/openvk/projects/1)
|
||||||
* [Ticketing System](https://openvk.su/support?act=new)
|
* [Ticketing System](https://ovk.to/support?act=new)
|
||||||
* Telegram Chat: Go to [our channel](https://t.me/openvkenglish) and open discussion in our channel menu.
|
* Telegram Chat: Go to [our channel](https://t.me/openvkenglish) and open discussion in our channel menu.
|
||||||
* [Reddit](https://www.reddit.com/r/openvk/)
|
* [Reddit](https://www.reddit.com/r/openvk/)
|
||||||
* [GitHub Discussions](https://github.com/openvk/openvk/discussions)
|
* [GitHub Discussions](https://github.com/openvk/openvk/discussions)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# <img align="right" src="https://github.com/openvk/openvk/raw/master/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
|
# <img align="right" src="/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
|
||||||
|
|
||||||
_[English](README.md)_
|
_[English](README.md)_
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ _[English](README.md)_
|
||||||
|
|
||||||
ВКонтакте принадлежит Павлу Дурову и VK Group.
|
ВКонтакте принадлежит Павлу Дурову и VK Group.
|
||||||
|
|
||||||
Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OpenVK).
|
Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://ovk.to/support?act=new) (для этого вам понадобится учетная запись OpenVK).
|
||||||
|
|
||||||
## Когда выйдет релизная версия?
|
## Когда выйдет релизная версия?
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
|
||||||
* **Пароль**: `admin`
|
* **Пароль**: `admin`
|
||||||
* Перед использованием встроенной учетной записи рекомендуется сменить пароль или отключить её.
|
* Перед использованием встроенной учетной записи рекомендуется сменить пароль или отключить её.
|
||||||
|
|
||||||
💡Запутались? Полное руководство по установке доступно [здесь](https://docs.openvk.uk/openvk_engine/centos8_installation/) (CentOS 8 [и](https://almalinux.org/ru/) [семейство](https://yum.oracle.com/oracle-linux-isos.html)).
|
💡Запутались? Полное руководство по установке доступно [здесь](https://docs.ovk.to/openvk_engine/centos8_installation/) (CentOS 8 [и](https://almalinux.org/ru/) [семейство](https://yum.oracle.com/oracle-linux-isos.html)).
|
||||||
|
|
||||||
# Установка в Docker/Kubernetes
|
# Установка в Docker/Kubernetes
|
||||||
Подробные иструкции можно найти в `install/automated/docker/README.md` и `install/automated/kubernetes/README.md` соответственно.
|
Подробные иструкции можно найти в `install/automated/docker/README.md` и `install/automated/kubernetes/README.md` соответственно.
|
||||||
|
@ -80,7 +80,7 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
|
||||||
Вы можете связаться с нами через:
|
Вы можете связаться с нами через:
|
||||||
|
|
||||||
* [Баг-трекер](https://github.com/openvk/openvk/projects/1)
|
* [Баг-трекер](https://github.com/openvk/openvk/projects/1)
|
||||||
* [Помощь в OVK](https://openvk.su/support?act=new)
|
* [Помощь в OVK](https://ovk.to/support?act=new)
|
||||||
* Telegram-чат: Перейдите на [наш канал](https://t.me/openvk) и откройте обсуждение в меню нашего канала.
|
* Telegram-чат: Перейдите на [наш канал](https://t.me/openvk) и откройте обсуждение в меню нашего канала.
|
||||||
* [Reddit](https://www.reddit.com/r/openvk/)
|
* [Reddit](https://www.reddit.com/r/openvk/)
|
||||||
* [GitHub Discussions](https://github.com/openvk/openvk/discussions)
|
* [GitHub Discussions](https://github.com/openvk/openvk/discussions)
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\ServiceAPI;
|
namespace openvk\ServiceAPI;
|
||||||
|
|
||||||
|
use openvk\Web\Models\Entities\APIToken;
|
||||||
use openvk\Web\Models\Entities\User;
|
use openvk\Web\Models\Entities\User;
|
||||||
|
use openvk\Web\Models\Repositories\APITokens;
|
||||||
use openvk\Web\Models\Repositories\Applications;
|
use openvk\Web\Models\Repositories\Applications;
|
||||||
|
use WhichBrowser;
|
||||||
|
|
||||||
class Apps implements Handler
|
class Apps implements Handler
|
||||||
{
|
{
|
||||||
|
@ -89,4 +92,25 @@ class Apps implements Handler
|
||||||
$app->withdrawCoins();
|
$app->withdrawCoins();
|
||||||
$resolve($coins);
|
$resolve($coins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRegularToken(string $clientName, bool $acceptsStale, callable $resolve, callable $reject): void
|
||||||
|
{
|
||||||
|
$token = NULL;
|
||||||
|
$stale = true;
|
||||||
|
if($acceptsStale)
|
||||||
|
$token = (new APITokens)->getStaleByUser($this->user->getId(), $clientName);
|
||||||
|
|
||||||
|
if(is_null($token)) {
|
||||||
|
$stale = false;
|
||||||
|
$token = new APIToken;
|
||||||
|
$token->setUser($this->user);
|
||||||
|
$token->setPlatform($clientName ?? (new WhichBrowser\Parser(getallheaders()))->toString());
|
||||||
|
$token->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$resolve([
|
||||||
|
'is_stale' => $stale,
|
||||||
|
'token' => $token->getFormattedToken(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,76 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
namespace openvk\ServiceAPI;
|
|
||||||
use openvk\Web\Models\Entities\{User, Club};
|
|
||||||
use openvk\Web\Models\Repositories\{Users, Clubs, Videos};
|
|
||||||
use Chandler\Database\DatabaseConnection;
|
|
||||||
|
|
||||||
class Search implements Handler
|
|
||||||
{
|
|
||||||
protected $user;
|
|
||||||
private $users;
|
|
||||||
private $clubs;
|
|
||||||
private $videos;
|
|
||||||
|
|
||||||
function __construct(?User $user)
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
$this->users = new Users;
|
|
||||||
$this->clubs = new Clubs;
|
|
||||||
$this->videos = new Videos;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fastSearch(string $query, string $type = "users", callable $resolve, callable $reject)
|
|
||||||
{
|
|
||||||
if($query == "" || strlen($query) < 3)
|
|
||||||
$reject(12, "No input or input < 3");
|
|
||||||
|
|
||||||
$repo;
|
|
||||||
$sort;
|
|
||||||
|
|
||||||
switch($type) {
|
|
||||||
default:
|
|
||||||
case "users":
|
|
||||||
$repo = (new Users);
|
|
||||||
$sort = "rating DESC";
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "groups":
|
|
||||||
$repo = (new Clubs);
|
|
||||||
$sort = "id ASC";
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "videos":
|
|
||||||
$repo = (new Videos);
|
|
||||||
$sort = "created ASC";
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = $repo->find($query, ["doNotSearchMe" => $this->user->getId(), "doNotSearchPrivate" => true,], $sort);
|
|
||||||
|
|
||||||
$results = array_slice(iterator_to_array($res), 0, 5);
|
|
||||||
|
|
||||||
$count = sizeof($results);
|
|
||||||
|
|
||||||
$arr = [
|
|
||||||
"count" => $count,
|
|
||||||
"items" => []
|
|
||||||
];
|
|
||||||
|
|
||||||
if(sizeof($results) < 1) {
|
|
||||||
$reject(2, "No results");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($results as $res) {
|
|
||||||
$arr["items"][] = [
|
|
||||||
"id" => $res->getId(),
|
|
||||||
"name" => $type == "users" ? $res->getCanonicalName() : $res->getName(),
|
|
||||||
"avatar" => $type != "videos" ? $res->getAvatarUrl() : $res->getThumbnailURL(),
|
|
||||||
"url" => $type != "videos" ? $res->getUrl() : "/video".$res->getPrettyId(),
|
|
||||||
"description" => ovk_proc_strtr($res->getDescription() ?? "...", 40)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$resolve($arr);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,20 +7,32 @@ final class Account extends VKAPIRequestHandler
|
||||||
function getProfileInfo(): object
|
function getProfileInfo(): object
|
||||||
{
|
{
|
||||||
$this->requireUser();
|
$this->requireUser();
|
||||||
|
$user = $this->getUser();
|
||||||
return (object) [
|
$return_object = (object) [
|
||||||
"first_name" => $this->getUser()->getFirstName(),
|
"first_name" => $user->getFirstName(),
|
||||||
"id" => $this->getUser()->getId(),
|
"photo_200" => $user->getAvatarURL("normal"),
|
||||||
"last_name" => $this->getUser()->getLastName(),
|
"nickname" => $user->getPseudo(),
|
||||||
"home_town" => $this->getUser()->getHometown(),
|
"is_service_account" => false,
|
||||||
"status" => $this->getUser()->getStatus(),
|
"id" => $user->getId(),
|
||||||
"audio_status" => is_null($this->getUser()->getCurrentAudioStatus()) ? NULL : $this->getUser()->getCurrentAudioStatus()->toVkApiStruct($this->getUser()),
|
"is_verified" => $user->isVerified(),
|
||||||
"bdate" => is_null($this->getUser()->getBirthday()) ? '01.01.1970' : $this->getUser()->getBirthday()->format('%e.%m.%Y'),
|
"verification_status" => $user->isVerified() ? 'verified' : 'unverified',
|
||||||
"bdate_visibility" => $this->getUser()->getBirthdayPrivacy(),
|
"last_name" => $user->getLastName(),
|
||||||
|
"home_town" => $user->getHometown(),
|
||||||
|
"status" => $user->getStatus(),
|
||||||
|
"bdate" => is_null($user->getBirthday()) ? '01.01.1970' : $user->getBirthday()->format('%e.%m.%Y'),
|
||||||
|
"bdate_visibility" => $user->getBirthdayPrivacy(),
|
||||||
"phone" => "+420 ** *** 228", # TODO
|
"phone" => "+420 ** *** 228", # TODO
|
||||||
"relation" => $this->getUser()->getMaritalStatus(),
|
"relation" => $user->getMaritalStatus(),
|
||||||
"sex" => $this->getUser()->isFemale() ? 1 : 2
|
"screen_name" => $user->getShortCode(),
|
||||||
|
"sex" => $user->isFemale() ? 1 : 2,
|
||||||
|
#"email" => $user->getEmail(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$audio_status = $user->getCurrentAudioStatus();
|
||||||
|
if(!is_null($audio_status))
|
||||||
|
$return_object->audio_status = $audio_status->toVkApiStruct($user);
|
||||||
|
|
||||||
|
return $return_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInfo(): object
|
function getInfo(): object
|
||||||
|
@ -152,4 +164,30 @@ final class Account extends VKAPIRequestHandler
|
||||||
|
|
||||||
return (object) $output;
|
return (object) $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getBalance(): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
if(!OPENVK_ROOT_CONF['openvk']['preferences']['commerce'])
|
||||||
|
$this->fail(105, "Commerce is disabled on this instance");
|
||||||
|
|
||||||
|
return (object) ['votes' => $this->getUser()->getCoins()];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOvkSettings(): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$settings_list = (object)[
|
||||||
|
'avatar_style' => $user->getStyleAvatar(),
|
||||||
|
'style' => $user->getStyle(),
|
||||||
|
'show_rating' => !$user->prefersNotToSeeRating(),
|
||||||
|
'nsfw_tolerance' => $user->getNsfwTolerance(),
|
||||||
|
'post_view' => $user->hasMicroblogEnabled() ? 'microblog' : 'old',
|
||||||
|
'main_page' => $user->getMainPage() == 0 ? 'my_page' : 'news',
|
||||||
|
];
|
||||||
|
|
||||||
|
return $settings_list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,7 +485,7 @@ final class Audio extends VKAPIRequestHandler
|
||||||
$this->requireUser();
|
$this->requireUser();
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
if(!is_null($album_id))
|
if(!is_null($album_id))
|
||||||
$this->fail(10, "album_id not implemented");
|
$this->fail(10, "album_id not implemented");
|
||||||
|
|
||||||
// TODO get rid of dups
|
// TODO get rid of dups
|
||||||
|
@ -581,13 +581,18 @@ final class Audio extends VKAPIRequestHandler
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchAlbums(string $query, int $offset = 0, int $limit = 25, int $drop_private = 0): object
|
function searchAlbums(string $query = '', int $offset = 0, int $limit = 25, int $drop_private = 0, int $order = 0, int $from_me = 0): object
|
||||||
{
|
{
|
||||||
$this->requireUser();
|
$this->requireUser();
|
||||||
|
|
||||||
$playlists = [];
|
$playlists = [];
|
||||||
$search = (new Audios)->searchPlaylists($query)->offsetLimit($offset, $limit);
|
$params = [];
|
||||||
foreach($search as $playlist) {
|
$order_str = (['id', 'length', 'listens'][$order] ?? 'id');
|
||||||
|
if($from_me === 1)
|
||||||
|
$params['from_me'] = $this->getUser()->getId();
|
||||||
|
|
||||||
|
$search = (new Audios)->findPlaylists($query, $params, ['type' => $order_str, 'invert' => false]);
|
||||||
|
foreach($search->offsetLimit($offset, $limit) as $playlist) {
|
||||||
if(!$playlist->canBeViewedBy($this->getUser())) {
|
if(!$playlist->canBeViewedBy($this->getUser())) {
|
||||||
if($drop_private == 0)
|
if($drop_private == 0)
|
||||||
$playlists[] = NULL;
|
$playlists[] = NULL;
|
||||||
|
@ -599,7 +604,7 @@ final class Audio extends VKAPIRequestHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
return (object) [
|
return (object) [
|
||||||
"count" => sizeof($playlists),
|
"count" => $search->size(),
|
||||||
"items" => $playlists,
|
"items" => $playlists,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ final class Friends extends VKAPIRequestHandler
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRequests(string $fields = "", int $offset = 0, int $count = 100, int $extended = 0): object
|
function getRequests(string $fields = "", int $out = 0, int $offset = 0, int $count = 100, int $extended = 0): object
|
||||||
{
|
{
|
||||||
if ($count >= 1000)
|
if ($count >= 1000)
|
||||||
$this->fail(100, "One of the required parameters was not passed or is invalid.");
|
$this->fail(100, "One of the required parameters was not passed or is invalid.");
|
||||||
|
@ -158,9 +158,18 @@ final class Friends extends VKAPIRequestHandler
|
||||||
$offset++;
|
$offset++;
|
||||||
$followers = [];
|
$followers = [];
|
||||||
|
|
||||||
foreach($this->getUser()->getFollowers($offset, $count) as $follower) {
|
if ($out != 0) {
|
||||||
$followers[$i] = $follower->getId();
|
foreach($this->getUser()->getFollowers($offset, $count) as $follower) {
|
||||||
$i++;
|
$followers[$i] = $follower->getId();
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach($this->getUser()->getRequests($offset, $count) as $follower) {
|
||||||
|
$followers[$i] = $follower->getId();
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $followers;
|
$response = $followers;
|
||||||
|
|
|
@ -6,15 +6,18 @@ use openvk\Web\Models\Entities\Notifications\GiftNotification;
|
||||||
|
|
||||||
final class Gifts extends VKAPIRequestHandler
|
final class Gifts extends VKAPIRequestHandler
|
||||||
{
|
{
|
||||||
function get(int $user_id, int $count = 10, int $offset = 0)
|
function get(int $user_id = NULL, int $count = 10, int $offset = 0)
|
||||||
{
|
{
|
||||||
$this->requireUser();
|
$this->requireUser();
|
||||||
|
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
|
||||||
$i += $offset;
|
$i += $offset;
|
||||||
|
$server_url = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
||||||
|
|
||||||
$user = (new UsersRepo)->get($user_id);
|
if($user_id)
|
||||||
|
$user = (new UsersRepo)->get($user_id);
|
||||||
|
else
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
if(!$user || $user->isDeleted())
|
if(!$user || $user->isDeleted())
|
||||||
$this->fail(177, "Invalid user");
|
$this->fail(177, "Invalid user");
|
||||||
|
@ -47,9 +50,9 @@ final class Gifts extends VKAPIRequestHandler
|
||||||
"date" => $gift->sent->timestamp(),
|
"date" => $gift->sent->timestamp(),
|
||||||
"gift" => [
|
"gift" => [
|
||||||
"id" => $gift->gift->getId(),
|
"id" => $gift->gift->getId(),
|
||||||
"thumb_256" => $gift->gift->getImage(2),
|
"thumb_256" => $server_url. $gift->gift->getImage(2),
|
||||||
"thumb_96" => $gift->gift->getImage(2),
|
"thumb_96" => $server_url . $gift->gift->getImage(2),
|
||||||
"thumb_48" => $gift->gift->getImage(2)
|
"thumb_48" => $server_url . $gift->gift->getImage(2)
|
||||||
],
|
],
|
||||||
"privacy" => 0
|
"privacy" => 0
|
||||||
];
|
];
|
||||||
|
@ -125,12 +128,13 @@ final class Gifts extends VKAPIRequestHandler
|
||||||
$this->fail(501, "Not implemented");
|
$this->fail(501, "Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
# этих методов не было в ВК, но я их добавил чтобы можно было отобразить список подарков
|
# в vk кстати называется gifts.getCatalog
|
||||||
function getCategories(bool $extended = false, int $page = 1)
|
function getCategories(bool $extended = false, int $page = 1)
|
||||||
{
|
{
|
||||||
$cats = (new GiftsRepo)->getCategories($page);
|
$cats = (new GiftsRepo)->getCategories($page);
|
||||||
$categ = [];
|
$categ = [];
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
$server_url = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
||||||
|
|
||||||
if(!OPENVK_ROOT_CONF['openvk']['preferences']['commerce'])
|
if(!OPENVK_ROOT_CONF['openvk']['preferences']['commerce'])
|
||||||
$this->fail(105, "Commerce is disabled on this instance");
|
$this->fail(105, "Commerce is disabled on this instance");
|
||||||
|
@ -140,8 +144,8 @@ final class Gifts extends VKAPIRequestHandler
|
||||||
"name" => $cat->getName(),
|
"name" => $cat->getName(),
|
||||||
"description" => $cat->getDescription(),
|
"description" => $cat->getDescription(),
|
||||||
"id" => $cat->getId(),
|
"id" => $cat->getId(),
|
||||||
"thumbnail" => $cat->getThumbnailURL(),
|
"thumbnail" => $server_url . $cat->getThumbnailURL(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if($extended == true) {
|
if($extended == true) {
|
||||||
$categ[$i]["localizations"] = [];
|
$categ[$i]["localizations"] = [];
|
||||||
|
@ -178,7 +182,7 @@ final class Gifts extends VKAPIRequestHandler
|
||||||
"name" => $gift->getName(),
|
"name" => $gift->getName(),
|
||||||
"image" => $gift->getImage(2),
|
"image" => $gift->getImage(2),
|
||||||
"usages_left" => (int)$gift->getUsagesLeft($this->getUser()),
|
"usages_left" => (int)$gift->getUsagesLeft($this->getUser()),
|
||||||
"price" => $gift->getPrice(), # голосов
|
"price" => $gift->getPrice(),
|
||||||
"is_free" => $gift->isFree()
|
"is_free" => $gift->isFree()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,10 @@ final class Groups extends VKAPIRequestHandler
|
||||||
case "can_suggest":
|
case "can_suggest":
|
||||||
$rClubs[$i]->can_suggest = !$usr->canBeModifiedBy($this->getUser()) && $usr->getWallType() == 2;
|
$rClubs[$i]->can_suggest = !$usr->canBeModifiedBy($this->getUser()) && $usr->getWallType() == 2;
|
||||||
break;
|
break;
|
||||||
|
case "background":
|
||||||
|
$backgrounds = $usr->getBackDropPictureURLs();
|
||||||
|
$rClubs[$i]->background = $backgrounds;
|
||||||
|
break;
|
||||||
# unstandard feild
|
# unstandard feild
|
||||||
case "suggested_count":
|
case "suggested_count":
|
||||||
if($usr->getWallType() != 2) {
|
if($usr->getWallType() != 2) {
|
||||||
|
@ -208,6 +212,10 @@ final class Groups extends VKAPIRequestHandler
|
||||||
case "can_suggest":
|
case "can_suggest":
|
||||||
$response[$i]->can_suggest = !$clb->canBeModifiedBy($this->getUser()) && $clb->getWallType() == 2;
|
$response[$i]->can_suggest = !$clb->canBeModifiedBy($this->getUser()) && $clb->getWallType() == 2;
|
||||||
break;
|
break;
|
||||||
|
case "background":
|
||||||
|
$backgrounds = $clb->getBackDropPictureURLs();
|
||||||
|
$response[$i]->background = $backgrounds;
|
||||||
|
break;
|
||||||
# unstandard feild
|
# unstandard feild
|
||||||
case "suggested_count":
|
case "suggested_count":
|
||||||
if($clb->getWallType() != 2) {
|
if($clb->getWallType() != 2) {
|
||||||
|
@ -244,23 +252,30 @@ final class Groups extends VKAPIRequestHandler
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(string $q, int $offset = 0, int $count = 100)
|
function search(string $q, int $offset = 0, int $count = 100, string $fields = "screen_name,is_admin,is_member,is_advertiser,photo_50,photo_100,photo_200")
|
||||||
{
|
{
|
||||||
|
if($count > 100) {
|
||||||
|
$this->fail(100, "One of the parameters specified was missing or invalid: count should be less or equal to 100");
|
||||||
|
}
|
||||||
|
|
||||||
$clubs = new ClubsRepo;
|
$clubs = new ClubsRepo;
|
||||||
|
|
||||||
$array = [];
|
$array = [];
|
||||||
$find = $clubs->find($q);
|
$find = $clubs->find($q);
|
||||||
|
|
||||||
foreach ($find as $group)
|
foreach ($find->offsetLimit($offset, $count) as $group)
|
||||||
$array[] = $group->getId();
|
$array[] = $group->getId();
|
||||||
|
|
||||||
|
if(!$array || sizeof($array) < 1) {
|
||||||
|
return (object) [
|
||||||
|
"count" => 0,
|
||||||
|
"items" => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return (object) [
|
return (object) [
|
||||||
"count" => $find->size(),
|
"count" => $find->size(),
|
||||||
"items" => $this->getById(implode(',', $array), "", "is_admin,is_member,is_advertiser,photo_50,photo_100,photo_200", $offset, $count)
|
"items" => $this->getById(implode(',', $array), "", $fields)
|
||||||
/*
|
|
||||||
* As there is no thing as "fields" by the original documentation
|
|
||||||
* i'll just bake this param by the example shown here: https://dev.vk.com/method/groups.search
|
|
||||||
*/
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,7 +362,10 @@ final class Groups extends VKAPIRequestHandler
|
||||||
!empty($topics) ? $club->setEveryone_Can_Create_Topics($topics) : NULL;
|
!empty($topics) ? $club->setEveryone_Can_Create_Topics($topics) : NULL;
|
||||||
!empty($adminlist) ? $club->setAdministrators_List_Display($adminlist) : NULL;
|
!empty($adminlist) ? $club->setAdministrators_List_Display($adminlist) : NULL;
|
||||||
!empty($topicsAboveWall) ? $club->setDisplay_Topics_Above_Wall($topicsAboveWall) : NULL;
|
!empty($topicsAboveWall) ? $club->setDisplay_Topics_Above_Wall($topicsAboveWall) : NULL;
|
||||||
!empty($hideFromGlobalFeed) ? $club->setHide_From_Global_Feed($hideFromGlobalFeed) : NULL;
|
|
||||||
|
if (!$club->isHidingFromGlobalFeedEnforced()) {
|
||||||
|
!empty($hideFromGlobalFeed) ? $club->setHide_From_Global_Feed($hideFromGlobalFeed) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
in_array($audio, [0, 1]) ? $club->setEveryone_can_upload_audios($audio) : NULL;
|
in_array($audio, [0, 1]) ? $club->setEveryone_can_upload_audios($audio) : NULL;
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
}
|
}
|
||||||
case "music":
|
case "music":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->music = "secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +158,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "movies":
|
case "movies":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->movies = "secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +165,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "tv":
|
case "tv":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->tv = "secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +172,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "books":
|
case "books":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->books = "secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +179,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "city":
|
case "city":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->city = "Воскресенск";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +186,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "interests":
|
case "interests":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->interests = "secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +193,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "quotes":
|
case "quotes":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->quotes = "secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +200,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "email":
|
case "email":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->email = "secret@gmail.com";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +207,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "telegram":
|
case "telegram":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->telegram = "@secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +214,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "about":
|
case "about":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->about = "secret";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +221,6 @@ final class Users extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
case "rating":
|
case "rating":
|
||||||
if(!$canView) {
|
if(!$canView) {
|
||||||
$response[$i]->rating = 22;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,12 +229,43 @@ final class Users extends VKAPIRequestHandler
|
||||||
case "counters":
|
case "counters":
|
||||||
$response[$i]->counters = (object) [
|
$response[$i]->counters = (object) [
|
||||||
"friends_count" => $usr->getFriendsCount(),
|
"friends_count" => $usr->getFriendsCount(),
|
||||||
"photos_count" => (new Albums)->getUserPhotosCount($usr),
|
"photos_count" => (new Photos)->getUserPhotosCount($usr),
|
||||||
"videos_count" => (new Videos)->getUserVideosCount($usr),
|
"videos_count" => (new Videos)->getUserVideosCount($usr),
|
||||||
"audios_count" => (new Audios)->getUserCollectionSize($usr),
|
"audios_count" => (new Audios)->getUserCollectionSize($usr),
|
||||||
"notes_count" => (new Notes)->getUserNotesCount($usr)
|
"notes_count" => (new Notes)->getUserNotesCount($usr)
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
|
case "correct_counters":
|
||||||
|
$response[$i]->counters = (object) [
|
||||||
|
"friends" => $usr->getFriendsCount(),
|
||||||
|
"photos" => (new Photos)->getUserPhotosCount($usr),
|
||||||
|
"videos" => (new Videos)->getUserVideosCount($usr),
|
||||||
|
"audios" => (new Audios)->getUserCollectionSize($usr),
|
||||||
|
"notes" => (new Notes)->getUserNotesCount($usr),
|
||||||
|
"groups" => $usr->getClubCount(),
|
||||||
|
"online_friends" => $usr->getFriendsOnlineCount(),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case "guid":
|
||||||
|
$response[$i]->guid = $usr->getChandlerGUID();
|
||||||
|
break;
|
||||||
|
case 'background':
|
||||||
|
$backgrounds = $usr->getBackDropPictureURLs();
|
||||||
|
$response[$i]->background = $backgrounds;
|
||||||
|
break;
|
||||||
|
case 'reg_date':
|
||||||
|
if(!$canView) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response[$i]->reg_date = $usr->getRegistrationTime()->timestamp();
|
||||||
|
break;
|
||||||
|
case 'is_dead':
|
||||||
|
$response[$i]->is_dead = $usr->isDead();
|
||||||
|
break;
|
||||||
|
case 'nickname':
|
||||||
|
$response[$i]->nickname = $usr->getPseudo();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,89 +317,90 @@ final class Users extends VKAPIRequestHandler
|
||||||
int $count = 100,
|
int $count = 100,
|
||||||
string $city = "",
|
string $city = "",
|
||||||
string $hometown = "",
|
string $hometown = "",
|
||||||
int $sex = 2,
|
int $sex = 3,
|
||||||
int $status = 0, # это про marital status
|
int $status = 0, # marital_status
|
||||||
bool $online = false,
|
bool $online = false,
|
||||||
# дальше идут параметры которых нету в vkapi но есть на сайте
|
# non standart params:
|
||||||
string $profileStatus = "", # а это уже нормальный статус
|
|
||||||
int $sort = 0,
|
int $sort = 0,
|
||||||
int $before = 0,
|
int $polit_views = 0,
|
||||||
int $politViews = 0,
|
|
||||||
int $after = 0,
|
|
||||||
string $interests = "",
|
|
||||||
string $fav_music = "",
|
string $fav_music = "",
|
||||||
string $fav_films = "",
|
string $fav_films = "",
|
||||||
string $fav_shows = "",
|
string $fav_shows = "",
|
||||||
string $fav_books = "",
|
string $fav_books = ""
|
||||||
string $fav_quotes = ""
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$users = new UsersRepo;
|
if($count > 100) {
|
||||||
|
$this->fail(100, "One of the parameters specified was missing or invalid: count should be less or equal to 100");
|
||||||
$sortg = "id ASC";
|
}
|
||||||
|
|
||||||
$nfilds = $fields;
|
$users = new UsersRepo;
|
||||||
|
$output_sort = ['type' => 'id', 'invert' => false];
|
||||||
|
$output_params = [
|
||||||
|
"ignore_private" => true,
|
||||||
|
];
|
||||||
|
|
||||||
switch($sort) {
|
switch($sort) {
|
||||||
|
default:
|
||||||
case 0:
|
case 0:
|
||||||
$sortg = "id DESC";
|
$output_sort = ['type' => 'id', 'invert' => false];
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
$sortg = "id ASC";
|
$output_sort = ['type' => 'id', 'invert' => true];
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
$sortg = "first_name DESC";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
$sortg = "first_name ASC";
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
$sortg = "rating DESC";
|
$output_sort = ['type' => 'rating', 'invert' => false];
|
||||||
|
|
||||||
if(!str_contains($nfilds, "rating")) {
|
|
||||||
$nfilds .= "rating";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
$sortg = "rating DESC";
|
|
||||||
|
|
||||||
if(!str_contains($nfilds, "rating")) {
|
|
||||||
$nfilds .= "rating";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!empty($city))
|
||||||
|
$output_params['city'] = $city;
|
||||||
|
|
||||||
|
if(!empty($hometown))
|
||||||
|
$output_params['hometown'] = $hometown;
|
||||||
|
|
||||||
|
if($sex != 3)
|
||||||
|
$output_params['gender'] = $sex;
|
||||||
|
|
||||||
|
if($status != 0)
|
||||||
|
$output_params['marital_status'] = $status;
|
||||||
|
|
||||||
|
if($polit_views != 0)
|
||||||
|
$output_params['polit_views'] = $polit_views;
|
||||||
|
|
||||||
|
if(!empty($interests))
|
||||||
|
$output_params['interests'] = $interests;
|
||||||
|
|
||||||
|
if(!empty($fav_music))
|
||||||
|
$output_params['fav_music'] = $fav_music;
|
||||||
|
|
||||||
|
if(!empty($fav_films))
|
||||||
|
$output_params['fav_films'] = $fav_films;
|
||||||
|
|
||||||
|
if(!empty($fav_shows))
|
||||||
|
$output_params['fav_shows'] = $fav_shows;
|
||||||
|
|
||||||
|
if(!empty($fav_books))
|
||||||
|
$output_params['fav_books'] = $fav_books;
|
||||||
|
|
||||||
|
if($online)
|
||||||
|
$output_params['is_online'] = 1;
|
||||||
|
|
||||||
$array = [];
|
$array = [];
|
||||||
|
$find = $users->find($q, $output_params, $output_sort);
|
||||||
|
|
||||||
$parameters = [
|
foreach ($find->offsetLimit($offset, $count) as $user)
|
||||||
"city" => !empty($city) ? $city : NULL,
|
|
||||||
"hometown" => !empty($hometown) ? $hometown : NULL,
|
|
||||||
"gender" => $sex < 2 ? $sex : NULL,
|
|
||||||
"maritalstatus" => (bool)$status ? $status : NULL,
|
|
||||||
"politViews" => (bool)$politViews ? $politViews : NULL,
|
|
||||||
"is_online" => $online ? 1 : NULL,
|
|
||||||
"status" => !empty($profileStatus) ? $profileStatus : NULL,
|
|
||||||
"before" => $before != 0 ? $before : NULL,
|
|
||||||
"after" => $after != 0 ? $after : NULL,
|
|
||||||
"interests" => !empty($interests) ? $interests : NULL,
|
|
||||||
"fav_music" => !empty($fav_music) ? $fav_music : NULL,
|
|
||||||
"fav_films" => !empty($fav_films) ? $fav_films : NULL,
|
|
||||||
"fav_shows" => !empty($fav_shows) ? $fav_shows : NULL,
|
|
||||||
"fav_books" => !empty($fav_books) ? $fav_books : NULL,
|
|
||||||
"fav_quotes" => !empty($fav_quotes) ? $fav_quotes : NULL,
|
|
||||||
"doNotSearchPrivate" => true,
|
|
||||||
];
|
|
||||||
|
|
||||||
$find = $users->find($q, $parameters, $sortg);
|
|
||||||
|
|
||||||
foreach ($find as $user)
|
|
||||||
$array[] = $user->getId();
|
$array[] = $user->getId();
|
||||||
|
|
||||||
|
if(!$array || sizeof($array) < 1) {
|
||||||
|
return (object) [
|
||||||
|
"count" => 0,
|
||||||
|
"items" => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return (object) [
|
return (object) [
|
||||||
"count" => $find->size(),
|
"count" => $find->size(),
|
||||||
"items" => $this->get(implode(',', $array), $nfilds, $offset, $count)
|
"items" => $this->get(implode(',', $array), $fields)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ final class Utils extends VKAPIRequestHandler
|
||||||
"object_id" => (int) substr($screen_name, strlen("club")),
|
"object_id" => (int) substr($screen_name, strlen("club")),
|
||||||
"type" => "group"
|
"type" => "group"
|
||||||
];
|
];
|
||||||
}
|
} else $this->fail(104, "Not found");
|
||||||
} else {
|
} else {
|
||||||
$user = (new Users)->getByShortURL($screen_name);
|
$user = (new Users)->getByShortURL($screen_name);
|
||||||
if($user) {
|
if($user) {
|
||||||
|
@ -39,8 +39,17 @@ final class Utils extends VKAPIRequestHandler
|
||||||
"type" => "group"
|
"type" => "group"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (object) [];
|
$this->fail(104, "Not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveGuid(string $guid): object
|
||||||
|
{
|
||||||
|
$user = (new Users)->getByChandlerUserId($guid);
|
||||||
|
if (is_null($user))
|
||||||
|
$this->fail(104, "Not found");
|
||||||
|
|
||||||
|
return $user->toVkApiStruct($this->getUser());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,4 +60,60 @@ final class Video extends VKAPIRequestHandler
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function search(string $q = '', int $sort = 0, int $offset = 0, int $count = 10, bool $extended = false, string $fields = ''): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
$params = [];
|
||||||
|
$db_sort = ['type' => 'id', 'invert' => false];
|
||||||
|
$videos = (new VideosRepo)->find($q, $params, $db_sort);
|
||||||
|
$items = iterator_to_array($videos->offsetLimit($offset, $count));
|
||||||
|
$count = $videos->size();
|
||||||
|
|
||||||
|
$return_items = [];
|
||||||
|
$profiles = [];
|
||||||
|
$groups = [];
|
||||||
|
foreach($items as $item)
|
||||||
|
$return_item = $item->getApiStructure($this->getUser());
|
||||||
|
$return_item = $return_item->video;
|
||||||
|
$return_items[] = $return_item;
|
||||||
|
|
||||||
|
if($return_item['owner_id']) {
|
||||||
|
if($return_item['owner_id'] > 0)
|
||||||
|
$profiles[] = $return_item['owner_id'];
|
||||||
|
else
|
||||||
|
$groups[] = abs($return_item['owner_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($extended) {
|
||||||
|
$profiles = array_unique($profiles);
|
||||||
|
$groups = array_unique($groups);
|
||||||
|
|
||||||
|
$profilesFormatted = [];
|
||||||
|
$groupsFormatted = [];
|
||||||
|
|
||||||
|
foreach($profiles as $prof) {
|
||||||
|
$profile = (new UsersRepo)->get($prof);
|
||||||
|
$profilesFormatted[] = $profile->toVkApiStruct($this->getUser(), $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($groups as $gr) {
|
||||||
|
$group = (new ClubsRepo)->get($gr);
|
||||||
|
$groupsFormatted[] = $group->toVkApiStruct($this->getUser(), $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
"count" => $count,
|
||||||
|
"items" => $return_items,
|
||||||
|
"profiles" => $profilesFormatted,
|
||||||
|
"groups" => $groupsFormatted,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
"count" => $count,
|
||||||
|
"items" => $return_items,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,65 +126,41 @@ final class Wall extends VKAPIRequestHandler
|
||||||
else
|
else
|
||||||
$profiles[] = $attachment->getOwner()->getId();
|
$profiles[] = $attachment->getOwner()->getId();
|
||||||
|
|
||||||
$post_source = [];
|
|
||||||
|
|
||||||
if($attachment->getPlatform(true) === NULL) {
|
|
||||||
$post_source = (object)["type" => "vk"];
|
|
||||||
} else {
|
|
||||||
$post_source = (object)[
|
|
||||||
"type" => "api",
|
|
||||||
"platform" => $attachment->getPlatform(true)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$repost[] = [
|
$repost[] = [
|
||||||
"id" => $attachment->getVirtualId(),
|
"id" => $attachment->getVirtualId(),
|
||||||
"owner_id" => $attachment->isPostedOnBehalfOfGroup() ? $attachment->getOwner()->getId() * -1 : $attachment->getOwner()->getId(),
|
"owner_id" => $attachment->isPostedOnBehalfOfGroup() ? $attachment->getOwner()->getId() * -1 : $attachment->getOwner()->getId(),
|
||||||
"from_id" => $attachment->isPostedOnBehalfOfGroup() ? $attachment->getOwner()->getId() * -1 : $attachment->getOwner()->getId(),
|
"from_id" => $attachment->isPostedOnBehalfOfGroup() ? $attachment->getOwner()->getId() * -1 : $attachment->getOwner()->getId(),
|
||||||
"date" => $attachment->getPublicationTime()->timestamp(),
|
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||||
"post_type" => "post",
|
"post_type" => $attachment->getVkApiType(),
|
||||||
"text" => $attachment->getText(false),
|
"text" => $attachment->getText(false),
|
||||||
"attachments" => $repostAttachments,
|
"attachments" => $repostAttachments,
|
||||||
"post_source" => $post_source,
|
"post_source" => $attachment->getPostSourceInfo(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($attachment->getVirtualId() > 0)
|
if ($attachment->getTargetWall() > 0)
|
||||||
$profiles[] = $attachment->getVirtualId();
|
$profiles[] = $attachment->getTargetWall();
|
||||||
else
|
else
|
||||||
$groups[] = $attachment->getVirtualId();
|
$groups[] = abs($attachment->getTargetWall());
|
||||||
if($post->isSigned())
|
if($post->isSigned())
|
||||||
$profiles[] = $attachment->getOwner()->getId();
|
$profiles[] = $attachment->getOwner()->getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$post_source = [];
|
|
||||||
|
|
||||||
if($post->getPlatform(true) === NULL) {
|
|
||||||
$post_source = (object)["type" => "vk"];
|
|
||||||
} else {
|
|
||||||
$post_source = (object)[
|
|
||||||
"type" => "api",
|
|
||||||
"platform" => $post->getPlatform(true)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$postType = "post";
|
|
||||||
$signerId = NULL;
|
$signerId = NULL;
|
||||||
if($post->getSuggestionType() != 0)
|
|
||||||
$postType = "suggest";
|
|
||||||
|
|
||||||
|
|
||||||
if($post->isSigned()) {
|
if($post->isSigned()) {
|
||||||
$actualAuthor = $post->getOwner(false);
|
$actualAuthor = $post->getOwner(false);
|
||||||
$signerId = $actualAuthor->getId();
|
$signerId = $actualAuthor->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
$items[] = (object)[
|
# TODO "can_pin", "copy_history" и прочее не должны возвращаться, если равны null или false
|
||||||
|
# Ну и ещё всё надо перенести в toVkApiStruct, а то слишком много дублированного кода
|
||||||
|
|
||||||
|
$post_temp_obj = (object)[
|
||||||
"id" => $post->getVirtualId(),
|
"id" => $post->getVirtualId(),
|
||||||
"from_id" => $from_id,
|
"from_id" => $from_id,
|
||||||
"owner_id" => $post->getTargetWall(),
|
"owner_id" => $post->getTargetWall(),
|
||||||
"date" => $post->getPublicationTime()->timestamp(),
|
"date" => $post->getPublicationTime()->timestamp(),
|
||||||
"post_type" => $postType,
|
"post_type" => $post->getVkApiType(),
|
||||||
"text" => $post->getText(false),
|
"text" => $post->getText(false),
|
||||||
"copy_history" => $repost,
|
"copy_history" => $repost,
|
||||||
"can_edit" => $post->canBeEditedBy($this->getUser()),
|
"can_edit" => $post->canBeEditedBy($this->getUser()),
|
||||||
|
@ -195,8 +171,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"is_pinned" => $post->isPinned(),
|
"is_pinned" => $post->isPinned(),
|
||||||
"is_explicit" => $post->isExplicit(),
|
"is_explicit" => $post->isExplicit(),
|
||||||
"attachments" => $attachments,
|
"attachments" => $attachments,
|
||||||
"post_source" => $post_source,
|
"post_source" => $post->getPostSourceInfo(),
|
||||||
"signer_id" => $signerId,
|
|
||||||
"comments" => (object)[
|
"comments" => (object)[
|
||||||
"count" => $post->getCommentsCount(),
|
"count" => $post->getCommentsCount(),
|
||||||
"can_post" => 1
|
"can_post" => 1
|
||||||
|
@ -213,6 +188,14 @@ final class Wall extends VKAPIRequestHandler
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if($signerId)
|
||||||
|
$post_temp_obj->signer_id = $signerId;
|
||||||
|
|
||||||
|
if($post->isDeactivationMessage())
|
||||||
|
$post_temp_obj->final_post = 1;
|
||||||
|
|
||||||
|
$items[] = $post_temp_obj;
|
||||||
|
|
||||||
if ($from_id > 0)
|
if ($from_id > 0)
|
||||||
$profiles[] = $from_id;
|
$profiles[] = $from_id;
|
||||||
else
|
else
|
||||||
|
@ -332,17 +315,6 @@ final class Wall extends VKAPIRequestHandler
|
||||||
else
|
else
|
||||||
$profiles[] = $attachment->getOwner()->getId();
|
$profiles[] = $attachment->getOwner()->getId();
|
||||||
|
|
||||||
$post_source = [];
|
|
||||||
|
|
||||||
if($attachment->getPlatform(true) === NULL) {
|
|
||||||
$post_source = (object)["type" => "vk"];
|
|
||||||
} else {
|
|
||||||
$post_source = (object)[
|
|
||||||
"type" => "api",
|
|
||||||
"platform" => $attachment->getPlatform(true)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$repost[] = [
|
$repost[] = [
|
||||||
"id" => $attachment->getVirtualId(),
|
"id" => $attachment->getVirtualId(),
|
||||||
"owner_id" => $attachment->isPostedOnBehalfOfGroup() ? $attachment->getOwner()->getId() * -1 : $attachment->getOwner()->getId(),
|
"owner_id" => $attachment->isPostedOnBehalfOfGroup() ? $attachment->getOwner()->getId() * -1 : $attachment->getOwner()->getId(),
|
||||||
|
@ -351,47 +323,29 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"post_type" => "post",
|
"post_type" => "post",
|
||||||
"text" => $attachment->getText(false),
|
"text" => $attachment->getText(false),
|
||||||
"attachments" => $repostAttachments,
|
"attachments" => $repostAttachments,
|
||||||
"post_source" => $post_source,
|
"post_source" => $attachment->getPostSourceInfo(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($attachment->getVirtualId() > 0)
|
if ($attachment->getTargetWall() > 0)
|
||||||
$profiles[] = $attachment->getVirtualId();
|
$profiles[] = $attachment->getTargetWall();
|
||||||
else
|
else
|
||||||
$groups[] = $attachment->getVirtualId();
|
$groups[] = abs($attachment->getTargetWall());
|
||||||
if($post->isSigned())
|
if($post->isSigned())
|
||||||
$profiles[] = $attachment->getOwner()->getId();
|
$profiles[] = $attachment->getOwner()->getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$post_source = [];
|
|
||||||
|
|
||||||
if($post->getPlatform(true) === NULL) {
|
|
||||||
$post_source = (object)["type" => "vk"];
|
|
||||||
} else {
|
|
||||||
$post_source = (object)[
|
|
||||||
"type" => "api",
|
|
||||||
"platform" => $post->getPlatform(true)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: $post->getVkApiType()
|
|
||||||
$postType = "post";
|
|
||||||
$signerId = NULL;
|
|
||||||
if($post->getSuggestionType() != 0)
|
|
||||||
$postType = "suggest";
|
|
||||||
|
|
||||||
|
|
||||||
if($post->isSigned()) {
|
if($post->isSigned()) {
|
||||||
$actualAuthor = $post->getOwner(false);
|
$actualAuthor = $post->getOwner(false);
|
||||||
$signerId = $actualAuthor->getId();
|
$signerId = $actualAuthor->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
$items[] = (object)[
|
$post_temp_obj = (object)[
|
||||||
"id" => $post->getVirtualId(),
|
"id" => $post->getVirtualId(),
|
||||||
"from_id" => $from_id,
|
"from_id" => $from_id,
|
||||||
"owner_id" => $post->getTargetWall(),
|
"owner_id" => $post->getTargetWall(),
|
||||||
"date" => $post->getPublicationTime()->timestamp(),
|
"date" => $post->getPublicationTime()->timestamp(),
|
||||||
"post_type" => $postType,
|
"post_type" => $post->getVkApiType(),
|
||||||
"text" => $post->getText(false),
|
"text" => $post->getText(false),
|
||||||
"copy_history" => $repost,
|
"copy_history" => $repost,
|
||||||
"can_edit" => $post->canBeEditedBy($this->getUser()),
|
"can_edit" => $post->canBeEditedBy($this->getUser()),
|
||||||
|
@ -401,8 +355,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"is_archived" => false,
|
"is_archived" => false,
|
||||||
"is_pinned" => $post->isPinned(),
|
"is_pinned" => $post->isPinned(),
|
||||||
"is_explicit" => $post->isExplicit(),
|
"is_explicit" => $post->isExplicit(),
|
||||||
"post_source" => $post_source,
|
"post_source" => $post->getPostSourceInfo(),
|
||||||
"signer_id" => $signerId,
|
|
||||||
"attachments" => $attachments,
|
"attachments" => $attachments,
|
||||||
"comments" => (object)[
|
"comments" => (object)[
|
||||||
"count" => $post->getCommentsCount(),
|
"count" => $post->getCommentsCount(),
|
||||||
|
@ -420,6 +373,14 @@ final class Wall extends VKAPIRequestHandler
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if($signerId)
|
||||||
|
$post_temp_obj->signer_id = $signerId;
|
||||||
|
|
||||||
|
if($post->isDeactivationMessage())
|
||||||
|
$post_temp_obj->final_post = 1;
|
||||||
|
|
||||||
|
$items[] = $post_temp_obj;
|
||||||
|
|
||||||
if ($from_id > 0)
|
if ($from_id > 0)
|
||||||
$profiles[] = $from_id;
|
$profiles[] = $from_id;
|
||||||
else
|
else
|
||||||
|
@ -792,6 +753,9 @@ final class Wall extends VKAPIRequestHandler
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if($comment->isFromPostAuthor($post))
|
||||||
|
$item['is_from_post_author'] = true;
|
||||||
|
|
||||||
if($need_likes == true)
|
if($need_likes == true)
|
||||||
$item['likes'] = [
|
$item['likes'] = [
|
||||||
"can_like" => 1,
|
"can_like" => 1,
|
||||||
|
@ -875,6 +839,9 @@ final class Wall extends VKAPIRequestHandler
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if($comment->isFromPostAuthor())
|
||||||
|
$item['is_from_post_author'] = true;
|
||||||
|
|
||||||
if($extended == true)
|
if($extended == true)
|
||||||
$profiles[] = $comment->getOwner()->getId();
|
$profiles[] = $comment->getOwner()->getId();
|
||||||
|
|
||||||
|
@ -890,8 +857,6 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$response['profiles'] = (!empty($profiles) ? (new Users)->get(implode(',', $profiles), $fields) : []);
|
$response['profiles'] = (!empty($profiles) ? (new Users)->get(implode(',', $profiles), $fields) : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ exceptions. It is still a work-in-progress functionality.
|
||||||
**Note**: requests to API are routed through
|
**Note**: requests to API are routed through
|
||||||
openvk.Web.Presenters.VKAPIPresenter, this dir contains only handlers.
|
openvk.Web.Presenters.VKAPIPresenter, this dir contains only handlers.
|
||||||
|
|
||||||
[Documentation for API clients](https://docs.openvk.uk/openvk_engine/api/description/)
|
[Documentation for API clients](https://docs.ovk.to/openvk_engine/api/description/)
|
||||||
|
|
||||||
## Implementing API methods
|
## Implementing API methods
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ class Audio extends Media
|
||||||
|
|
||||||
# Taken from winamp :D
|
# Taken from winamp :D
|
||||||
const genres = [
|
const genres = [
|
||||||
'Blues','Big Band','Classic Rock','Chorus','Country','Easy Listening','Dance','Acoustic','Disco','Humour','Funk','Speech','Grunge','Chanson','Hip-Hop','Opera','Jazz','Chamber Music','Metal','Sonata','New Age','Symphony','Oldies','Booty Bass','Other','Primus','Pop','Porn Groove','R&B','Satire','Rap','Slow Jam','Reggae','Club','Rock','Tango','Techno','Samba','Industrial','Folklore','Alternative','Ballad','Ska','Power Ballad','Death Metal','Rhythmic Soul','Pranks','Freestyle','Soundtrack','Duet','Euro-Techno','Punk Rock','Ambient','Drum Solo','Trip-Hop','A Cappella','Vocal','Euro-House','Jazz+Funk','Dance Hall','Fusion','Goa','Trance','Drum & Bass','Classical','Club-House','Instrumental','Hardcore','Acid','Terror','House','Indie','Game','BritPop','Sound Clip','Negerpunk','Gospel','Polsk Punk','Noise','Beat','AlternRock','Christian Gangsta Rap','Bass','Heavy Metal','Soul','Black Metal','Punk','Crossover','Space','Contemporary Christian','Meditative','Christian Rock','Instrumental Pop','Merengue','Instrumental Rock','Salsa','Ethnic','Thrash Metal','Gothic','Anime','Darkwave','JPop','Techno-Industrial','Synthpop','Electronic','Abstract','Pop-Folk','Art Rock','Eurodance','Baroque','Dream','Bhangra','Southern Rock','Big Beat','Comedy','Breakbeat','Cult','Chillout','Gangsta Rap','Downtempo','Top 40','Dub','Christian Rap','EBM','Pop / Funk','Eclectic','Jungle','Electro','Native American','Electroclash','Cabaret','Emo','New Wave','Experimental','Psychedelic','Garage','Rave','Global','Showtunes','IDM','Trailer','Illbient','Lo-Fi','Industro-Goth','Tribal','Jam Band','Acid Punk','Krautrock','Acid Jazz','Leftfield','Polka','Lounge','Retro','Math Rock','Musical','New Romantic','Rock & Roll','Nu-Breakz','Hard Rock','Post-Punk','Folk','Post-Rock','Folk-Rock','Psytrance','National Folk','Shoegaze','Swing','Space Rock','Fast Fusion','Trop Rock','Bebob','World Music','Latin','Neoclassical','Revival','Audiobook','Celtic','Audio Theatre','Bluegrass','Neue Deutsche Welle','Avantgarde','Podcast','Gothic Rock','Indie Rock','Progressive Rock','G-Funk','Psychedelic Rock','Dubstep','Symphonic Rock','Garage Rock','Slow Rock','Psybient','Psychobilly','Touhou'
|
'A Cappella', 'Abstract', 'Acid', 'Acid Jazz', 'Acid Punk', 'Acoustic', 'AlternRock', 'Alternative', 'Ambient', 'Anime', 'Art Rock', 'Audio Theatre', 'Audiobook', 'Avantgarde', 'Ballad', 'Baroque', 'Bass', 'Beat', 'Bebob', 'Bhangra', 'Big Band', 'Big Beat', 'Black Metal', 'Bluegrass', 'Blues', 'Booty Bass', 'Breakbeat', 'BritPop', 'Cabaret', 'Celtic', 'Chamber Music', 'Chanson', 'Chillout', 'Chorus', 'Christian Gangsta Rap', 'Christian Rap', 'Christian Rock', 'Classic Rock', 'Classical', 'Club', 'Club-House', 'Comedy', 'Contemporary Christian', 'Country', 'Crossover', 'Cult', 'Dance', 'Dance Hall', 'Darkwave', 'Death Metal', 'Disco', 'Downtempo', 'Dream', 'Drum & Bass', 'Drum Solo', 'Dub', 'Dubstep', 'Duet', 'EBM', 'Easy Listening', 'Eclectic', 'Electro', 'Electroclash', 'Electronic', 'Emo', 'Ethnic', 'Euro-House', 'Euro-Techno', 'Eurodance', 'Experimental', 'Fast Fusion', 'Folk', 'Folk-Rock', 'Folklore', 'Freestyle', 'Funk', 'Fusion', 'G-Funk', 'Game', 'Gangsta Rap', 'Garage', 'Garage Rock', 'Global', 'Goa', 'Gospel', 'Gothic', 'Gothic Rock', 'Grunge', 'Hard Rock', 'Hardcore', 'Heavy Metal', 'Hip-Hop', 'House', 'Humour', 'IDM', 'Illbient', 'Indie', 'Indie Rock', 'Industrial', 'Industro-Goth', 'Instrumental', 'Instrumental Pop', 'Instrumental Rock', 'JPop', 'Jam Band', 'Jazz', 'Jazz+Funk', 'Jungle', 'Krautrock', 'Latin', 'Leftfield', 'Lo-Fi', 'Lounge', 'Math Rock', 'Meditative', 'Merengue', 'Metal', 'Musical', 'National Folk', 'Native American', 'Negerpunk', 'Neoclassical', 'Neue Deutsche Welle', 'New Age', 'New Romantic', 'New Wave', 'Noise', 'Nu-Breakz', 'Oldies', 'Opera', 'Other', 'Podcast', 'Polka', 'Polsk Punk', 'Pop', 'Pop / Funk', 'Pop-Folk', 'Porn Groove', 'Post-Punk', 'Post-Rock', 'Power Ballad', 'Pranks', 'Primus', 'Progressive Rock', 'Psybient', 'Psychedelic', 'Psychedelic Rock', 'Psychobilly', 'Psytrance', 'Punk', 'Punk Rock', 'R&B', 'Rap', 'Rave', 'Reggae', 'Retro', 'Revival', 'Rhythmic Soul', 'Rock', 'Rock & Roll', 'Salsa', 'Samba', 'Satire', 'Shoegaze', 'Showtunes', 'Ska', 'Slow Jam', 'Slow Rock', 'Sonata', 'Soul', 'Sound Clip', 'Soundtrack', 'Southern Rock', 'Space', 'Space Rock', 'Speech', 'Swing', 'Symphonic Rock', 'Symphony', 'Synthpop', 'Tango', 'Techno', 'Techno-Industrial', 'Terror', 'Thrash Metal', 'Top 40', 'Touhou', 'Trailer', 'Trance', 'Tribal', 'Trip-Hop', 'Trop Rock', 'Vocal', 'World Music'
|
||||||
];
|
];
|
||||||
|
|
||||||
# Taken from: https://web.archive.org/web/20220322153107/https://dev.vk.com/reference/objects/audio-genres
|
# Taken from: https://web.archive.org/web/20220322153107/https://dev.vk.com/reference/objects/audio-genres
|
||||||
|
@ -152,6 +152,11 @@ class Audio extends Media
|
||||||
return $this->getPerformer() . " — " . $this->getTitle();
|
return $this->getPerformer() . " — " . $this->getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDownloadName(): string
|
||||||
|
{
|
||||||
|
return preg_replace('/[\\/:*?"<>|]/', '_', str_replace(' ', '_', $this->getName()));
|
||||||
|
}
|
||||||
|
|
||||||
function getGenre(): ?string
|
function getGenre(): ?string
|
||||||
{
|
{
|
||||||
return $this->getRecord()->genre;
|
return $this->getRecord()->genre;
|
||||||
|
|
|
@ -152,6 +152,11 @@ class Club extends RowModel
|
||||||
return (bool) $this->getRecord()->hide_from_global_feed;
|
return (bool) $this->getRecord()->hide_from_global_feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isHidingFromGlobalFeedEnforced(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->enforce_hiding_from_global_feed;
|
||||||
|
}
|
||||||
|
|
||||||
function getType(): int
|
function getType(): int
|
||||||
{
|
{
|
||||||
return $this->getRecord()->type;
|
return $this->getRecord()->type;
|
||||||
|
@ -432,7 +437,7 @@ class Club extends RowModel
|
||||||
return (new \openvk\Web\Models\Repositories\Audios)->getClubCollectionSize($this);
|
return (new \openvk\Web\Models\Repositories\Audios)->getClubCollectionSize($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toVkApiStruct(?User $user = NULL): object
|
function toVkApiStruct(?User $user = NULL, string $fields = ''): object
|
||||||
{
|
{
|
||||||
$res = (object) [];
|
$res = (object) [];
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,22 @@ class Comment extends Post
|
||||||
|
|
||||||
return $this->getTarget()->canBeViewedBy($user);
|
return $this->getTarget()->canBeViewedBy($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isFromPostAuthor($target = NULL)
|
||||||
|
{
|
||||||
|
if(!$target)
|
||||||
|
$target = $this->getTarget();
|
||||||
|
|
||||||
|
$target_owner = $target->getOwner();
|
||||||
|
$comment_owner = $this->getOwner();
|
||||||
|
|
||||||
|
if($target_owner->getRealId() === $comment_owner->getRealId())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
# TODO: make it work with signer_id
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function toNotifApiStruct()
|
function toNotifApiStruct()
|
||||||
{
|
{
|
||||||
|
@ -124,4 +140,31 @@ class Comment extends Post
|
||||||
|
|
||||||
return $user->getId() == $this->getOwner(false)->getId();
|
return $user->getId() == $this->getOwner(false)->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTargetURL(): string
|
||||||
|
{
|
||||||
|
$target = $this->getTarget();
|
||||||
|
$target_name = 'wall';
|
||||||
|
|
||||||
|
if(!$target) {
|
||||||
|
return '/404';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(get_class($target)) {
|
||||||
|
case 'openvk\Web\Models\Entities\Note':
|
||||||
|
$target_name = 'note';
|
||||||
|
break;
|
||||||
|
case 'openvk\Web\Models\Entities\Photo':
|
||||||
|
$target_name = 'photo';
|
||||||
|
break;
|
||||||
|
case 'openvk\Web\Models\Entities\Video':
|
||||||
|
$target_name = 'video';
|
||||||
|
break;
|
||||||
|
case 'openvk\Web\Models\Entities\Topic':
|
||||||
|
$target_name = 'topic';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $target_name . $target->getPrettyId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class Message extends RowModel
|
||||||
$dateTime = new DateTime($this->getRecord()->created);
|
$dateTime = new DateTime($this->getRecord()->created);
|
||||||
|
|
||||||
if($dateTime->format("%d.%m.%y") == ovk_strftime_safe("%d.%m.%y", time())) {
|
if($dateTime->format("%d.%m.%y") == ovk_strftime_safe("%d.%m.%y", time())) {
|
||||||
return $dateTime->format("%T %p");
|
return $dateTime->format("%T");
|
||||||
} else {
|
} else {
|
||||||
return $dateTime->format("%d.%m.%y");
|
return $dateTime->format("%d.%m.%y");
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ class Photo extends Media
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function crop(real $left, real $top, real $width, real $height): void
|
function crop(float $left, float $top, float $width, float $height): void
|
||||||
{
|
{
|
||||||
if(isset($this->changes["hash"]))
|
if(isset($this->changes["hash"]))
|
||||||
$hash = $this->changes["hash"];
|
$hash = $this->changes["hash"];
|
||||||
|
|
|
@ -41,6 +41,21 @@ class Playlist extends MediaCollection
|
||||||
{
|
{
|
||||||
return $this->getRecord()->length;
|
return $this->getRecord()->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fetchClassic(int $offset = 0, ?int $limit = NULL): \Traversable
|
||||||
|
{
|
||||||
|
$related = $this->getRecord()->related("$this->relTableName.collection")
|
||||||
|
->limit($limit ?? OPENVK_DEFAULT_PER_PAGE, $offset)
|
||||||
|
->order("index ASC");
|
||||||
|
|
||||||
|
foreach($related as $rel) {
|
||||||
|
$media = $rel->ref($this->entityTableName, "media");
|
||||||
|
if(!$media)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
yield new $this->entityClassName($media);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getAudios(int $offset = 0, ?int $limit = NULL, ?int $shuffleSeed = NULL): \Traversable
|
function getAudios(int $offset = 0, ?int $limit = NULL, ?int $shuffleSeed = NULL): \Traversable
|
||||||
{
|
{
|
||||||
|
@ -162,6 +177,7 @@ class Playlist extends MediaCollection
|
||||||
"bookmarked" => $this->isBookmarkedBy($user),
|
"bookmarked" => $this->isBookmarkedBy($user),
|
||||||
"listens" => $this->getListens(),
|
"listens" => $this->getListens(),
|
||||||
"cover_url" => $this->getCoverURL(),
|
"cover_url" => $this->getCoverURL(),
|
||||||
|
"searchable" => !$this->isUnlisted(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +215,11 @@ class Playlist extends MediaCollection
|
||||||
{
|
{
|
||||||
return $this->getRecord()->cover_photo_id;
|
return $this->getRecord()->cover_photo_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCoverPhoto(): ?Photo
|
||||||
|
{
|
||||||
|
return (new Photos)->get((int) $this->getRecord()->cover_photo_id);
|
||||||
|
}
|
||||||
|
|
||||||
function canBeModifiedBy(User $user): bool
|
function canBeModifiedBy(User $user): bool
|
||||||
{
|
{
|
||||||
|
@ -253,4 +274,9 @@ class Playlist extends MediaCollection
|
||||||
|
|
||||||
return implode(" • ", $props);
|
return implode(" • ", $props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isUnlisted(): bool
|
||||||
|
{
|
||||||
|
return (bool)$this->getRecord()->unlisted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,10 @@ class Post extends Postable
|
||||||
case 'openvk_legacy_ios':
|
case 'openvk_legacy_ios':
|
||||||
return 'iphone';
|
return 'iphone';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'windows_phone':
|
||||||
|
return 'wphone';
|
||||||
|
break;
|
||||||
|
|
||||||
case 'vika_touch': // кика хохотач ахахахаххахахахахах
|
case 'vika_touch': // кика хохотач ахахахаххахахахахах
|
||||||
case 'vk4me':
|
case 'vk4me':
|
||||||
|
@ -175,6 +179,31 @@ class Post extends Postable
|
||||||
"img" => NULL
|
"img" => NULL
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPostSourceInfo(): array
|
||||||
|
{
|
||||||
|
$post_source = ["type" => "vk"];
|
||||||
|
if($this->getPlatform(true) !== NULL) {
|
||||||
|
$post_source = [
|
||||||
|
"type" => "api",
|
||||||
|
"platform" => $this->getPlatform(true)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->isUpdateAvatarMessage())
|
||||||
|
$post_source['data'] = 'profile_photo';
|
||||||
|
|
||||||
|
return $post_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVkApiType(): string
|
||||||
|
{
|
||||||
|
$type = 'post';
|
||||||
|
if($this->getSuggestionType() != 0)
|
||||||
|
$type = 'suggest';
|
||||||
|
|
||||||
|
return $type;
|
||||||
|
}
|
||||||
|
|
||||||
function pin(): void
|
function pin(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,7 +80,7 @@ class Report extends RowModel
|
||||||
|
|
||||||
function getAuthor(): RowModel
|
function getAuthor(): RowModel
|
||||||
{
|
{
|
||||||
return (new Posts)->get($this->getContentId())->getOwner();
|
return $this->getContentObject()->getOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getReportAuthor(): User
|
function getReportAuthor(): User
|
||||||
|
|
|
@ -123,7 +123,7 @@ trait TRichText
|
||||||
$text = preg_replace_callback("%([\n\r\s]|^)(\#([\p{L}_0-9][\p{L}_0-9\(\)\-\']+[\p{L}_0-9\(\)]|[\p{L}_0-9]{1,2}))%Xu", function($m) {
|
$text = preg_replace_callback("%([\n\r\s]|^)(\#([\p{L}_0-9][\p{L}_0-9\(\)\-\']+[\p{L}_0-9\(\)]|[\p{L}_0-9]{1,2}))%Xu", function($m) {
|
||||||
$slug = rawurlencode($m[3]);
|
$slug = rawurlencode($m[3]);
|
||||||
|
|
||||||
return "$m[1]<a href='/feed/hashtag/$slug'>$m[2]</a>";
|
return "$m[1]<a href='/search?section=posts&q=%23$slug'>$m[2]</a>";
|
||||||
}, $text);
|
}, $text);
|
||||||
|
|
||||||
$text = $this->formatEmojis($text);
|
$text = $this->formatEmojis($text);
|
||||||
|
|
|
@ -39,4 +39,25 @@ trait TSubscribable
|
||||||
$sub->delete();
|
$sub->delete();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeFlags(User $user, int $flags, bool $reverse): bool
|
||||||
|
{
|
||||||
|
$ctx = DatabaseConnection::i()->getContext();
|
||||||
|
$data = [
|
||||||
|
"follower" => $reverse ? $this->getId() : $user->getId(),
|
||||||
|
"model" => static::class,
|
||||||
|
"target" => $reverse ? $user->getId() : $this->getId(),
|
||||||
|
];
|
||||||
|
$sub = $ctx->table("subscriptions")->where($data);
|
||||||
|
|
||||||
|
bdump($data);
|
||||||
|
|
||||||
|
if (!$sub)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$sub->update([
|
||||||
|
'flags' => $flags
|
||||||
|
]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -592,6 +592,16 @@ class User extends RowModel
|
||||||
return $this->_abstractRelationCount("get-followers");
|
return $this->_abstractRelationCount("get-followers");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRequests(int $page = 1, int $limit = 6): \Traversable
|
||||||
|
{
|
||||||
|
return $this->_abstractRelationGenerator("get-requests", $page, $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRequestsCount(): int
|
||||||
|
{
|
||||||
|
return $this->_abstractRelationCount("get-requests");
|
||||||
|
}
|
||||||
|
|
||||||
function getSubscriptions(int $page = 1, int $limit = 6): \Traversable
|
function getSubscriptions(int $page = 1, int $limit = 6): \Traversable
|
||||||
{
|
{
|
||||||
return $this->_abstractRelationGenerator("get-subscriptions-user", $page, $limit);
|
return $this->_abstractRelationGenerator("get-subscriptions-user", $page, $limit);
|
||||||
|
@ -1214,6 +1224,11 @@ class User extends RowModel
|
||||||
return (bool) $this->getRecord()->activated;
|
return (bool) $this->getRecord()->activated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isDead(): bool
|
||||||
|
{
|
||||||
|
return $this->onlineStatus() == 2;
|
||||||
|
}
|
||||||
|
|
||||||
function getUnbanTime(): ?string
|
function getUnbanTime(): ?string
|
||||||
{
|
{
|
||||||
$ban = (new Bans)->get((int) $this->getRecord()->block_reason);
|
$ban = (new Bans)->get((int) $this->getRecord()->block_reason);
|
||||||
|
@ -1306,17 +1321,22 @@ class User extends RowModel
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isClosed()
|
function isClosed(): bool
|
||||||
{
|
{
|
||||||
return (bool) $this->getProfileType();
|
return (bool) $this->getProfileType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isHideFromGlobalFeedEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->isClosed();
|
||||||
|
}
|
||||||
|
|
||||||
function getRealId()
|
function getRealId()
|
||||||
{
|
{
|
||||||
return $this->getId();
|
return $this->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toVkApiStruct(?User $user = NULL): object
|
function toVkApiStruct(?User $user = NULL, string $fields = ''): object
|
||||||
{
|
{
|
||||||
$res = (object) [];
|
$res = (object) [];
|
||||||
|
|
||||||
|
@ -1328,12 +1348,21 @@ class User extends RowModel
|
||||||
$res->photo_100 = $this->getAvatarURL("tiny");
|
$res->photo_100 = $this->getAvatarURL("tiny");
|
||||||
$res->photo_200 = $this->getAvatarURL("normal");
|
$res->photo_200 = $this->getAvatarURL("normal");
|
||||||
$res->photo_id = !is_null($this->getAvatarPhoto()) ? $this->getAvatarPhoto()->getPrettyId() : NULL;
|
$res->photo_id = !is_null($this->getAvatarPhoto()) ? $this->getAvatarPhoto()->getPrettyId() : NULL;
|
||||||
# TODO: Perenesti syuda vsyo ostalnoyie
|
|
||||||
|
|
||||||
$res->is_closed = $this->isClosed();
|
$res->is_closed = $this->isClosed();
|
||||||
|
|
||||||
if(!is_null($user)) {
|
if(!is_null($user))
|
||||||
$res->can_access_closed = (bool)$this->canBeViewedBy($user);
|
$res->can_access_closed = (bool)$this->canBeViewedBy($user);
|
||||||
|
|
||||||
|
if(!is_array($fields))
|
||||||
|
$fields = explode(',', $fields);
|
||||||
|
|
||||||
|
foreach($fields as $field) {
|
||||||
|
switch($field) {
|
||||||
|
case 'is_dead':
|
||||||
|
$res->is_dead = $user->isDead();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
|
@ -181,8 +181,8 @@ class Video extends Media
|
||||||
{
|
{
|
||||||
if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/youtube.txt"), $link, $matches)) {
|
if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/youtube.txt"), $link, $matches)) {
|
||||||
$pointer = "YouTube:$matches[1]";
|
$pointer = "YouTube:$matches[1]";
|
||||||
} else if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/vimeo.txt"), $link, $matches)) {
|
/*} else if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/vimeo.txt"), $link, $matches)) {
|
||||||
$pointer = "Vimeo:$matches[1]";
|
$pointer = "Vimeo:$matches[1]";*/
|
||||||
} else {
|
} else {
|
||||||
throw new ISE("Invalid link");
|
throw new ISE("Invalid link");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,4 +23,13 @@ class APITokens extends Repository
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getStaleByUser(int $userId, string $platform, bool $withRevoked = false): ?APIToken
|
||||||
|
{
|
||||||
|
return $this->toEntity($this->table->where([
|
||||||
|
'user' => $userId,
|
||||||
|
'platform' => $platform,
|
||||||
|
'deleted' => $withRevoked,
|
||||||
|
])->fetch());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,11 +67,21 @@ class Applications
|
||||||
return sizeof($this->appRels->where("user", $user->getId()));
|
return sizeof($this->appRels->where("user", $user->getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(string $query, array $pars = [], string $sort = "id"): Util\EntityStream
|
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
$result = $this->apps->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("enabled", 1);
|
$result = $this->apps->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("enabled", 1);
|
||||||
|
$order_str = 'id';
|
||||||
|
|
||||||
|
switch($order['type']) {
|
||||||
|
case 'id':
|
||||||
|
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
return new Util\EntityStream("Application", $result->order("$sort"));
|
return new Util\EntityStream("Application", $result);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -208,7 +208,7 @@ class Audios
|
||||||
$search = $this->audios->where([
|
$search = $this->audios->where([
|
||||||
"unlisted" => 0,
|
"unlisted" => 0,
|
||||||
"deleted" => 0,
|
"deleted" => 0,
|
||||||
])->where("MATCH ($columns) AGAINST (? WITH QUERY EXPANSION)", $query)->order($order);
|
])->where("MATCH ($columns) AGAINST (? IN BOOLEAN MODE)", "%$query%")->order($order);
|
||||||
|
|
||||||
if($withLyrics)
|
if($withLyrics)
|
||||||
$search = $search->where("lyrics IS NOT NULL");
|
$search = $search->where("lyrics IS NOT NULL");
|
||||||
|
@ -219,6 +219,7 @@ class Audios
|
||||||
function searchPlaylists(string $query): EntityStream
|
function searchPlaylists(string $query): EntityStream
|
||||||
{
|
{
|
||||||
$search = $this->playlists->where([
|
$search = $this->playlists->where([
|
||||||
|
"unlisted" => 0,
|
||||||
"deleted" => 0,
|
"deleted" => 0,
|
||||||
])->where("MATCH (`name`, `description`) AGAINST (? IN BOOLEAN MODE)", $query);
|
])->where("MATCH (`name`, `description`) AGAINST (? IN BOOLEAN MODE)", $query);
|
||||||
|
|
||||||
|
@ -243,53 +244,72 @@ class Audios
|
||||||
])->fetch());
|
])->fetch());
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable
|
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false], int $page = 1, ?int $perPage = NULL): \Traversable
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
$result = $this->audios->where([
|
$result = $this->audios->where([
|
||||||
"unlisted" => 0,
|
"unlisted" => 0,
|
||||||
"deleted" => 0,
|
"deleted" => 0,
|
||||||
]);
|
]);
|
||||||
|
$order_str = (in_array($order['type'], ['id', 'length', 'listens']) ? $order['type'] : 'id') . ' ' . ($order['invert'] ? 'ASC' : 'DESC');;
|
||||||
|
|
||||||
$notNullParams = [];
|
if($params["only_performers"] == "1") {
|
||||||
|
|
||||||
foreach($pars as $paramName => $paramValue)
|
|
||||||
if($paramName != "before" && $paramName != "after" && $paramName != "only_performers")
|
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
|
||||||
else
|
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
|
||||||
|
|
||||||
$nnparamsCount = sizeof($notNullParams);
|
|
||||||
|
|
||||||
if($notNullParams["only_performers"] == "1") {
|
|
||||||
$result->where("performer LIKE ?", $query);
|
$result->where("performer LIKE ?", $query);
|
||||||
} else {
|
} else {
|
||||||
$result->where("name LIKE ? OR performer LIKE ?", $query, $query);
|
$result->where("name LIKE ? OR performer LIKE ?", $query, $query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($nnparamsCount > 0) {
|
foreach($params as $paramName => $paramValue) {
|
||||||
foreach($notNullParams as $paramName => $paramValue) {
|
if(is_null($paramValue) || $paramValue == '') continue;
|
||||||
switch($paramName) {
|
|
||||||
case "before":
|
switch($paramName) {
|
||||||
$result->where("created < ?", $paramValue);
|
case "before":
|
||||||
break;
|
$result->where("created < ?", $paramValue);
|
||||||
case "after":
|
break;
|
||||||
$result->where("created > ?", $paramValue);
|
case "after":
|
||||||
break;
|
$result->where("created > ?", $paramValue);
|
||||||
case "with_lyrics":
|
break;
|
||||||
$result->where("lyrics IS NOT NULL");
|
case "with_lyrics":
|
||||||
break;
|
$result->where("lyrics IS NOT NULL");
|
||||||
}
|
break;
|
||||||
|
case 'genre':
|
||||||
|
if($paramValue == 'any') break;
|
||||||
|
|
||||||
|
$result->where("genre", $paramValue);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Util\EntityStream("Audio", $result->order($sort));
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
|
return new Util\EntityStream("Audio", $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPlaylists(string $query, int $page = 1, ?int $perPage = NULL): \Traversable
|
function findPlaylists(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): \Traversable
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
$result = $this->playlists->where("name LIKE ?", $query);
|
$result = $this->playlists->where([
|
||||||
|
"deleted" => 0,
|
||||||
|
])->where("CONCAT_WS(' ', name, description) LIKE ?", $query);
|
||||||
|
$order_str = (in_array($order['type'], ['id', 'length', 'listens']) ? $order['type'] : 'id') . ' ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||||
|
|
||||||
|
if(is_null($params['from_me']) || empty($params['from_me']))
|
||||||
|
$result->where(["unlisted" => 0]);
|
||||||
|
|
||||||
|
foreach($params as $paramName => $paramValue) {
|
||||||
|
if(is_null($paramValue) || $paramValue == '') continue;
|
||||||
|
|
||||||
|
switch($paramName) {
|
||||||
|
# БУДЬ МАКСИМАЛЬНО АККУРАТЕН С ДАННЫМ ПАРАМЕТРОМ
|
||||||
|
case "from_me":
|
||||||
|
$result->where("owner", $paramValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
return new Util\EntityStream("Playlist", $result);
|
return new Util\EntityStream("Playlist", $result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,18 +42,30 @@ class Clubs
|
||||||
{
|
{
|
||||||
return $this->toClub($this->clubs->get($id));
|
return $this->toClub($this->clubs->get($id));
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable
|
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false], int $page = 1, ?int $perPage = NULL): \Traversable
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
$result = $this->clubs->where("name LIKE ? OR about LIKE ?", $query, $query);
|
$result = $this->clubs;
|
||||||
|
$order_str = 'id';
|
||||||
return new Util\EntityStream("Club", $result->order($sort));
|
|
||||||
|
switch($order['type']) {
|
||||||
|
case 'id':
|
||||||
|
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $result->where("name LIKE ? OR about LIKE ?", $query, $query);
|
||||||
|
|
||||||
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
|
return new Util\EntityStream("Club", $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCount(): int
|
function getCount(): int
|
||||||
{
|
{
|
||||||
return sizeof(clone $this->clubs);
|
return (clone $this->clubs)->count('*');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPopularClubs(): \Traversable
|
function getPopularClubs(): \Traversable
|
||||||
|
|
|
@ -60,34 +60,31 @@ class Comments
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream
|
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$result = $this->comments->where("content LIKE ?", "%$query%")->where("deleted", 0);
|
||||||
|
$order_str = 'id';
|
||||||
|
|
||||||
$notNullParams = [];
|
switch($order['type']) {
|
||||||
|
case 'id':
|
||||||
|
$order_str = 'created ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
foreach($pars as $paramName => $paramValue)
|
foreach($params as $paramName => $paramValue) {
|
||||||
if($paramName != "before" && $paramName != "after")
|
switch($paramName) {
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
case "before":
|
||||||
else
|
$result->where("created < ?", $paramValue);
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
break;
|
||||||
|
case "after":
|
||||||
$result = $this->comments->where("content LIKE ?", $query)->where("deleted", 0);
|
$result->where("created > ?", $paramValue);
|
||||||
$nnparamsCount = sizeof($notNullParams);
|
break;
|
||||||
|
|
||||||
if($nnparamsCount > 0) {
|
|
||||||
foreach($notNullParams as $paramName => $paramValue) {
|
|
||||||
switch($paramName) {
|
|
||||||
case "before":
|
|
||||||
$result->where("created < ?", $paramValue);
|
|
||||||
break;
|
|
||||||
case "after":
|
|
||||||
$result->where("created > ?", $paramValue);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Util\EntityStream("Comment", $result->order("$sort"));
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
|
return new Util\EntityStream("Comment", $result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Notifications
|
||||||
return (new $repoClassName)->get($id);
|
return (new $repoClassName)->get($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getQuery(User $user, bool $count = false, int $offset, bool $archived = false, int $page = 1, ?int $perPage = NULL): string
|
private function getQuery(User $user, bool $count, int $offset, bool $archived = false, int $page = 1, ?int $perPage = NULL): string
|
||||||
{
|
{
|
||||||
$query = "SELECT " . ($count ? "COUNT(*) AS cnt" : "*") . " FROM notifications WHERE recipientType=0 ";
|
$query = "SELECT " . ($count ? "COUNT(*) AS cnt" : "*") . " FROM notifications WHERE recipientType=0 ";
|
||||||
$query .= "AND timestamp " . ($archived ? "<" : ">") . "$offset AND recipientId=" . $user->getId();
|
$query .= "AND timestamp " . ($archived ? "<" : ">") . "$offset AND recipientId=" . $user->getId();
|
||||||
|
|
|
@ -154,36 +154,45 @@ class Posts
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream
|
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
|
|
||||||
$notNullParams = [];
|
|
||||||
|
|
||||||
foreach($pars as $paramName => $paramValue)
|
|
||||||
if($paramName != "before" && $paramName != "after")
|
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
|
||||||
else
|
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
|
||||||
|
|
||||||
$result = $this->posts->where("content LIKE ?", $query)->where("deleted", 0)->where("suggested", 0);
|
$result = $this->posts->where("content LIKE ?", $query)->where("deleted", 0)->where("suggested", 0);
|
||||||
$nnparamsCount = sizeof($notNullParams);
|
$order_str = 'id';
|
||||||
|
|
||||||
if($nnparamsCount > 0) {
|
switch($order['type']) {
|
||||||
foreach($notNullParams as $paramName => $paramValue) {
|
case 'id':
|
||||||
switch($paramName) {
|
$order_str = 'created ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||||
case "before":
|
break;
|
||||||
$result->where("created < ?", $paramValue);
|
}
|
||||||
break;
|
|
||||||
case "after":
|
foreach($params as $paramName => $paramValue) {
|
||||||
$result->where("created > ?", $paramValue);
|
if(is_null($paramValue) || $paramValue == '') continue;
|
||||||
break;
|
|
||||||
}
|
switch($paramName) {
|
||||||
|
case "before":
|
||||||
|
$result->where("created < ?", $paramValue);
|
||||||
|
break;
|
||||||
|
case "after":
|
||||||
|
$result->where("created > ?", $paramValue);
|
||||||
|
break;
|
||||||
|
/*case 'die_in_agony':
|
||||||
|
$result->where("nsfw", 1);
|
||||||
|
break;
|
||||||
|
case 'ads':
|
||||||
|
$result->where("ad", 1);
|
||||||
|
break;*/
|
||||||
|
# БУДЬ МАКСИМАЛЬНО АККУРАТЕН С ДАННЫМ ПАРАМЕТРОМ
|
||||||
|
case 'from_me':
|
||||||
|
$result->where("owner", $paramValue);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
return new Util\EntityStream("Post", $result->order("$sort"));
|
return new Util\EntityStream("Post", $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPostCountOnUserWall(int $user): int
|
function getPostCountOnUserWall(int $user): int
|
||||||
|
@ -252,6 +261,6 @@ class Posts
|
||||||
|
|
||||||
function getCount(): int
|
function getCount(): int
|
||||||
{
|
{
|
||||||
return sizeof(clone $this->posts);
|
return (clone $this->posts)->count('*');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,107 +44,94 @@ class Users
|
||||||
return $alias->getUser();
|
return $alias->getUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getByChandlerUser(?ChandlerUser $user): ?User
|
function getByChandlerUserId(string $cid): ?User
|
||||||
{
|
{
|
||||||
return $user ? $this->toUser($this->users->where("user", $user->getId())->fetch()) : NULL;
|
return $this->toUser($this->users->where("user", $cid)->fetch());
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(string $query, array $pars = [], string $sort = "id DESC"): Util\EntityStream
|
function getByChandlerUser(?ChandlerUser $user): ?User
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
return $user ? $this->getByChandlerUserId($user->getId()) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||||
|
{
|
||||||
|
$query = "%$query%";
|
||||||
$result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo, shortcode) LIKE ?", $query)->where("deleted", 0);
|
$result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo, shortcode) LIKE ?", $query)->where("deleted", 0);
|
||||||
|
$order_str = 'id';
|
||||||
$notNullParams = [];
|
|
||||||
$nnparamsCount = 0;
|
|
||||||
|
|
||||||
foreach($pars as $paramName => $paramValue)
|
|
||||||
if($paramName != "before" && $paramName != "after" && $paramName != "gender" && $paramName != "maritalstatus" && $paramName != "politViews" && $paramName != "doNotSearchMe")
|
|
||||||
$paramValue != NULL ? $notNullParams += ["$paramName" => "%$paramValue%"] : NULL;
|
|
||||||
else
|
|
||||||
$paramValue != NULL ? $notNullParams += ["$paramName" => "$paramValue"] : NULL;
|
|
||||||
|
|
||||||
$nnparamsCount = sizeof($notNullParams);
|
switch($order['type']) {
|
||||||
|
case 'id':
|
||||||
|
case 'reg_date':
|
||||||
|
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||||
|
break;
|
||||||
|
case 'rating':
|
||||||
|
$order_str = 'rating DESC';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if($nnparamsCount > 0) {
|
foreach($params as $paramName => $paramValue) {
|
||||||
foreach($notNullParams as $paramName => $paramValue) {
|
if(is_null($paramValue) || $paramValue == '') continue;
|
||||||
switch($paramName) {
|
|
||||||
case "hometown":
|
switch($paramName) {
|
||||||
$result->where("hometown LIKE ?", $paramValue);
|
case "hometown":
|
||||||
break;
|
$result->where("hometown LIKE ?", "%$paramValue%");
|
||||||
case "city":
|
break;
|
||||||
$result->where("city LIKE ?", $paramValue);
|
case "city":
|
||||||
break;
|
$result->where("city LIKE ?", "%$paramValue%");
|
||||||
case "maritalstatus":
|
break;
|
||||||
$result->where("marital_status ?", $paramValue);
|
case "marital_status":
|
||||||
break;
|
$result->where("marital_status ?", $paramValue);
|
||||||
case "status":
|
break;
|
||||||
$result->where("status LIKE ?", $paramValue);
|
case "polit_views":
|
||||||
break;
|
$result->where("polit_views ?", $paramValue);
|
||||||
case "politViews":
|
break;
|
||||||
$result->where("polit_views ?", $paramValue);
|
case "is_online":
|
||||||
break;
|
$result->where("online >= ?", time() - 900);
|
||||||
case "email":
|
break;
|
||||||
$result->where("email_contact LIKE ?", $paramValue);
|
case "fav_mus":
|
||||||
break;
|
$result->where("fav_music LIKE ?", "%$paramValue%");
|
||||||
case "telegram":
|
break;
|
||||||
$result->where("telegram LIKE ?", $paramValue);
|
case "fav_films":
|
||||||
break;
|
$result->where("fav_films LIKE ?", "%$paramValue%");
|
||||||
case "site":
|
break;
|
||||||
$result->where("telegram LIKE ?", $paramValue);
|
case "fav_shows":
|
||||||
break;
|
$result->where("fav_shows LIKE ?", "%$paramValue%");
|
||||||
case "address":
|
break;
|
||||||
$result->where("address LIKE ?", $paramValue);
|
case "fav_books":
|
||||||
break;
|
$result->where("fav_books LIKE ?", "%$paramValue%");
|
||||||
case "is_online":
|
break;
|
||||||
$result->where("online >= ?", time() - 900);
|
case "before":
|
||||||
break;
|
$result->where("UNIX_TIMESTAMP(since) < ?", $paramValue);
|
||||||
case "interests":
|
break;
|
||||||
$result->where("interests LIKE ?", $paramValue);
|
case "after":
|
||||||
break;
|
$result->where("UNIX_TIMESTAMP(since) > ?", $paramValue);
|
||||||
case "fav_mus":
|
break;
|
||||||
$result->where("fav_music LIKE ?", $paramValue);
|
case "gender":
|
||||||
break;
|
if((int) $paramValue == 3) break;
|
||||||
case "fav_films":
|
$result->where("sex ?", (int) $paramValue);
|
||||||
$result->where("fav_films LIKE ?", $paramValue);
|
break;
|
||||||
break;
|
case "ignore_id":
|
||||||
case "fav_shows":
|
$result->where("id != ?", $paramValue);
|
||||||
$result->where("fav_shows LIKE ?", $paramValue);
|
break;
|
||||||
break;
|
case "ignore_private":
|
||||||
case "fav_books":
|
$result->where("profile_type", 0);
|
||||||
$result->where("fav_books LIKE ?", $paramValue);
|
break;
|
||||||
break;
|
|
||||||
case "fav_quote":
|
|
||||||
$result->where("fav_quote LIKE ?", $paramValue);
|
|
||||||
break;
|
|
||||||
case "before":
|
|
||||||
$result->where("UNIX_TIMESTAMP(since) < ?", $paramValue);
|
|
||||||
break;
|
|
||||||
case "after":
|
|
||||||
$result->where("UNIX_TIMESTAMP(since) > ?", $paramValue);
|
|
||||||
break;
|
|
||||||
case "gender":
|
|
||||||
$result->where("sex ?", $paramValue);
|
|
||||||
break;
|
|
||||||
case "doNotSearchMe":
|
|
||||||
$result->where("id !=", $paramValue);
|
|
||||||
break;
|
|
||||||
case "doNotSearchPrivate":
|
|
||||||
$result->where("profile_type", 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
return new Util\EntityStream("User", $result->order($sort));
|
return new Util\EntityStream("User", $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatistics(): object
|
function getStatistics(): object
|
||||||
{
|
{
|
||||||
return (object) [
|
return (object) [
|
||||||
"all" => sizeof(clone $this->users),
|
"all" => (clone $this->users)->count('*'),
|
||||||
"active" => sizeof((clone $this->users)->where("online > 0")),
|
"active" => (clone $this->users)->where("online > 0")->count('*'),
|
||||||
"online" => sizeof((clone $this->users)->where("online >= ?", time() - 900)),
|
"online" => (clone $this->users)->where("online >= ?", time() - 900)->count('*'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,36 +46,37 @@ class Videos
|
||||||
return sizeof($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0]));
|
return sizeof($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream
|
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
|
|
||||||
$notNullParams = [];
|
|
||||||
|
|
||||||
foreach($pars as $paramName => $paramValue)
|
|
||||||
if($paramName != "before" && $paramName != "after")
|
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
|
||||||
else
|
|
||||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
|
||||||
|
|
||||||
$result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0);
|
$result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0);
|
||||||
$nnparamsCount = sizeof($notNullParams);
|
$order_str = 'id';
|
||||||
|
|
||||||
if($nnparamsCount > 0) {
|
switch($order['type']) {
|
||||||
foreach($notNullParams as $paramName => $paramValue) {
|
case 'id':
|
||||||
switch($paramName) {
|
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||||
case "before":
|
break;
|
||||||
$result->where("created < ?", $paramValue);
|
}
|
||||||
break;
|
|
||||||
case "after":
|
foreach($params as $paramName => $paramValue) {
|
||||||
$result->where("created > ?", $paramValue);
|
switch($paramName) {
|
||||||
break;
|
case "before":
|
||||||
}
|
$result->where("created < ?", $paramValue);
|
||||||
|
break;
|
||||||
|
case "after":
|
||||||
|
$result->where("created > ?", $paramValue);
|
||||||
|
break;
|
||||||
|
case 'only_youtube':
|
||||||
|
if((int) $paramValue != 1) break;
|
||||||
|
$result->where("link != ?", 'NULL');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($order_str)
|
||||||
|
$result->order($order_str);
|
||||||
|
|
||||||
return new Util\EntityStream("Video", $result->order("$sort"));
|
return new Util\EntityStream("Video", $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLastVideo(User $user)
|
function getLastVideo(User $user)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
(SELECT DISTINCT(follower) AS __id FROM
|
(SELECT DISTINCT(follower) AS __id FROM
|
||||||
(SELECT follower FROM subscriptions WHERE target=? AND model="openvk\\Web\\Models\\Entities\\User") u0
|
(SELECT follower, flags FROM subscriptions WHERE target=? AND model="openvk\\Web\\Models\\Entities\\User") u0
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
(SELECT target FROM subscriptions WHERE follower=? AND model="openvk\\Web\\Models\\Entities\\User") u1
|
(SELECT target FROM subscriptions WHERE follower=? AND model="openvk\\Web\\Models\\Entities\\User") u1
|
||||||
ON u0.follower = u1.target WHERE u1.target IS NULL) u2
|
ON u0.follower = u1.target WHERE u1.target IS NULL) u2
|
||||||
|
|
6
Web/Models/sql/get-requests.tsql
Executable file
6
Web/Models/sql/get-requests.tsql
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
(SELECT DISTINCT(follower) AS __id FROM
|
||||||
|
(SELECT follower FROM subscriptions WHERE target=? AND flags=0 AND model="openvk\\Web\\Models\\Entities\\User") u0
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT target FROM subscriptions WHERE follower=? AND flags=0 AND model="openvk\\Web\\Models\\Entities\\User") u1
|
||||||
|
ON u0.follower = u1.target WHERE u1.target IS NULL) u2
|
||||||
|
INNER JOIN profiles ON profiles.id = u2.__id
|
|
@ -145,6 +145,6 @@ final class AboutPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderDev(): void
|
function renderDev(): void
|
||||||
{
|
{
|
||||||
$this->redirect("https://docs.openvk.uk/");
|
$this->redirect("https://docs.ovk.to/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,13 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
||||||
$this->flash("warn", tr("admin_commerce_disabled"), tr("admin_commerce_disabled_desc"));
|
$this->flash("warn", tr("admin_commerce_disabled"), tr("admin_commerce_disabled_desc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function warnIfLongpoolBroken(): void
|
||||||
|
{
|
||||||
|
bdump(is_writable(CHANDLER_ROOT . '/tmp/events.bin'));
|
||||||
|
if(file_exists(CHANDLER_ROOT . '/tmp/events.bin') == false || is_writable(CHANDLER_ROOT . '/tmp/events.bin') == false)
|
||||||
|
$this->flash("warn", tr("admin_longpool_broken"), tr("admin_longpool_broken_desc", CHANDLER_ROOT . '/tmp/events.bin'));
|
||||||
|
}
|
||||||
|
|
||||||
private function searchResults(object $repo, &$count)
|
private function searchResults(object $repo, &$count)
|
||||||
{
|
{
|
||||||
|
@ -76,7 +83,7 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderIndex(): void
|
function renderIndex(): void
|
||||||
{
|
{
|
||||||
|
$this->warnIfLongpoolBroken();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderUsers(): void
|
function renderUsers(): void
|
||||||
|
@ -154,6 +161,7 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
$club->setShortCode($this->postParam("shortcode"));
|
$club->setShortCode($this->postParam("shortcode"));
|
||||||
$club->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
$club->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
||||||
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed") ? 0 : 1));
|
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed") ? 0 : 1));
|
||||||
|
$club->setEnforce_Hiding_From_Global_Feed(empty($this->postParam("enforce_hiding_from_global_feed") ? 0 : 1));
|
||||||
$club->save();
|
$club->save();
|
||||||
break;
|
break;
|
||||||
case "ban":
|
case "ban":
|
||||||
|
@ -681,7 +689,8 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
$this->template->obj_type = $obj_type;
|
$this->template->obj_type = $obj_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->template->logs = (new Logs)->search($filter);
|
$logs = iterator_to_array((new Logs)->search($filter));
|
||||||
|
$this->template->logs = $logs;
|
||||||
$this->template->object_types = (new Logs)->getTypes();
|
$this->template->object_types = (new Logs)->getTypes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
if (!$entity || $entity->isBanned())
|
if (!$entity || $entity->isBanned())
|
||||||
$this->redirect("/playlists" . $this->user->id);
|
$this->redirect("/playlists" . $this->user->id);
|
||||||
|
|
||||||
$playlists = $this->audios->getPlaylistsByClub($entity, $page, 10);
|
$playlists = $this->audios->getPlaylistsByClub($entity, $page, OPENVK_DEFAULT_PER_PAGE);
|
||||||
$playlistsCount = $this->audios->getClubPlaylistsCount($entity);
|
$playlistsCount = $this->audios->getClubPlaylistsCount($entity);
|
||||||
} else {
|
} else {
|
||||||
$entity = (new Users)->get($owner);
|
$entity = (new Users)->get($owner);
|
||||||
|
@ -85,7 +85,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
if(!$entity->getPrivacyPermission("audios.read", $this->user->identity))
|
if(!$entity->getPrivacyPermission("audios.read", $this->user->identity))
|
||||||
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
|
|
||||||
$playlists = $this->audios->getPlaylistsByUser($entity, $page, 9);
|
$playlists = $this->audios->getPlaylistsByUser($entity, $page, OPENVK_DEFAULT_PER_PAGE);
|
||||||
$playlistsCount = $this->audios->getUserPlaylistsCount($entity);
|
$playlistsCount = $this->audios->getUserPlaylistsCount($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +109,8 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
$this->template->mode = $mode;
|
$this->template->mode = $mode;
|
||||||
$this->template->page = $page;
|
$this->template->page = $page;
|
||||||
|
|
||||||
if(in_array($mode, ["list", "new", "popular"]) && $this->user->identity)
|
if(in_array($mode, ["list", "new", "popular"]) && $this->user->identity && $page < 2)
|
||||||
$this->template->friendsAudios = $this->user->identity->getBroadcastList("all", true);
|
$this->template->friendsAudios = $this->user->identity->getBroadcastList("all", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,13 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
$group = NULL;
|
$group = NULL;
|
||||||
|
$playlist = NULL;
|
||||||
$isAjax = $this->postParam("ajax", false) == 1;
|
$isAjax = $this->postParam("ajax", false) == 1;
|
||||||
|
|
||||||
|
if(!is_null($this->queryParam("gid")) && !is_null($this->queryParam("playlist"))) {
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||||
|
}
|
||||||
|
|
||||||
if(!is_null($this->queryParam("gid"))) {
|
if(!is_null($this->queryParam("gid"))) {
|
||||||
$gid = (int) $this->queryParam("gid");
|
$gid = (int) $this->queryParam("gid");
|
||||||
$group = (new Clubs)->get($gid);
|
$group = (new Clubs)->get($gid);
|
||||||
|
@ -153,6 +159,19 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!is_null($this->queryParam("playlist"))) {
|
||||||
|
$playlist_id = (int)$this->queryParam("playlist");
|
||||||
|
$playlist = (new Audios)->getPlaylist($playlist_id);
|
||||||
|
if(!$playlist || $playlist->isDeleted())
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||||
|
|
||||||
|
if(!$playlist->canBeModifiedBy($this->user->identity))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||||
|
|
||||||
|
$this->template->playlist = $playlist;
|
||||||
|
$this->template->owner = $playlist->getOwner();
|
||||||
|
}
|
||||||
|
|
||||||
$this->template->group = $group;
|
$this->template->group = $group;
|
||||||
|
|
||||||
if($_SERVER["REQUEST_METHOD"] !== "POST")
|
if($_SERVER["REQUEST_METHOD"] !== "POST")
|
||||||
|
@ -196,6 +215,8 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
$lyrics = $this->postParam("lyrics");
|
$lyrics = $this->postParam("lyrics");
|
||||||
$genre = empty($this->postParam("genre")) ? "Other" : $this->postParam("genre");
|
$genre = empty($this->postParam("genre")) ? "Other" : $this->postParam("genre");
|
||||||
$nsfw = ($this->postParam("explicit") ?? "off") === "on";
|
$nsfw = ($this->postParam("explicit") ?? "off") === "on";
|
||||||
|
$is_unlisted = ($this->postParam("unlisted") ?? "off") === "on";
|
||||||
|
|
||||||
if(empty($performer) || empty($name) || iconv_strlen($performer . $name) > 128) # FQN of audio must not be more than 128 chars
|
if(empty($performer) || empty($name) || iconv_strlen($performer . $name) > 128) # FQN of audio must not be more than 128 chars
|
||||||
$this->flashFail("err", tr("error"), tr("error_insufficient_info"), null, $isAjax);
|
$this->flashFail("err", tr("error"), tr("error_insufficient_info"), null, $isAjax);
|
||||||
|
|
||||||
|
@ -206,6 +227,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
$audio->setLyrics(empty($lyrics) ? NULL : $lyrics);
|
$audio->setLyrics(empty($lyrics) ? NULL : $lyrics);
|
||||||
$audio->setGenre($genre);
|
$audio->setGenre($genre);
|
||||||
$audio->setExplicit($nsfw);
|
$audio->setExplicit($nsfw);
|
||||||
|
$audio->setUnlisted($is_unlisted);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$audio->setFile($upload);
|
$audio->setFile($upload);
|
||||||
|
@ -215,13 +237,18 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
} catch(\RuntimeException $ex) {
|
} catch(\RuntimeException $ex) {
|
||||||
$this->flashFail("err", tr("error"), tr("ffmpeg_timeout"), null, $isAjax);
|
$this->flashFail("err", tr("error"), tr("ffmpeg_timeout"), null, $isAjax);
|
||||||
} catch(\BadMethodCallException $ex) {
|
} catch(\BadMethodCallException $ex) {
|
||||||
$this->flashFail("err", tr("error"), "Загрузка аудио под Linux на данный момент не реализована. Следите за обновлениями: <a href='https://github.com/openvk/openvk/pull/512/commits'>https://github.com/openvk/openvk/pull/512/commits</a>", null, $isAjax);
|
$this->flashFail("err", tr("error"), "хз", null, $isAjax);
|
||||||
} catch(\Exception $ex) {
|
} catch(\Exception $ex) {
|
||||||
$this->flashFail("err", tr("error"), tr("ffmpeg_not_installed"), null, $isAjax);
|
$this->flashFail("err", tr("error"), tr("ffmpeg_not_installed"), null, $isAjax);
|
||||||
}
|
}
|
||||||
|
|
||||||
$audio->save();
|
$audio->save();
|
||||||
$audio->add($group ?? $this->user->identity);
|
|
||||||
|
if($playlist) {
|
||||||
|
$playlist->add($audio);
|
||||||
|
} else {
|
||||||
|
$audio->add($group ?? $this->user->identity);
|
||||||
|
}
|
||||||
|
|
||||||
if(!$isAjax)
|
if(!$isAjax)
|
||||||
$this->redirect(is_null($group) ? "/audios" . $this->user->id : "/audios-" . $group->getId());
|
$this->redirect(is_null($group) ? "/audios" . $this->user->id : "/audios-" . $group->getId());
|
||||||
|
@ -233,9 +260,9 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
else
|
else
|
||||||
$redirectLink .= $this->user->id;
|
$redirectLink .= $this->user->id;
|
||||||
|
|
||||||
$pagesCount = (int)ceil((new Audios)->getCollectionSizeByEntityId(isset($group) ? $group->getRealId() : $this->user->id) / 10);
|
if($playlist)
|
||||||
$redirectLink .= "?p=".$pagesCount;
|
$redirectLink = "/playlist" . $playlist->getPrettyId();
|
||||||
|
|
||||||
$this->returnJson([
|
$this->returnJson([
|
||||||
"success" => true,
|
"success" => true,
|
||||||
"redirect_link" => $redirectLink,
|
"redirect_link" => $redirectLink,
|
||||||
|
@ -279,7 +306,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderSearch(): void
|
function renderSearch(): void
|
||||||
{
|
{
|
||||||
$this->redirect("/search?type=audios");
|
$this->redirect("/search?section=audios");
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderNewPlaylist(): void
|
function renderNewPlaylist(): void
|
||||||
|
@ -304,6 +331,8 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
$title = $this->postParam("title");
|
$title = $this->postParam("title");
|
||||||
$description = $this->postParam("description");
|
$description = $this->postParam("description");
|
||||||
|
$is_unlisted = (int)$this->postParam('is_unlisted');
|
||||||
|
|
||||||
$audios = !empty($this->postParam("audios")) ? array_slice(explode(",", $this->postParam("audios")), 0, 1000) : [];
|
$audios = !empty($this->postParam("audios")) ? array_slice(explode(",", $this->postParam("audios")), 0, 1000) : [];
|
||||||
|
|
||||||
if(empty($title) || iconv_strlen($title) < 1)
|
if(empty($title) || iconv_strlen($title) < 1)
|
||||||
|
@ -313,7 +342,9 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
$playlist->setOwner($owner);
|
$playlist->setOwner($owner);
|
||||||
$playlist->setName(substr($title, 0, 125));
|
$playlist->setName(substr($title, 0, 125));
|
||||||
$playlist->setDescription(substr($description, 0, 2045));
|
$playlist->setDescription(substr($description, 0, 2045));
|
||||||
|
if($is_unlisted == 1)
|
||||||
|
$playlist->setUnlisted(true);
|
||||||
|
|
||||||
if($_FILES["cover"]["error"] === UPLOAD_ERR_OK) {
|
if($_FILES["cover"]["error"] === UPLOAD_ERR_OK) {
|
||||||
if(!str_starts_with($_FILES["cover"]["type"], "image"))
|
if(!str_starts_with($_FILES["cover"]["type"], "image"))
|
||||||
$this->flashFail("err", tr("error"), tr("not_a_photo"));
|
$this->flashFail("err", tr("error"), tr("not_a_photo"));
|
||||||
|
@ -427,6 +458,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
$title = $this->postParam("title");
|
$title = $this->postParam("title");
|
||||||
$description = $this->postParam("description");
|
$description = $this->postParam("description");
|
||||||
|
$is_unlisted = (int)$this->postParam('is_unlisted');
|
||||||
$new_audios = !empty($this->postParam("audios")) ? explode(",", rtrim($this->postParam("audios"), ",")) : [];
|
$new_audios = !empty($this->postParam("audios")) ? explode(",", rtrim($this->postParam("audios"), ",")) : [];
|
||||||
|
|
||||||
if(empty($title) || iconv_strlen($title) < 1)
|
if(empty($title) || iconv_strlen($title) < 1)
|
||||||
|
@ -436,6 +468,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
$playlist->setDescription(ovk_proc_strtr($description, 2045));
|
$playlist->setDescription(ovk_proc_strtr($description, 2045));
|
||||||
$playlist->setEdited(time());
|
$playlist->setEdited(time());
|
||||||
$playlist->resetLength();
|
$playlist->resetLength();
|
||||||
|
$playlist->setUnlisted((bool)$is_unlisted);
|
||||||
|
|
||||||
if($_FILES["new_cover"]["error"] === UPLOAD_ERR_OK) {
|
if($_FILES["new_cover"]["error"] === UPLOAD_ERR_OK) {
|
||||||
if(!str_starts_with($_FILES["new_cover"]["type"], "image"))
|
if(!str_starts_with($_FILES["new_cover"]["type"], "image"))
|
||||||
|
@ -475,12 +508,15 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
$this->template->playlist = $playlist;
|
$this->template->playlist = $playlist;
|
||||||
$this->template->page = $page;
|
$this->template->page = $page;
|
||||||
|
$this->template->cover = $playlist->getCoverPhoto();
|
||||||
|
$this->template->cover_url = $this->template->cover ? $this->template->cover->getURL() : "/assets/packages/static/openvk/img/song.jpg";
|
||||||
$this->template->audios = iterator_to_array($playlist->fetch($page, 10));
|
$this->template->audios = iterator_to_array($playlist->fetch($page, 10));
|
||||||
$this->template->ownerId = $owner_id;
|
$this->template->ownerId = $owner_id;
|
||||||
$this->template->owner = $playlist->getOwner();
|
$this->template->owner = $playlist->getOwner();
|
||||||
$this->template->isBookmarked = $this->user->identity && $playlist->isBookmarkedBy($this->user->identity);
|
$this->template->isBookmarked = $this->user->identity && $playlist->isBookmarkedBy($this->user->identity);
|
||||||
$this->template->isMy = $this->user->identity && $playlist->getOwner()->getId() === $this->user->id;
|
$this->template->isMy = $this->user->identity && $playlist->getOwner()->getId() === $this->user->id;
|
||||||
$this->template->canEdit = $this->user->identity && $playlist->canBeModifiedBy($this->user->identity);
|
$this->template->canEdit = $this->user->identity && $playlist->canBeModifiedBy($this->user->identity);
|
||||||
|
$this->template->count = $playlist->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAction(int $audio_id): void
|
function renderAction(int $audio_id): void
|
||||||
|
@ -531,16 +567,65 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "add_to_club":
|
case "add_to_club":
|
||||||
$club = (new Clubs)->get((int)$this->postParam("club"));
|
$detailed = [];
|
||||||
|
if($audio->isWithdrawn())
|
||||||
if(!$club || !$club->canBeModifiedBy($this->user->identity))
|
$this->flashFail("err", "error", tr("invalid_audio"), null, true);
|
||||||
$this->flashFail("err", "error", tr("access_denied"), null, true);
|
|
||||||
|
if(empty($this->postParam("clubs")))
|
||||||
if(!$audio->isInLibraryOf($club))
|
$this->flashFail("err", "error", 'clubs not passed', null, true);
|
||||||
$audio->add($club);
|
|
||||||
else
|
$clubs_arr = explode(',', $this->postParam("clubs"));
|
||||||
$this->flashFail("err", "error", tr("group_has_audio"), null, true);
|
$count = sizeof($clubs_arr);
|
||||||
|
if($count < 1 || $count > 10) {
|
||||||
|
$this->flashFail("err", "error", tr('too_many_or_to_lack'), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($clubs_arr as $club_id) {
|
||||||
|
$club = (new Clubs)->get((int)$club_id);
|
||||||
|
if(!$club || !$club->canBeModifiedBy($this->user->identity))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!$audio->isInLibraryOf($club)) {
|
||||||
|
$detailed[$club_id] = true;
|
||||||
|
$audio->add($club);
|
||||||
|
} else {
|
||||||
|
$detailed[$club_id] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->returnJson(["success" => true, 'detailed' => $detailed]);
|
||||||
|
break;
|
||||||
|
case "add_to_playlist":
|
||||||
|
$detailed = [];
|
||||||
|
if($audio->isWithdrawn())
|
||||||
|
$this->flashFail("err", "error", tr("invalid_audio"), null, true);
|
||||||
|
|
||||||
|
if(empty($this->postParam("playlists")))
|
||||||
|
$this->flashFail("err", "error", 'playlists not passed', null, true);
|
||||||
|
|
||||||
|
$playlists_arr = explode(',', $this->postParam("playlists"));
|
||||||
|
$count = sizeof($playlists_arr);
|
||||||
|
if($count < 1 || $count > 10) {
|
||||||
|
$this->flashFail("err", "error", tr('too_many_or_to_lack'), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($playlists_arr as $playlist_id) {
|
||||||
|
$pid = explode('_', $playlist_id);
|
||||||
|
$playlist = (new Audios)->getPlaylistByOwnerAndVID((int)$pid[0], (int)$pid[1]);
|
||||||
|
if(!$playlist || !$playlist->canBeModifiedBy($this->user->identity))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!$playlist->hasAudio($audio)) {
|
||||||
|
$playlist->add($audio);
|
||||||
|
$detailed[$playlist_id] = true;
|
||||||
|
} else {
|
||||||
|
$detailed[$playlist_id] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->returnJson(["success" => true, 'detailed' => $detailed]);
|
||||||
break;
|
break;
|
||||||
case "delete":
|
case "delete":
|
||||||
if($audio->canBeModifiedBy($this->user->identity))
|
if($audio->canBeModifiedBy($this->user->identity))
|
||||||
|
@ -653,6 +738,28 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
$audios = $stream->page($page, 10);
|
$audios = $stream->page($page, 10);
|
||||||
$audiosCount = $stream->size();
|
$audiosCount = $stream->size();
|
||||||
break;
|
break;
|
||||||
|
case "classic_search_context":
|
||||||
|
$data = json_decode($this->postParam("context_entity"), true);
|
||||||
|
|
||||||
|
$params = [];
|
||||||
|
$order = [
|
||||||
|
"type" => $data['order'] ?? 'id',
|
||||||
|
"invert" => (int)$data['invert'] == 1 ? true : false
|
||||||
|
];
|
||||||
|
|
||||||
|
if($data['genre'] && $data['genre'] != 'any')
|
||||||
|
$params['genre'] = $data['genre'];
|
||||||
|
|
||||||
|
if($data['only_performers'] && (int)$data['only_performers'] == 1)
|
||||||
|
$params['only_performers'] = '1';
|
||||||
|
|
||||||
|
if($data['with_lyrics'] && (int)$data['with_lyrics'] == 1)
|
||||||
|
$params['with_lyrics'] = '1';
|
||||||
|
|
||||||
|
$stream = $this->audios->find($data['query'], $params, $order);
|
||||||
|
$audios = $stream->page($page, 10);
|
||||||
|
$audiosCount = $stream->size();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pagesCount = ceil($audiosCount / $perPage);
|
$pagesCount = ceil($audiosCount / $perPage);
|
||||||
|
|
|
@ -233,7 +233,10 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
$club->setEveryone_Can_Create_Topics(empty($this->postParam("everyone_can_create_topics")) ? 0 : 1);
|
$club->setEveryone_Can_Create_Topics(empty($this->postParam("everyone_can_create_topics")) ? 0 : 1);
|
||||||
$club->setDisplay_Topics_Above_Wall(empty($this->postParam("display_topics_above_wall")) ? 0 : 1);
|
$club->setDisplay_Topics_Above_Wall(empty($this->postParam("display_topics_above_wall")) ? 0 : 1);
|
||||||
$club->setEveryone_can_upload_audios(empty($this->postParam("upload_audios")) ? 0 : 1);
|
$club->setEveryone_can_upload_audios(empty($this->postParam("upload_audios")) ? 0 : 1);
|
||||||
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed")) ? 0 : 1);
|
|
||||||
|
if (!$club->isHidingFromGlobalFeedEnforced()) {
|
||||||
|
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed") ? 0 : 1));
|
||||||
|
}
|
||||||
|
|
||||||
$website = $this->postParam("website") ?? "";
|
$website = $this->postParam("website") ?? "";
|
||||||
if(empty($website))
|
if(empty($website))
|
||||||
|
@ -279,48 +282,99 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderSetAvatar(int $id)
|
function renderSetAvatar(int $id)
|
||||||
{
|
{
|
||||||
$photo = new Photo;
|
$this->assertUserLoggedIn();
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
$club = $this->clubs->get($id);
|
$club = $this->clubs->get($id);
|
||||||
if ($club->isBanned()) $this->flashFail("err", tr("error"), tr("forbidden"));
|
|
||||||
if($_SERVER["REQUEST_METHOD"] === "POST" && $_FILES["ava"]["error"] === UPLOAD_ERR_OK) {
|
if(!$club || $club->isBanned() || !$club->canBeModifiedBy($this->user->identity))
|
||||||
|
$this->flashFail("err", tr("error"), tr("forbidden"), NULL, true);
|
||||||
|
|
||||||
|
if($_SERVER["REQUEST_METHOD"] === "POST" && $_FILES["blob"]["error"] === UPLOAD_ERR_OK) {
|
||||||
try {
|
try {
|
||||||
|
$photo = new Photo;
|
||||||
|
|
||||||
$anon = OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["anonymousPosting"]["enable"];
|
$anon = OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["anonymousPosting"]["enable"];
|
||||||
if($anon && $this->user->id === $club->getOwner()->getId())
|
if($anon && $this->user->id === $club->getOwner()->getId())
|
||||||
$anon = $club->isOwnerHidden();
|
$anon = $club->isOwnerHidden();
|
||||||
else if($anon)
|
else if($anon)
|
||||||
$anon = $club->getManager($this->user->identity)->isHidden();
|
$anon = $club->getManager($this->user->identity)->isHidden();
|
||||||
|
|
||||||
$photo->setOwner($this->user->id);
|
$photo->setOwner($this->user->id);
|
||||||
$photo->setDescription("Club image");
|
$photo->setDescription("Club image");
|
||||||
$photo->setFile($_FILES["ava"]);
|
$photo->setFile($_FILES["blob"]);
|
||||||
$photo->setCreated(time());
|
$photo->setCreated(time());
|
||||||
$photo->setAnonymous($anon);
|
$photo->setAnonymous($anon);
|
||||||
$photo->save();
|
$photo->save();
|
||||||
|
|
||||||
(new Albums)->getClubAvatarAlbum($club)->addPhoto($photo);
|
(new Albums)->getClubAvatarAlbum($club)->addPhoto($photo);
|
||||||
|
|
||||||
$flags = 0;
|
if($this->postParam("on_wall") == 1) {
|
||||||
$flags |= 0b00010000;
|
$post = new Post;
|
||||||
$flags |= 0b10000000;
|
|
||||||
|
$post->setOwner($this->user->id);
|
||||||
|
$post->setWall($club->getId() * -1);
|
||||||
|
$post->setCreated(time());
|
||||||
|
$post->setContent("");
|
||||||
|
|
||||||
$post = new Post;
|
$flags = 0;
|
||||||
$post->setOwner($this->user->id);
|
$flags |= 0b00010000;
|
||||||
$post->setWall($club->getId()*-1);
|
$flags |= 0b10000000;
|
||||||
$post->setCreated(time());
|
|
||||||
$post->setContent("");
|
|
||||||
$post->setFlags($flags);
|
|
||||||
$post->save();
|
|
||||||
$post->attach($photo);
|
|
||||||
|
|
||||||
} catch(ISE $ex) {
|
$post->setFlags($flags);
|
||||||
$name = $album->getName();
|
$post->save();
|
||||||
$this->flashFail("err", tr("error"), tr("error_when_uploading_photo"));
|
|
||||||
|
$post->attach($photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch(\Throwable $ex) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("error_when_uploading_photo"), NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->returnJson([
|
||||||
|
"success" => true,
|
||||||
|
"new_photo" => $photo->getPrettyId(),
|
||||||
|
"url" => $photo->getURL(),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return " ";
|
||||||
}
|
}
|
||||||
$this->returnJson([
|
|
||||||
"url" => $photo->getURL(),
|
|
||||||
"id" => $photo->getPrettyId()
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDeleteAvatar(int $id) {
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
$club = $this->clubs->get($id);
|
||||||
|
|
||||||
|
if(!$club || $club->isBanned() || !$club->canBeModifiedBy($this->user->identity))
|
||||||
|
$this->flashFail("err", tr("error"), tr("forbidden"), NULL, true);
|
||||||
|
|
||||||
|
$avatar = $club->getAvatarPhoto();
|
||||||
|
|
||||||
|
if(!$avatar)
|
||||||
|
$this->flashFail("succ", tr("error"), "no avatar bro", NULL, true);
|
||||||
|
|
||||||
|
$avatar->isolate();
|
||||||
|
|
||||||
|
$newAvatar = $club->getAvatarPhoto();
|
||||||
|
|
||||||
|
if(!$newAvatar)
|
||||||
|
$this->returnJson([
|
||||||
|
"success" => true,
|
||||||
|
"has_new_photo" => false,
|
||||||
|
"new_photo" => NULL,
|
||||||
|
"url" => "/assets/packages/static/openvk/img/camera_200.png",
|
||||||
|
]);
|
||||||
|
else
|
||||||
|
$this->returnJson([
|
||||||
|
"success" => true,
|
||||||
|
"has_new_photo" => true,
|
||||||
|
"new_photo" => $newAvatar->getPrettyId(),
|
||||||
|
"url" => $newAvatar->getURL(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
function renderEditBackdrop(int $id): void
|
function renderEditBackdrop(int $id): void
|
||||||
{
|
{
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
|
|
|
@ -274,7 +274,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
setlocale(LC_TIME, ...(explode(";", tr("__locale"))));
|
setlocale(LC_TIME, ...(explode(";", tr("__locale"))));
|
||||||
|
|
||||||
if (!OPENVK_ROOT_CONF["openvk"]["preferences"]["maintenanceMode"]["all"]) {
|
if (!OPENVK_ROOT_CONF["openvk"]["preferences"]["maintenanceMode"]["all"]) {
|
||||||
if (OPENVK_ROOT_CONF["openvk"]["preferences"]["maintenanceMode"][$this->presenterName]) {
|
if ($this->presenterName && OPENVK_ROOT_CONF["openvk"]["preferences"]["maintenanceMode"][$this->presenterName]) {
|
||||||
$this->pass("openvk!Maintenance->section", $this->presenterName);
|
$this->pass("openvk!Maintenance->section", $this->presenterName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -307,7 +307,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
$theme = Themepacks::i()[Session::i()->get("_sessionTheme", "ovk")];
|
$theme = Themepacks::i()[Session::i()->get("_sessionTheme", "ovk")];
|
||||||
} else if($this->requestParam("themePreview")) {
|
} else if($this->requestParam("themePreview")) {
|
||||||
$theme = Themepacks::i()[$this->requestParam("themePreview")];
|
$theme = Themepacks::i()[$this->requestParam("themePreview")];
|
||||||
} else if($this->user->identity !== NULL && $this->user->identity->getTheme()) {
|
} else if($this->user !== NULL && $this->user->identity !== NULL && $this->user->identity->getTheme()) {
|
||||||
$theme = $this->user->identity->getTheme();
|
$theme = $this->user->identity->getTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Presenters;
|
namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Models\Entities\{User, Club};
|
use openvk\Web\Models\Entities\{User, Club};
|
||||||
use openvk\Web\Models\Repositories\{Users, Clubs, Posts, Comments, Videos, Applications, Notes, Audios};
|
use openvk\Web\Models\Repositories\{Users, Clubs, Posts, Videos, Applications, Audios};
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
|
||||||
final class SearchPresenter extends OpenVKPresenter
|
final class SearchPresenter extends OpenVKPresenter
|
||||||
|
@ -9,21 +9,17 @@ final class SearchPresenter extends OpenVKPresenter
|
||||||
private $users;
|
private $users;
|
||||||
private $clubs;
|
private $clubs;
|
||||||
private $posts;
|
private $posts;
|
||||||
private $comments;
|
|
||||||
private $videos;
|
private $videos;
|
||||||
private $apps;
|
private $apps;
|
||||||
private $notes;
|
|
||||||
private $audios;
|
private $audios;
|
||||||
|
|
||||||
function __construct(Users $users, Clubs $clubs)
|
function __construct()
|
||||||
{
|
{
|
||||||
$this->users = $users;
|
$this->users = new Users;
|
||||||
$this->clubs = $clubs;
|
$this->clubs = new Clubs;
|
||||||
$this->posts = new Posts;
|
$this->posts = new Posts;
|
||||||
$this->comments = new Comments;
|
|
||||||
$this->videos = new Videos;
|
$this->videos = new Videos;
|
||||||
$this->apps = new Applications;
|
$this->apps = new Applications;
|
||||||
$this->notes = new Notes;
|
|
||||||
$this->audios = new Audios;
|
$this->audios = new Audios;
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
@ -33,85 +29,101 @@ final class SearchPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
$query = $this->queryParam("query") ?? "";
|
$query = $this->queryParam("q") ?? "";
|
||||||
$type = $this->queryParam("type") ?? "users";
|
$section = $this->queryParam("section") ?? "users";
|
||||||
$sorter = $this->queryParam("sort") ?? "id";
|
$order = $this->queryParam("order") ?? "id";
|
||||||
$invert = $this->queryParam("invert") == 1 ? "ASC" : "DESC";
|
$invert = (int) ($this->queryParam("invert") ?? 0) == 1;
|
||||||
$page = (int) ($this->queryParam("p") ?? 1);
|
$page = (int) ($this->queryParam("p") ?? 1);
|
||||||
|
|
||||||
# https://youtu.be/pSAWM5YuXx8
|
# https://youtu.be/pSAWM5YuXx8
|
||||||
|
# https://youtu.be/FfNZRhIn2Vk
|
||||||
|
|
||||||
$repos = [
|
$repos = [
|
||||||
"groups" => "clubs",
|
"groups" => "clubs",
|
||||||
"users" => "users",
|
"users" => "users",
|
||||||
"posts" => "posts",
|
"posts" => "posts",
|
||||||
"comments" => "comments",
|
|
||||||
"videos" => "videos",
|
"videos" => "videos",
|
||||||
"audios" => "audios",
|
"audios" => "audios",
|
||||||
"apps" => "apps",
|
"apps" => "apps",
|
||||||
"notes" => "notes"
|
"audios_playlists" => "audios"
|
||||||
|
];
|
||||||
|
$parameters = [
|
||||||
|
"ignore_private" => true,
|
||||||
];
|
];
|
||||||
|
|
||||||
switch($sorter) {
|
foreach($_REQUEST as $param_name => $param_value) {
|
||||||
default:
|
if(is_null($param_value)) continue;
|
||||||
case "id":
|
|
||||||
$sort = "id " . $invert;
|
switch($param_name) {
|
||||||
break;
|
default:
|
||||||
case "name":
|
$parameters[$param_name] = $param_value;
|
||||||
$sort = "first_name " . $invert;
|
break;
|
||||||
break;
|
case 'marital_status':
|
||||||
case "rating":
|
case 'polit_views':
|
||||||
$sort = "rating " . $invert;
|
if((int) $param_value == 0) continue;
|
||||||
break;
|
$parameters[$param_name] = $param_value;
|
||||||
case "length":
|
|
||||||
if($type != "audios") break;
|
break;
|
||||||
|
case 'is_online':
|
||||||
$sort = "length " . $invert;
|
if((int) $param_value == 1)
|
||||||
break;
|
$parameters['is_online'] = 1;
|
||||||
case "listens":
|
|
||||||
if($type != "audios") break;
|
break;
|
||||||
|
case 'only_performers':
|
||||||
$sort = "listens " . $invert;
|
if((int) $param_value == 1 || $param_value == 'on')
|
||||||
break;
|
$parameters['only_performers'] = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'with_lyrics':
|
||||||
|
if($param_value == 'on' || $param_value == '1')
|
||||||
|
$parameters['with_lyrics'] = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
# дай бог работал этот case
|
||||||
|
case 'from_me':
|
||||||
|
if((int) $param_value != 1) continue;
|
||||||
|
$parameters['from_me'] = $this->user->id;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$parameters = [
|
$repo = $repos[$section] or $this->throwError(400, "Bad Request", "Invalid search entity $section.");
|
||||||
"type" => $this->queryParam("type"),
|
|
||||||
"city" => $this->queryParam("city") != "" ? $this->queryParam("city") : NULL,
|
|
||||||
"maritalstatus" => $this->queryParam("maritalstatus") != 0 ? $this->queryParam("maritalstatus") : NULL,
|
|
||||||
"with_photo" => $this->queryParam("with_photo"),
|
|
||||||
"status" => $this->queryParam("status") != "" ? $this->queryParam("status") : NULL,
|
|
||||||
"politViews" => $this->queryParam("politViews") != 0 ? $this->queryParam("politViews") : NULL,
|
|
||||||
"email" => $this->queryParam("email"),
|
|
||||||
"telegram" => $this->queryParam("telegram"),
|
|
||||||
"site" => $this->queryParam("site") != "" ? "https://".$this->queryParam("site") : NULL,
|
|
||||||
"address" => $this->queryParam("address"),
|
|
||||||
"is_online" => $this->queryParam("is_online") == 1 ? 1 : NULL,
|
|
||||||
"interests" => $this->queryParam("interests") != "" ? $this->queryParam("interests") : NULL,
|
|
||||||
"fav_mus" => $this->queryParam("fav_mus") != "" ? $this->queryParam("fav_mus") : NULL,
|
|
||||||
"fav_films" => $this->queryParam("fav_films") != "" ? $this->queryParam("fav_films") : NULL,
|
|
||||||
"fav_shows" => $this->queryParam("fav_shows") != "" ? $this->queryParam("fav_shows") : NULL,
|
|
||||||
"fav_books" => $this->queryParam("fav_books") != "" ? $this->queryParam("fav_books") : NULL,
|
|
||||||
"fav_quote" => $this->queryParam("fav_quote") != "" ? $this->queryParam("fav_quote") : NULL,
|
|
||||||
"hometown" => $this->queryParam("hometown") != "" ? $this->queryParam("hometown") : NULL,
|
|
||||||
"before" => $this->queryParam("datebefore") != "" ? strtotime($this->queryParam("datebefore")) : NULL,
|
|
||||||
"after" => $this->queryParam("dateafter") != "" ? strtotime($this->queryParam("dateafter")) : NULL,
|
|
||||||
"gender" => $this->queryParam("gender") != "" && $this->queryParam("gender") != 2 ? $this->queryParam("gender") : NULL,
|
|
||||||
"doNotSearchPrivate" => true,
|
|
||||||
"only_performers" => $this->queryParam("only_performers") == "on" ? "1" : NULL,
|
|
||||||
"with_lyrics" => $this->queryParam("with_lyrics") == "on" ? true : NULL,
|
|
||||||
];
|
|
||||||
|
|
||||||
$repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type.");
|
|
||||||
|
|
||||||
$results = $this->{$repo}->find($query, $parameters, $sort);
|
$results = NULL;
|
||||||
$iterator = $results->page($page, 14);
|
switch($section) {
|
||||||
|
default:
|
||||||
|
$results = $this->{$repo}->find($query, $parameters, ['type' => $order, 'invert' => $invert]);
|
||||||
|
break;
|
||||||
|
case 'audios_playlists':
|
||||||
|
$results = $this->{$repo}->findPlaylists($query, $parameters, ['type' => $order, 'invert' => $invert]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iterator = $results->page($page, OPENVK_DEFAULT_PER_PAGE);
|
||||||
$count = $results->size();
|
$count = $results->size();
|
||||||
|
|
||||||
$this->template->iterator = iterator_to_array($iterator);
|
$this->template->order = $order;
|
||||||
|
$this->template->invert = $invert;
|
||||||
|
$this->template->data = $this->template->iterator = iterator_to_array($iterator);
|
||||||
$this->template->count = $count;
|
$this->template->count = $count;
|
||||||
$this->template->type = $type;
|
$this->template->section = $section;
|
||||||
$this->template->page = $page;
|
$this->template->page = $page;
|
||||||
$this->template->perPage = 14;
|
$this->template->perPage = OPENVK_DEFAULT_PER_PAGE;
|
||||||
|
$this->template->query = $query;
|
||||||
|
$this->template->atSearch = true;
|
||||||
|
|
||||||
|
$this->template->paginatorConf = (object) [
|
||||||
|
"page" => $page,
|
||||||
|
"count" => $count,
|
||||||
|
"amount" => sizeof($this->template->data),
|
||||||
|
"perPage" => $this->template->perPage,
|
||||||
|
"atBottom" => false,
|
||||||
|
"tidy" => true,
|
||||||
|
"space" => 6,
|
||||||
|
'pageCount' => ceil($count / $this->template->perPage),
|
||||||
|
];
|
||||||
|
$this->template->extendedPaginatorConf = clone $this->template->paginatorConf;
|
||||||
|
$this->template->extendedPaginatorConf->space = 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,13 +329,15 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$user = $this->users->get((int) $this->postParam("id"));
|
$user = $this->users->get((int) $this->postParam("id"));
|
||||||
if(!$user) exit("Invalid state");
|
if(!$user) exit("Invalid state");
|
||||||
|
|
||||||
$user->toggleSubscription($this->user->identity);
|
if ($this->postParam("act") == "rej")
|
||||||
|
$user->changeFlags($this->user->identity, 0b10000000, true);
|
||||||
|
else
|
||||||
|
$user->toggleSubscription($this->user->identity);
|
||||||
|
|
||||||
$this->redirect($user->getURL());
|
$this->redirect($_SERVER['HTTP_REFERER']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSetAvatar()
|
function renderSetAvatar() {
|
||||||
{
|
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
@ -346,8 +348,8 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$photo->setFile($_FILES["blob"]);
|
$photo->setFile($_FILES["blob"]);
|
||||||
$photo->setCreated(time());
|
$photo->setCreated(time());
|
||||||
$photo->save();
|
$photo->save();
|
||||||
} catch(ISE $ex) {
|
} catch(\Throwable $ex) {
|
||||||
$this->flashFail("err", tr("error"), tr("error_upload_failed"));
|
$this->flashFail("err", tr("error"), tr("error_upload_failed"), NULL, (int)$this->postParam("ajax", true) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$album = (new Albums)->getUserAvatarAlbum($this->user->identity);
|
$album = (new Albums)->getUserAvatarAlbum($this->user->identity);
|
||||||
|
@ -358,23 +360,57 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$flags = 0;
|
$flags = 0;
|
||||||
$flags |= 0b00010000;
|
$flags |= 0b00010000;
|
||||||
|
|
||||||
$post = new Post;
|
if($this->postParam("on_wall") == 1) {
|
||||||
$post->setOwner($this->user->id);
|
$post = new Post;
|
||||||
$post->setWall($this->user->id);
|
$post->setOwner($this->user->id);
|
||||||
$post->setCreated(time());
|
$post->setWall($this->user->id);
|
||||||
$post->setContent("");
|
$post->setCreated(time());
|
||||||
$post->setFlags($flags);
|
$post->setContent("");
|
||||||
$post->save();
|
$post->setFlags($flags);
|
||||||
$post->attach($photo);
|
$post->save();
|
||||||
if($this->postParam("ava", true) == (int)1) {
|
|
||||||
|
$post->attach($photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((int)$this->postParam("ajax", true) == 1) {
|
||||||
$this->returnJson([
|
$this->returnJson([
|
||||||
"url" => $photo->getURL(),
|
"success" => true,
|
||||||
"id" => $photo->getPrettyId()
|
"new_photo" => $photo->getPrettyId(),
|
||||||
|
"url" => $photo->getURL(),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$this->flashFail("succ", tr("photo_saved"), tr("photo_saved_comment"));
|
$this->flashFail("succ", tr("photo_saved"), tr("photo_saved_comment"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDeleteAvatar() {
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
$avatar = $this->user->identity->getAvatarPhoto();
|
||||||
|
|
||||||
|
if(!$avatar)
|
||||||
|
$this->flashFail("succ", tr("error"), "no avatar bro", NULL, true);
|
||||||
|
|
||||||
|
$avatar->isolate();
|
||||||
|
|
||||||
|
$newAvatar = $this->user->identity->getAvatarPhoto();
|
||||||
|
|
||||||
|
if(!$newAvatar)
|
||||||
|
$this->returnJson([
|
||||||
|
"success" => true,
|
||||||
|
"has_new_photo" => false,
|
||||||
|
"new_photo" => NULL,
|
||||||
|
"url" => "/assets/packages/static/openvk/img/camera_200.png",
|
||||||
|
]);
|
||||||
|
else
|
||||||
|
$this->returnJson([
|
||||||
|
"success" => true,
|
||||||
|
"has_new_photo" => true,
|
||||||
|
"new_photo" => $newAvatar->getPrettyId(),
|
||||||
|
"url" => $newAvatar->getURL(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
function renderSettings(): void
|
function renderSettings(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,8 +186,12 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderRoute(string $object, string $method): void
|
function renderRoute(string $object, string $method): void
|
||||||
{
|
{
|
||||||
|
$callback = $this->queryParam("callback");
|
||||||
$authMechanism = $this->queryParam("auth_mechanism") ?? "token";
|
$authMechanism = $this->queryParam("auth_mechanism") ?? "token";
|
||||||
if($authMechanism === "roaming") {
|
if($authMechanism === "roaming") {
|
||||||
|
if($callback)
|
||||||
|
$this->fail(-1, "User authorization failed: roaming mechanism is unavailable with jsonp.", $object, $method);
|
||||||
|
|
||||||
if(!$this->user->identity)
|
if(!$this->user->identity)
|
||||||
$this->fail(5, "User authorization failed: roaming mechanism is selected, but user is not logged in.", $object, $method);
|
$this->fail(5, "User authorization failed: roaming mechanism is selected, but user is not logged in.", $object, $method);
|
||||||
else
|
else
|
||||||
|
@ -234,8 +238,14 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
settype($val, $parameter->getType()->getName());
|
// Проверка типа параметра
|
||||||
$params[] = $val;
|
$type = $parameter->getType();
|
||||||
|
if (($type && !$type->isBuiltin()) || is_null($val)) {
|
||||||
|
$params[] = $val;
|
||||||
|
} else {
|
||||||
|
settype($val, $parameter->getType()->getName());
|
||||||
|
$params[] = $val;
|
||||||
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
// Just ignore the exception, since
|
// Just ignore the exception, since
|
||||||
// some args are intended for internal use
|
// some args are intended for internal use
|
||||||
|
@ -253,10 +263,16 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
$result = json_encode([
|
$result = json_encode([
|
||||||
"response" => $res,
|
"response" => $res,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if($callback) {
|
||||||
|
$result = $callback . '(' . $result . ')';
|
||||||
|
header('Content-Type: application/javascript');
|
||||||
|
} else
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
|
||||||
$size = strlen($result);
|
$size = strlen($result);
|
||||||
header("Content-Type: application/json");
|
|
||||||
header("Content-Length: $size");
|
header("Content-Length: $size");
|
||||||
|
|
||||||
exit($result);
|
exit($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,17 +302,31 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
$this->fail(28, "Invalid 2FA code", "internal", "acquireToken");
|
$this->fail(28, "Invalid 2FA code", "internal", "acquireToken");
|
||||||
}
|
}
|
||||||
|
|
||||||
$platform = $this->requestParam("client_name");
|
$token = NULL;
|
||||||
|
$tokenIsStale = true;
|
||||||
$token = new APIToken;
|
$platform = $this->requestParam("client_name");
|
||||||
$token->setUser($user);
|
$acceptsStale = $this->requestParam("accepts_stale");
|
||||||
$token->setPlatform($platform ?? (new WhichBrowser\Parser(getallheaders()))->toString());
|
if($acceptsStale == "1") {
|
||||||
$token->save();
|
if(is_null($platform))
|
||||||
|
$this->fail(101, "accepts_stale can only be used with explicitly set client_name", "internal", "acquireToken");
|
||||||
|
|
||||||
|
$token = (new APITokens)->getStaleByUser($uId, $platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_null($token)) {
|
||||||
|
$tokenIsStale = false;
|
||||||
|
|
||||||
|
$token = new APIToken;
|
||||||
|
$token->setUser($user);
|
||||||
|
$token->setPlatform($platform ?? (new WhichBrowser\Parser(getallheaders()))->toString());
|
||||||
|
$token->save();
|
||||||
|
}
|
||||||
|
|
||||||
$payload = json_encode([
|
$payload = json_encode([
|
||||||
"access_token" => $token->getFormattedToken(),
|
"access_token" => $token->getFormattedToken(),
|
||||||
"expires_in" => 0,
|
"expires_in" => 0,
|
||||||
"user_id" => $uId,
|
"user_id" => $uId,
|
||||||
|
"is_stale" => $tokenIsStale,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$size = strlen($payload);
|
$size = strlen($payload);
|
||||||
|
@ -304,4 +334,42 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
header("Content-Length: $size");
|
header("Content-Length: $size");
|
||||||
exit($payload);
|
exit($payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderOAuthLogin() {
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
|
$client = $this->queryParam("client_name");
|
||||||
|
$postmsg = $this->queryParam("prefers_postMessage") ?? '0';
|
||||||
|
$stale = $this->queryParam("accepts_stale") ?? '0';
|
||||||
|
$origin = NULL;
|
||||||
|
$url = $this->queryParam("redirect_uri");
|
||||||
|
if(is_null($url) || is_null($client))
|
||||||
|
exit("<b>Error:</b> redirect_uri and client_name params are required.");
|
||||||
|
|
||||||
|
if($url != "about:blank") {
|
||||||
|
if(!filter_var($url, FILTER_VALIDATE_URL))
|
||||||
|
exit("<b>Error:</b> Invalid URL passed to redirect_uri.");
|
||||||
|
|
||||||
|
$parsedUrl = (object) parse_url($url);
|
||||||
|
if($parsedUrl->scheme != 'https' && $parsedUrl->scheme != 'http')
|
||||||
|
exit("<b>Error:</b> redirect_uri should either point to about:blank or to a web resource.");
|
||||||
|
|
||||||
|
$origin = "$parsedUrl->scheme://$parsedUrl->host";
|
||||||
|
if(!is_null($parsedUrl->port ?? NULL))
|
||||||
|
$origin .= ":$parsedUrl->port";
|
||||||
|
|
||||||
|
$url .= strpos($url, '?') === false ? '?' : '&';
|
||||||
|
} else {
|
||||||
|
$url .= "#";
|
||||||
|
if($postmsg == '1') {
|
||||||
|
exit("<b>Error:</b> prefers_postMessage can only be set if redirect_uri is not about:blank");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->template->clientName = $client;
|
||||||
|
$this->template->usePostMessage = $postmsg == '1';
|
||||||
|
$this->template->acceptsStale = $stale == '1';
|
||||||
|
$this->template->origin = $origin;
|
||||||
|
$this->template->redirectUri = $url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,11 @@
|
||||||
{script "js/l10n.js"}
|
{script "js/l10n.js"}
|
||||||
{script "js/openvk.cls.js"}
|
{script "js/openvk.cls.js"}
|
||||||
{script "js/node_modules/dashjs/dist/dash.all.min.js"}
|
{script "js/node_modules/dashjs/dist/dash.all.min.js"}
|
||||||
|
<script src="/assets/packages/static/openvk/js/node_modules/cropperjs/dist/cropper.js" type="module"></script>
|
||||||
{script "js/al_music.js"}
|
{script "js/al_music.js"}
|
||||||
|
|
||||||
{css "js/node_modules/tippy.js/dist/backdrop.css"}
|
{css "js/node_modules/tippy.js/dist/backdrop.css"}
|
||||||
|
{css "js/node_modules/cropperjs/dist/cropper.css"}
|
||||||
{css "js/node_modules/tippy.js/dist/border.css"}
|
{css "js/node_modules/tippy.js/dist/border.css"}
|
||||||
{css "js/node_modules/tippy.js/dist/svg-arrow.css"}
|
{css "js/node_modules/tippy.js/dist/svg-arrow.css"}
|
||||||
{css "js/node_modules/tippy.js/themes/light.css"}
|
{css "js/node_modules/tippy.js/themes/light.css"}
|
||||||
|
@ -85,7 +87,7 @@
|
||||||
|
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<div id="xhead" class="dm"></div>
|
<div id="xhead" class="dm"></div>
|
||||||
<div class="page_header{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} page_custom_header{/if}">
|
<div class="page_header{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} page_custom_header{/if}{if $atSearch} search_expanded search_expanded_at_all{/if}">
|
||||||
<a href="/" class="home_button{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} home_button_custom{/if}" title="{$instance_name}">{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}{$instance_name}{/if}</a>
|
<a href="/" class="home_button{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} home_button_custom{/if}" title="{$instance_name}">{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}{$instance_name}{/if}</a>
|
||||||
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
|
@ -94,67 +96,45 @@
|
||||||
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
||||||
</div>
|
</div>
|
||||||
{else}
|
{else}
|
||||||
<div class="link dec">
|
<div class="link">
|
||||||
<a href="/">{_header_home}</a>
|
<a href="/">{_header_home}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link dec">
|
<div class="link">
|
||||||
<a href="/search?type=groups">{_header_groups}</a>
|
<a href="/search?section=groups">{_header_groups}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link dec">
|
<div class="link">
|
||||||
<a href="/search">{_header_search}</a>
|
<a href="/search?q=§ion=users&order=rating">{_header_search}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link dec">
|
<div class="link">
|
||||||
<a href="/invite">{_header_invite}</a>
|
<a href="/invite">{_header_invite}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link dec">
|
<div class="link">
|
||||||
<a href="/support">{_header_help} <b n:if="$ticketAnsweredCount > 0">({$ticketAnsweredCount})</b></a>
|
<a href="/support">{_header_help} <b n:if="$ticketAnsweredCount > 0">({$ticketAnsweredCount})</b></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link dec">
|
<div class="link">
|
||||||
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
||||||
</div>
|
</div>
|
||||||
{var $atSearch = str_contains($_SERVER['REQUEST_URI'], "/search")}
|
<div id="search_box" class='header_divider_stick'>
|
||||||
<div id="srch" class="{if $atSearch}nodivider{else}link{/if}">
|
<div id="search_box_fr">
|
||||||
|
<form id='search_form' action="/search" method="get">
|
||||||
{if !$atSearch}
|
<div id='search_and_one_more_wrapper'>
|
||||||
<form action="/search" method="get" id="searcher" style="position:relative;">
|
<input n:attr="value => $_REQUEST['q'] ? $_REQUEST['q'] : NULL" autocomplete="off" type="search" maxlength="79" name="q" placeholder="{_header_search}" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
||||||
<input autocomplete="off" id="searchInput" oninput="checkSearchTips()" onfocus="expandSearch()" onblur="decreaseSearch()" class="sr" type="search" name="query" placeholder="{_header_search}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
<select name="section">
|
||||||
<select onchange="checkSearchTips()" id="typer" name="type" class="whatFind" style="display:none;top: 0px;">
|
<option n:attr="selected => $_REQUEST['section'] == 'users'" value="users">{_s_by_people}</option>
|
||||||
<option value="users">{_s_by_people}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'groups'" value="groups">{_s_by_groups}</option>
|
||||||
<option value="groups">{_s_by_groups}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'posts'" value="posts">{_s_by_posts}</option>
|
||||||
<option value="posts">{_s_by_posts}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'videos'" value="videos">{_s_by_videos}</option>
|
||||||
<option value="comments">{_s_by_comments}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'apps'" value="apps">{_s_by_apps}</option>
|
||||||
<option value="videos">{_s_by_videos}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'audios'" value="audios">{_s_by_audios}</option>
|
||||||
<option value="apps">{_s_by_apps}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'audios_playlists'" value="audios_playlists">{_s_by_audios_playlists}</option>
|
||||||
<option value="audios">{_s_by_audios}</option>
|
</select>
|
||||||
</select>
|
</div>
|
||||||
|
<button class="search_box_button">
|
||||||
|
<span>{_header_search}</span>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="searchTips" id="srcht" hidden>
|
</div>
|
||||||
<table style="border:none;border-spacing: 0;">
|
<div id="searchBoxFastTips"></div>
|
||||||
<tbody id="srchrr">
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{else}
|
|
||||||
<form action="/search" method="get" id="searcher" style="margin-top: -1px;position:relative;">
|
|
||||||
<input id="searchInput" value="{$_GET['query'] ?? ''}" type="search" class="sr" name="query" placeholder="{_header_search}" style="height: 20px; background-color: #fff; padding-left: 6px;width: 555px;" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
|
||||||
<select name="type" class="whatFind">
|
|
||||||
<option value="users" {if str_contains($_SERVER['REQUEST_URI'], "type=users")}selected{/if}>{_s_by_people}</option>
|
|
||||||
<option value="groups" {if str_contains($_SERVER['REQUEST_URI'], "type=groups")}selected{/if}>{_s_by_groups}</option>
|
|
||||||
<option value="posts" {if str_contains($_SERVER['REQUEST_URI'], "type=posts")}selected{/if}>{_s_by_posts}</option>
|
|
||||||
<option value="comments" {if str_contains($_SERVER['REQUEST_URI'], "type=comments")}selected{/if}>{_s_by_comments}</option>
|
|
||||||
<option value="videos" {if str_contains($_SERVER['REQUEST_URI'], "type=videos")}selected{/if}>{_s_by_videos}</option>
|
|
||||||
<option value="apps" {if str_contains($_SERVER['REQUEST_URI'], "type=apps")}selected{/if}>{_s_by_apps}</option>
|
|
||||||
<option value="audios" {if str_contains($_SERVER['REQUEST_URI'], "type=audios")}selected{/if}>{_s_by_audios}</option>
|
|
||||||
</select>
|
|
||||||
<button class="searchBtn"><span style="color:white;font-weight: 600;font-size:12px;">{_header_search}</span></button>
|
|
||||||
</form>
|
|
||||||
<script>
|
|
||||||
let els = document.querySelectorAll("div.dec")
|
|
||||||
for(const element of els) {
|
|
||||||
element.style.display = "none"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{else}
|
{else}
|
||||||
|
@ -178,9 +158,9 @@
|
||||||
<a href="/edit" class="link edit-button">{_edit_button}</a>
|
<a href="/edit" class="link edit-button">{_edit_button}</a>
|
||||||
<a href="{$thisUser->getURL()}" class="link" title="{_my_page} [Alt+Shift+.]" accesskey=".">{_my_page}</a>
|
<a href="{$thisUser->getURL()}" class="link" title="{_my_page} [Alt+Shift+.]" accesskey=".">{_my_page}</a>
|
||||||
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
|
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
|
||||||
<object type="internal/link" n:if="$thisUser->getFollowersCount() > 0">
|
<object type="internal/link" n:if="$thisUser->getRequestsCount() > 0">
|
||||||
<a href="/friends{$thisUser->getId()}?act=incoming" class="linkunderline">
|
<a href="/friends{$thisUser->getId()}?act=incoming" class="linkunderline">
|
||||||
(<b>{$thisUser->getFollowersCount()}</b>)
|
(<b>{$thisUser->getRequestsCount()}</b>)
|
||||||
</a>
|
</a>
|
||||||
</object>
|
</object>
|
||||||
</a>
|
</a>
|
||||||
|
@ -196,9 +176,9 @@
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('groups')" href="/groups{$thisUser->getId()}" class="link">{_my_groups}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('groups')" href="/groups{$thisUser->getId()}" class="link">{_my_groups}</a>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link" title="{_my_feed} [Alt+Shift+,]" accesskey=",">{_my_feed}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link" title="{_my_feed} [Alt+Shift+,]" accesskey=",">{_my_feed}</a>
|
||||||
<a href="/notifications" class="link" title="{_my_feedback} [Alt+Shift+N]" accesskey="n">{_my_feedback}
|
<a href="/notifications" class="link" title="{_my_feedback} [Alt+Shift+N]" accesskey="n">{_my_feedback}
|
||||||
{if $thisUser->getNotificationsCount() > 0}
|
<object type="internal/link" n:if="$thisUser->getNotificationsCount() > 0">
|
||||||
(<b>{$thisUser->getNotificationsCount()}</b>)
|
(<b>{$thisUser->getNotificationsCount()}</b>)
|
||||||
{/if}
|
</object>
|
||||||
</a>
|
</a>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_my_apps}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_my_apps}</a>
|
||||||
<a href="/settings" class="link">{_my_settings}</a>
|
<a href="/settings" class="link">{_my_settings}</a>
|
||||||
|
@ -398,19 +378,13 @@
|
||||||
{script "js/al_mentions.js"}
|
{script "js/al_mentions.js"}
|
||||||
{script "js/al_polls.js"}
|
{script "js/al_polls.js"}
|
||||||
{script "js/al_suggestions.js"}
|
{script "js/al_suggestions.js"}
|
||||||
|
{script "js/al_navigation.js"}
|
||||||
|
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
{script "js/al_notifs.js"}
|
{script "js/al_notifs.js"}
|
||||||
{script "js/al_feed.js"}
|
{script "js/al_feed.js"}
|
||||||
{/ifset}
|
{/ifset}
|
||||||
|
|
||||||
{if OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['fartscroll']}
|
|
||||||
<script src="https://unpkg.com/fartscroll@1.0.0/fartscroll.js"></script>
|
|
||||||
<script>
|
|
||||||
fartscroll(400);
|
|
||||||
</script>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<script>bsdnHydrate();</script>
|
<script>bsdnHydrate();</script>
|
||||||
|
|
||||||
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['enable']" async defer data-domain="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['domain']}" src="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['server']}js/plausible.js"></script>
|
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['enable']" async defer data-domain="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['domain']}" src="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['server']}js/plausible.js"></script>
|
||||||
|
@ -448,7 +422,8 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.openvk = {
|
window.openvk = {
|
||||||
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres}
|
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres},
|
||||||
|
"at_search": {$atSearch ?? false},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
{include description, x => $dat}
|
{include description, x => $dat}
|
||||||
{/ifset}
|
{/ifset}
|
||||||
</td>
|
</td>
|
||||||
<td n:ifset="actions" valign="top" class="action_links" style="width: 150px;">
|
<td n:ifset="actions" valign="top" class="action_links" style="min-width: 150px;">
|
||||||
{include actions, x => $dat}
|
{include actions, x => $dat}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -255,17 +255,6 @@
|
||||||
Disabled
|
Disabled
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td class="e">
|
|
||||||
Fartscroll
|
|
||||||
</td>
|
|
||||||
<td class="v">
|
|
||||||
{php echo OPENVK_ROOT_CONF["openvk"]["preferences"]["bellsAndWhistles"]["fartscroll"] ? "Enabled" : "Disabled"}
|
|
||||||
</td>
|
|
||||||
<td class="v">
|
|
||||||
Disabled
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">
|
<td class="e">
|
||||||
NDA Test Label
|
NDA Test Label
|
||||||
|
@ -282,7 +271,7 @@
|
||||||
Number verification
|
Number verification
|
||||||
</td>
|
</td>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
{php echo OPENVK_ROOT_CONF["openvk"]["credentials"]["zadarma"]["enable"] ? "SMS (Zadarma)" : "Disabled"}
|
{php echo OPENVK_ROOT_CONF["openvk"]["credentials"]["smsc"]["enable"] ? "SMS" : "Disabled"}
|
||||||
</td>
|
</td>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
Disabled
|
Disabled
|
||||||
|
@ -364,21 +353,21 @@
|
||||||
Vladimir Barinov, Konstantin Kichulkin and Daniel Myslivets
|
Vladimir Barinov, Konstantin Kichulkin and Daniel Myslivets
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr n:foreach="$themes as $theme">
|
<tr n:foreach="$themes as $themeEntry">
|
||||||
<td class="e">
|
<td class="e">
|
||||||
{$theme->getName()}
|
{$themeEntry->getName()}
|
||||||
</td>
|
</td>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
{$theme->isEnabled() ? "Enabled" : "Installed"}
|
{$themeEntry->isEnabled() ? "Enabled" : "Installed"}
|
||||||
</td>
|
</td>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
{$theme->getVersion()}
|
{$themeEntry->getVersion()}
|
||||||
</td>
|
</td>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
{$theme->getDescription()|truncate:20}
|
{$themeEntry->getDescription()|truncate:20}
|
||||||
</td>
|
</td>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
{$theme->getAuthor()}
|
{$themeEntry->getAuthor()}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -58,13 +58,17 @@
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" {if $club->isVerified()} checked {/if} />
|
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" n:attr="checked => $club->isVerified()" />
|
||||||
<label for="verify">{_admin_verification}</label>
|
<label for="verify">{_admin_verification}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<input class="toggle-large" type="checkbox" id="hide_from_global_feed" name="hide_from_global_feed" value="1" {if $club->isHideFromGlobalFeedEnabled()} checked {/if} />
|
<input class="toggle-large" type="checkbox" id="hide_from_global_feed" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled()" />
|
||||||
<label for="hide_from_global_feed">{_admin_club_excludeglobalfeed}</label>
|
<label for="hide_from_global_feed">{_admin_club_excludeglobalfeed}</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="group">
|
||||||
|
<input class="toggle-large" type="checkbox" id="enforce_hiding_from_global_feed" name="enforce_hiding_from_global_feed" value="1" n:attr="checked => $club->isHidingFromGlobalFeedEnforced()" />
|
||||||
|
<label for="enforce_hiding_from_global_feed">{_admin_club_enforceexcludeglobalfeed}</label>
|
||||||
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="buttons-container">
|
<div class="buttons-container">
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<center>
|
<center>
|
||||||
<iframe id="appFrame" referrerpolicy="unsafe-url" sandbox="allow-scripts" frameBorder="0" src="{$url}" height="600" width="600"></iframe>
|
<iframe id="appFrame" referrerpolicy="unsafe-url" frameBorder="0" src="{$url}" height="600" width="600"
|
||||||
|
sandbox="allow-scripts allow-same-origin allow-pointer-lock allow-forms allow-downloads-without-user-activation"></iframe>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
<div n:if="!is_null($news)" id="news">
|
<div n:if="!is_null($news)" id="news">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{block header}
|
{block header}
|
||||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||||
»
|
»
|
||||||
<a href="/audios{$ownerId}">{_audios}</a>
|
<a href="/playlists{$ownerId}">{_playlists}</a>
|
||||||
»
|
»
|
||||||
<a href="/playlist{$playlist->getPrettyId()}">{_playlist}</a>
|
<a href="/playlist{$playlist->getPrettyId()}">{_playlist}</a>
|
||||||
»
|
»
|
||||||
|
@ -30,8 +30,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="moreInfo">
|
<div class="moreInfo">
|
||||||
<textarea name="description" maxlength="2045" style="margin-top: 11px;">{$playlist->getDescription()}</textarea>
|
<textarea placeholder="{_description}" name="description" maxlength="2045" style="margin-top: 11px;">{$playlist->getDescription()}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type='checkbox' name='is_unlisted' n:attr='checked => $playlist->isUnlisted()'>
|
||||||
|
{_playlist_hide_from_search}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -56,6 +61,7 @@
|
||||||
<form method="post" id="editPlaylistForm" data-id="{$playlist->getId()}" enctype="multipart/form-data">
|
<form method="post" id="editPlaylistForm" data-id="{$playlist->getId()}" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="title" maxlength="128" />
|
<input type="hidden" name="title" maxlength="128" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<input type="hidden" name="is_unlisted" value="0" />
|
||||||
<textarea style="display:none;" name="description" maxlength="2048" />
|
<textarea style="display:none;" name="description" maxlength="2048" />
|
||||||
<input type="hidden" name="audios">
|
<input type="hidden" name="audios">
|
||||||
<input type="file" style="display:none;" name="new_cover" accept=".jpg,.png">
|
<input type="file" style="display:none;" name="new_cover" accept=".jpg,.png">
|
||||||
|
@ -71,6 +77,7 @@
|
||||||
u("#editPlaylistForm").on("submit", (e) => {
|
u("#editPlaylistForm").on("submit", (e) => {
|
||||||
document.querySelector("#editPlaylistForm input[name='title']").value = document.querySelector(".playlistInfo input[name='title']").value
|
document.querySelector("#editPlaylistForm input[name='title']").value = document.querySelector(".playlistInfo input[name='title']").value
|
||||||
document.querySelector("#editPlaylistForm textarea[name='description']").value = document.querySelector(".playlistBlock textarea[name='description']").value
|
document.querySelector("#editPlaylistForm textarea[name='description']").value = document.querySelector(".playlistBlock textarea[name='description']").value
|
||||||
|
document.querySelector("#editPlaylistForm input[name='is_unlisted']").value = document.querySelector("input[name='is_unlisted']").checked ? 1 : 0
|
||||||
})
|
})
|
||||||
|
|
||||||
u("#editPlaylistForm input[name='new_cover']").on("change", (e) => {
|
u("#editPlaylistForm input[name='new_cover']").on("change", (e) => {
|
||||||
|
|
|
@ -59,66 +59,47 @@
|
||||||
<input n:if="$mode == 'popular'" type="hidden" name="bigplayer_context" data-type="popular_audios" data-entity="0" data-page="1">
|
<input n:if="$mode == 'popular'" type="hidden" name="bigplayer_context" data-type="popular_audios" data-entity="0" data-page="1">
|
||||||
<div class="bigPlayerDetector"></div>
|
<div class="bigPlayerDetector"></div>
|
||||||
|
|
||||||
<div style="width: 100%;display: flex;margin-bottom: -10px;" class="audiosDiv">
|
<div class="audiosDiv">
|
||||||
<div style="width: 74%;" class="audiosContainer" n:if="$mode != 'playlists'">
|
<div style="width: 74%;" class="audiosContainer audiosPaddingContainer" n:if="$mode != 'playlists'">
|
||||||
<div style="padding: 8px;">
|
<div n:if="$audiosCount <= 0" style='height: 50%;'>
|
||||||
<div n:if="$audiosCount <= 0">
|
{include "../components/content_error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_audios_thisuser") : tr("no_audios_user")) : tr("no_audios_club")}
|
||||||
{include "../components/error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_audios_thisuser") : tr("no_audios_user")) : tr("no_audios_club")}
|
</div>
|
||||||
</div>
|
<div n:if="$audiosCount > 0" class="infContainer">
|
||||||
<div n:if="$audiosCount > 0" class="infContainer">
|
<div class="infObj" n:foreach="$audios as $audio">
|
||||||
<div class="infObj" n:foreach="$audios as $audio">
|
{include "player.xml", audio => $audio, club => $club}
|
||||||
{include "player.xml", audio => $audio, club => $club}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div n:if="$mode != 'new' && $mode != 'popular'">
|
<div n:if="$mode != 'new' && $mode != 'popular'">
|
||||||
{include "../components/paginator.xml", conf => (object) [
|
{include "../components/paginator.xml", conf => (object) [
|
||||||
"page" => $page,
|
"page" => $page,
|
||||||
"count" => $audiosCount,
|
"count" => $audiosCount,
|
||||||
"amount" => sizeof($audios),
|
"amount" => sizeof($audios),
|
||||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||||
"atBottom" => true,
|
"atBottom" => true,
|
||||||
]}
|
]}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="width: 74%;" n:if="$mode == 'playlists'">
|
<div style="width: 71.8%;" class="audiosPaddingContainer audiosPaddingContainer" n:if="$mode == 'playlists'">
|
||||||
<div style="padding: 8px;">
|
<div n:if="$playlistsCount <= 0" style='height: 100%;'>
|
||||||
<div n:if="$playlistsCount <= 0">
|
{include "../components/content_error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_playlists_thisuser") : tr("no_playlists_user")) : tr("no_playlists_club")}
|
||||||
{include "../components/error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_playlists_thisuser") : tr("no_playlists_user")) : tr("no_playlists_club")}
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="infContainer playlistContainer" n:if="$playlistsCount > 0">
|
<div class="infContainer playlistContainer" n:if="$playlistsCount > 0">
|
||||||
<div class="infObj" n:foreach="$playlists as $playlist">
|
{foreach $playlists as $playlist}
|
||||||
<a href="/playlist{$playlist->getPrettyId()}">
|
{include 'playlistListView.xml', playlist => $playlist}
|
||||||
<div class="playlistCover">
|
{/foreach}
|
||||||
<img src="{$playlist->getCoverURL()}" alt="{_playlist_cover}">
|
</div>
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
|
<div>
|
||||||
<div class="playlistInfo">
|
{include "../components/paginator.xml", conf => (object) [
|
||||||
<a href="/playlist{$playlist->getPrettyId()}">
|
"page" => $page,
|
||||||
<span style="font-size: 12px" class="playlistName">
|
"count" => $playlistsCount,
|
||||||
{ovk_proc_strtr($playlist->getName(), 15)}
|
"amount" => sizeof($playlists),
|
||||||
</span>
|
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||||
</a>
|
"atBottom" => true,
|
||||||
|
]}
|
||||||
<a href="{$playlist->getOwner()->getURL()}">{ovk_proc_strtr($playlist->getOwner()->getCanonicalName(), 20)}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{include "../components/paginator.xml", conf => (object) [
|
|
||||||
"page" => $page,
|
|
||||||
"count" => $playlistsCount,
|
|
||||||
"amount" => sizeof($playlists),
|
|
||||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
|
||||||
"atBottom" => true,
|
|
||||||
]}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{include "tabs.xml"}
|
{include "tabs.xml"}
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
{if !$_GET["gid"]}
|
{if !$_GET["gid"]}
|
||||||
<a href="{$thisUser->getURL()}">{$thisUser->getCanonicalName()}</a>
|
<a href="{$thisUser->getURL()}">{$thisUser->getCanonicalName()}</a>
|
||||||
»
|
»
|
||||||
<a href="/audios{$thisUser->getId()}">{_audios}</a>
|
<a href="/playlists{$thisUser->getId()}">{_playlists}</a>
|
||||||
{else}
|
{else}
|
||||||
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
||||||
»
|
»
|
||||||
<a href="/audios-{$club->getId()}">{_audios}</a>
|
<a href="/playlists-{$club->getId()}">{_playlists}</a>
|
||||||
{/if}
|
{/if}
|
||||||
»
|
»
|
||||||
{_new_playlist}
|
{_new_playlist}
|
||||||
|
@ -44,6 +44,10 @@
|
||||||
<div class="moreInfo" style="margin-top: 11px;">
|
<div class="moreInfo" style="margin-top: 11px;">
|
||||||
<textarea placeholder="{_description}" name="description" maxlength="2045" />
|
<textarea placeholder="{_description}" name="description" maxlength="2045" />
|
||||||
</div>
|
</div>
|
||||||
|
<label>
|
||||||
|
<input type='checkbox' name='is_unlisted'>
|
||||||
|
{_playlist_hide_from_search}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -68,6 +72,7 @@
|
||||||
<form method="post" id="newPlaylistForm" enctype="multipart/form-data">
|
<form method="post" id="newPlaylistForm" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="title" maxlength="125" />
|
<input type="hidden" name="title" maxlength="125" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<input type="hidden" name="is_unlisted" value="0" />
|
||||||
<textarea style="display:none;" name="description" maxlength="2045" />
|
<textarea style="display:none;" name="description" maxlength="2045" />
|
||||||
<input type="hidden" name="audios">
|
<input type="hidden" name="audios">
|
||||||
<input type="file" style="display:none;" name="cover" accept=".jpg,.png">
|
<input type="file" style="display:none;" name="cover" accept=".jpg,.png">
|
||||||
|
@ -83,6 +88,7 @@
|
||||||
u("#newPlaylistForm").on("submit", (e) => {
|
u("#newPlaylistForm").on("submit", (e) => {
|
||||||
document.querySelector("#newPlaylistForm input[name='title']").value = document.querySelector(".plinfo input[name='title']").value
|
document.querySelector("#newPlaylistForm input[name='title']").value = document.querySelector(".plinfo input[name='title']").value
|
||||||
document.querySelector("#newPlaylistForm textarea[name='description']").value = document.querySelector(".plinfo textarea[name='description']").value
|
document.querySelector("#newPlaylistForm textarea[name='description']").value = document.querySelector(".plinfo textarea[name='description']").value
|
||||||
|
document.querySelector("#newPlaylistForm input[name='is_unlisted']").value = document.querySelector(".plinfo input[name='is_unlisted']").checked ? 1 : 0
|
||||||
})
|
})
|
||||||
|
|
||||||
u("#newPlaylistForm input[name='cover']").on("change", (e) => {
|
u("#newPlaylistForm input[name='cover']").on("change", (e) => {
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
{extends "../@layout.xml"}
|
{extends "../@layout.xml"}
|
||||||
|
|
||||||
{block title}{_playlist}{/block}
|
{block title}
|
||||||
|
{_playlist}
|
||||||
|
{$playlist->getName()}
|
||||||
|
{/block}
|
||||||
|
|
||||||
{block headIncludes}
|
{block headIncludes}
|
||||||
<meta property="og:type" content="music.album">
|
<meta property="og:type" content="music.album">
|
||||||
<meta property="og:title" content="{$playlist->getName()}">
|
<meta property="og:title" content="{$playlist->getName()}">
|
||||||
<meta property="og:url" content="{$playlist->getURL()}">
|
<meta property="og:url" content="{$playlist->getURL()}">
|
||||||
<meta property="og:description" content="{$playlist->getDescription()}">
|
<meta property="og:description" content="{$playlist->getDescription()}">
|
||||||
<meta property="og:image" content="{$playlist->getCoverURL()}">
|
<meta property="og:image" content="{$cover_url}">
|
||||||
|
|
||||||
<script type="application/ld+json">
|
<script type="application/ld+json">
|
||||||
{
|
{
|
||||||
|
@ -22,31 +25,36 @@
|
||||||
{block header}
|
{block header}
|
||||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||||
»
|
»
|
||||||
<a href="/audios{$ownerId}">{_audios}</a>
|
<a href="/playlists{$ownerId}">{_playlists}</a>
|
||||||
»
|
»
|
||||||
{_playlist}
|
{_playlist}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
{include "bigplayer.xml"}
|
{include "bigplayer.xml"}
|
||||||
|
|
||||||
{php $count = $playlist->size()}
|
|
||||||
|
|
||||||
<input type="hidden" name="bigplayer_context" data-type="playlist_context" data-entity="{$playlist->getId()}" data-page="{$page}">
|
<input type="hidden" name="bigplayer_context" data-type="playlist_context" data-entity="{$playlist->getId()}" data-page="{$page}">
|
||||||
<div class="playlistBlock">
|
<div class="playlistBlock">
|
||||||
<div class="playlistCover" style="float: left;">
|
<div class="playlistCover" style="float: left;">
|
||||||
<a href="{$playlist->getCoverURL()}" target="_blank">
|
{if $cover}
|
||||||
<img src="{$playlist->getCoverURL('normal')}" alt="{_playlist_cover}">
|
<a href="{$cover_url}" target="_blank">
|
||||||
|
<img onclick="OpenMiniature(event, {$cover_url}, null, {$cover->getPrettyId()}, null)" src="{$cover_url}" alt="{_playlist_cover}">
|
||||||
</a>
|
</a>
|
||||||
|
{else}
|
||||||
|
<a>
|
||||||
|
<img src="{$cover_url}" alt="{_playlist_cover}">
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="profile_links" style="width: 139px;" n:if="isset($thisUser)">
|
<div class="profile_links" n:if="isset($thisUser)">
|
||||||
<a class="profile_link" style="width: 98%;" href="/playlist{$playlist->getPrettyId()}/edit" n:if="$playlist->canBeModifiedBy($thisUser)">{_edit_playlist}</a>
|
<a class="profile_link" href="/player/upload?playlist={$playlist->getId()}" n:if="$canEdit">{_upload_audio}</a>
|
||||||
<a class="profile_link" style="width: 98%;" id="bookmarkPlaylist" data-id="{$playlist->getId()}" n:if="!$isBookmarked">{_bookmark}</a>
|
<a class="profile_link" href="/playlist{$playlist->getPrettyId()}/edit" n:if="$canEdit">{_edit_playlist}</a>
|
||||||
<a class="profile_link" style="width: 98%;" id="unbookmarkPlaylist" data-id="{$playlist->getId()}" n:if="$isBookmarked">{_unbookmark}</a>
|
<a class="profile_link" id="bookmarkPlaylist" data-id="{$playlist->getId()}" n:if="!$isBookmarked">{_bookmark}</a>
|
||||||
|
<a class="profile_link" id="unbookmarkPlaylist" data-id="{$playlist->getId()}" n:if="$isBookmarked">{_unbookmark}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="float: left;padding-left: 13px;width:75%">
|
<div class='playlistWrapper'>
|
||||||
<div class="playlistInfo">
|
<div class="playlistInfo">
|
||||||
<h4 style="border-bottom:unset;">{$playlist->getName()}</h4>
|
<h4 style="border-bottom:unset;">{$playlist->getName()}</h4>
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,22 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
{if !is_null($group)}
|
{if !$playlist}
|
||||||
<a href="{$group->getURL()}">{$group->getCanonicalName()}</a>
|
{if !is_null($group)}
|
||||||
»
|
<a href="{$group->getURL()}">{$group->getCanonicalName()}</a>
|
||||||
<a href="/audios-{$group->getId()}">{_audios}</a>
|
»
|
||||||
|
<a href="/audios-{$group->getId()}">{_audios}</a>
|
||||||
|
{else}
|
||||||
|
<a href="{$thisUser->getURL()}">{$thisUser->getCanonicalName()}</a>
|
||||||
|
»
|
||||||
|
<a href="/audios{$thisUser->getId()}">{_audios}</a>
|
||||||
|
{/if}
|
||||||
{else}
|
{else}
|
||||||
<a href="{$thisUser->getURL()}">{$thisUser->getCanonicalName()}</a>
|
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||||
»
|
»
|
||||||
<a href="/audios{$thisUser->getId()}">{_audios}</a>
|
<a href="/playlists{$ownerId}">{_playlists}</a>
|
||||||
|
»
|
||||||
|
<a href="/playlist{$playlist->getPrettyId()}">{_playlist}</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
»
|
»
|
||||||
|
@ -36,6 +44,7 @@
|
||||||
<input type="hidden" name="lyrics" />
|
<input type="hidden" name="lyrics" />
|
||||||
<input type="hidden" name="genre" />
|
<input type="hidden" name="genre" />
|
||||||
<input type="hidden" name="explicit" />
|
<input type="hidden" name="explicit" />
|
||||||
|
<input type="hidden" name="unlisted" />
|
||||||
|
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
<input id="audio_input" type="file" name="blob" accept="audio/*" style="display:none" />
|
<input id="audio_input" type="file" name="blob" accept="audio/*" style="display:none" />
|
||||||
|
@ -43,20 +52,20 @@
|
||||||
</form>
|
</form>
|
||||||
</div><br/>
|
</div><br/>
|
||||||
|
|
||||||
<span>{_you_can_also_add_audio_using} <b><a href="/search?type=audios">{_search_audio_inst}</a></b>.<span>
|
<span>{_you_can_also_add_audio_using} <b><a href="/search?section=audios">{_search_audio_inst}</a></b>.<span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="lastStep" style="display:none;">
|
<div id="lastStep" style="display:none;">
|
||||||
<table cellspacing="7" cellpadding="0" border="0" align="center">
|
<table cellspacing="7" cellpadding="0" border="0" align="center">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
|
||||||
<td width="120" valign="top"><span class="nobold">{_audio_name}:</span></td>
|
|
||||||
<td><input type="text" name="name" autocomplete="off" maxlength="80" /></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top"><span class="nobold">{_performer}:</span></td>
|
<td width="120" valign="top"><span class="nobold">{_performer}:</span></td>
|
||||||
<td><input name="performer" type="text" autocomplete="off" maxlength="80" /></td>
|
<td><input name="performer" type="text" autocomplete="off" maxlength="80" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top"><span class="nobold">{_audio_name}:</span></td>
|
||||||
|
<td><input type="text" name="name" autocomplete="off" maxlength="80" /></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top"><span class="nobold">{_genre}:</span></td>
|
<td width="120" valign="top"><span class="nobold">{_genre}:</span></td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -74,7 +83,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top"></td>
|
<td width="120" valign="top"></td>
|
||||||
<td>
|
<td>
|
||||||
<label><input type="checkbox" name="explicit">{_audios_explicit}</label>
|
<label style='display:block'><input type="checkbox" name="explicit">{_audios_explicit}</label>
|
||||||
|
<label><input type="checkbox" name="unlisted">{_audios_unlisted}</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -100,8 +110,24 @@
|
||||||
|
|
||||||
document.querySelector("#firstStep").style.display = "none"
|
document.querySelector("#firstStep").style.display = "none"
|
||||||
document.querySelector("#lastStep").style.display = "block"
|
document.querySelector("#lastStep").style.display = "block"
|
||||||
|
|
||||||
|
function fallback() {
|
||||||
|
console.info('Tags not found, setting default values.')
|
||||||
|
|
||||||
|
document.querySelector("#lastStep input[name=name]").value = files[0].name
|
||||||
|
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||||
|
document.querySelector("#lastStep input[name=performer]").value = tr("track_unknown");
|
||||||
|
}
|
||||||
|
|
||||||
let tags = await id3.fromFile(files[0]);
|
let tags = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
tags = await id3.fromFile(files[0]);
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(tags)
|
||||||
if(tags != null) {
|
if(tags != null) {
|
||||||
console.log("ID" + tags.kind + " detected, setting values...");
|
console.log("ID" + tags.kind + " detected, setting values...");
|
||||||
|
|
||||||
|
@ -116,17 +142,31 @@
|
||||||
document.querySelector("#lastStep input[name=performer]").value = tr("track_unknown");
|
document.querySelector("#lastStep input[name=performer]").value = tr("track_unknown");
|
||||||
|
|
||||||
if(tags.genre != null) {
|
if(tags.genre != null) {
|
||||||
if(document.querySelector("#lastStep select[name=genre] > option[value='" + tags.genre + "']") != null) {
|
// if there are more than one genre
|
||||||
document.querySelector("#lastStep select[name=genre]").value = tags.genre;
|
if(tags.genre.split(', ').length > 1) {
|
||||||
|
const genres = tags.genre.split(', ')
|
||||||
|
|
||||||
|
genres.forEach(genre => {
|
||||||
|
if(document.querySelector("#lastStep select[name=genre] > option[value='" + genre + "']") != null) {
|
||||||
|
document.querySelector("#lastStep select[name=genre]").value = genre;
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
console.warn("Unknown genre: " + tags.genre);
|
if(document.querySelector("#lastStep select[name=genre] > option[value='" + tags.genre + "']") != null) {
|
||||||
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
document.querySelector("#lastStep select[name=genre]").value = tags.genre;
|
||||||
|
} else {
|
||||||
|
console.warn("Unknown genre: " + tags.genre);
|
||||||
|
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(tags.comments != null)
|
||||||
|
document.querySelector("#lastStep textarea[name=lyrics]").value = tags.comments
|
||||||
} else {
|
} else {
|
||||||
document.querySelector("#lastStep input[name=name]").value = files[0].name
|
fallback()
|
||||||
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
|
||||||
document.querySelector("#lastStep input[name=performer]").value = tr("track_unknown");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -147,12 +187,14 @@
|
||||||
var genre_ = document.querySelector("#audio_upload input[name=genre]");
|
var genre_ = document.querySelector("#audio_upload input[name=genre]");
|
||||||
var lyrics_ = document.querySelector("#audio_upload input[name=lyrics]");
|
var lyrics_ = document.querySelector("#audio_upload input[name=lyrics]");
|
||||||
var explicit_ = document.querySelector("#audio_upload input[name=explicit]");
|
var explicit_ = document.querySelector("#audio_upload input[name=explicit]");
|
||||||
|
var unlisted_ = document.querySelector("#audio_upload input[name=unlisted]");
|
||||||
|
|
||||||
name_.value = document.querySelector("#lastStep input[name=name]").value
|
name_.value = document.querySelector("#lastStep input[name=name]").value
|
||||||
perf_.value = document.querySelector("#lastStep input[name=performer]").value
|
perf_.value = document.querySelector("#lastStep input[name=performer]").value
|
||||||
genre_.value = document.querySelector("#lastStep select[name=genre]").value
|
genre_.value = document.querySelector("#lastStep select[name=genre]").value
|
||||||
lyrics_.value = document.querySelector("#lastStep textarea[name=lyrics]").value
|
lyrics_.value = document.querySelector("#lastStep textarea[name=lyrics]").value
|
||||||
explicit_.value = document.querySelector("#lastStep input[name=explicit]").checked ? "on" : "off"
|
explicit_.value = document.querySelector("#lastStep input[name=explicit]").checked ? "on" : "off"
|
||||||
|
unlisted_.value = document.querySelector("#lastStep input[name=unlisted]").checked ? "on" : "off"
|
||||||
|
|
||||||
$("#audio_upload > form").trigger("submit");
|
$("#audio_upload > form").trigger("submit");
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="bigPlayer">
|
<div n:class="bigPlayer, $tidy ? tidy">
|
||||||
<audio class="audio" />
|
<audio class="audio" />
|
||||||
<div class="paddingLayer">
|
<div class="paddingLayer">
|
||||||
<div class="playButtons">
|
<div class="playButtons">
|
||||||
|
@ -18,21 +18,21 @@
|
||||||
<div class="trackPanel">
|
<div class="trackPanel">
|
||||||
<div class="trackInfo">
|
<div class="trackInfo">
|
||||||
<div class="trackName">
|
<div class="trackName">
|
||||||
<b>{_track_unknown}</b> —
|
<a>{_track_unknown}</a> —
|
||||||
<span>{_track_noname}</span>
|
<span>{_track_noname}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="timer" style="float:right">
|
<div class="timer" style="float:right">
|
||||||
<span class="time">00:00</span>
|
<span class="time">00:00</span>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span class="elapsedTime" style="cursor:pointer">-00:00</span>
|
<span class="elapsedTime">-00:00</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="track" style="margin-top: -2px;">
|
<div class="track" style="margin-top: -2px;">
|
||||||
<div class="bigPlayerTip">00:00</div>
|
<div class="bigPlayerTip">00:00</div>
|
||||||
<div class="selectableTrack">
|
<div class="selectableTrack">
|
||||||
<div style="width: 95%;position: relative;">
|
<div id='bigPlayerLengthSliderWrapper'>
|
||||||
<div class="slider"></div>
|
<div class="slider"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
<div class="volumePanel">
|
<div class="volumePanel">
|
||||||
<div class="selectableTrack">
|
<div class="selectableTrack">
|
||||||
<div style="position: relative;width:72%">
|
<div id='bigPlayerVolumeSliderWrapper'>
|
||||||
<div class="slider"></div>
|
<div class="slider"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{php $id = $audio->getId() . rand(0, 1000)}
|
{php $id = $audio->getId() . rand(0, 1000)}
|
||||||
{php $isWithdrawn = $audio->isWithdrawn()}
|
{php $isWithdrawn = $audio->isWithdrawn()}
|
||||||
|
{php $isAvailable = $audio->isAvailable()}
|
||||||
{php $editable = isset($thisUser) && $audio->canBeModifiedBy($thisUser)}
|
{php $editable = isset($thisUser) && $audio->canBeModifiedBy($thisUser)}
|
||||||
<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" {if $hideButtons}data-prettyid="{$audio->getPrettyId()}" data-name="{$audio->getName()}"{/if} data-genre="{$audio->getGenre()}" class="audioEmbed {if !$audio->isAvailable()}processed{/if} {if $isWithdrawn}withdrawn{/if}" data-length="{$audio->getLength()}" data-keys="{json_encode($audio->getKeys())}" data-url="{$audio->getURL()}">
|
<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" {if $hideButtons}data-prettyid="{$audio->getPrettyId()}" data-name="{$audio->getName()}"{/if} data-genre="{$audio->getGenre()}" class="audioEmbed {if !$isAvailable}processed{/if} {if $isWithdrawn}withdrawn{/if}" data-length="{$audio->getLength()}" data-keys="{json_encode($audio->getKeys())}" data-url="{$audio->getURL()}">
|
||||||
<audio class="audio" />
|
<audio class="audio" />
|
||||||
|
|
||||||
<div id="miniplayer" class="audioEntry" style="min-height: 39px;">
|
<div id="miniplayer" class="audioEntry" style="min-height: 39px;">
|
||||||
|
@ -11,29 +12,32 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="status" style="margin-top: 12px;">
|
<div class="status" style="margin-top: 12px;">
|
||||||
<div class="mediaInfo noOverflow" style="margin-bottom: -8px; cursor: pointer;display:flex;width: 85%;">
|
<div class="mediaInfo noOverflow">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<strong class="performer">
|
<strong class="performer">
|
||||||
<a href="/search?query=&type=audios&sort=id&only_performers=on&query={$audio->getPerformer()}">{$audio->getPerformer()}</a>
|
<a href="/search?query=§ion=audios&order=listens&only_performers=on&q={$audio->getPerformer()}">{$audio->getPerformer()}</a>
|
||||||
</strong>
|
</strong>
|
||||||
—
|
—
|
||||||
<span class="title {if !empty($audio->getLyrics())}withLyrics{/if}">{$audio->getTitle()}</span>
|
<span class="title {if !empty($audio->getLyrics())}withLyrics{/if}">{$audio->getTitle()}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="explicitMark" n:if="$audio->isExplicit()"></div>
|
<svg n:if="$audio->isExplicit()" class="explicitMark" xmlns="http://www.w3.org/2000/svg" height="11" viewBox="0 0 11 11" width="11">
|
||||||
|
<path d="m1 2.506v5.988a1.5 1.5 0 0 0 1.491 1.506h6.019c.827 0 1.49-.674 1.49-1.506v-5.988a1.5 1.5 0 0 0 -1.491-1.506h-6.019c-.827 0-1.49.674-1.49 1.506zm4 2.494v-1h2v-1h-3v5h3v-1h-2v-1h2v-1zm-5-2.494a2.496 2.496 0 0 1 2.491-2.506h6.019a2.5 2.5 0 0 1 2.49 2.506v5.988a2.496 2.496 0 0 1 -2.491 2.506h-6.019a2.5 2.5 0 0 1 -2.49-2.506z" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="volume" style="display: flex; flex-direction: column;width:14%;">
|
<div class="volume" style="display: flex; flex-direction: column;width:14%;">
|
||||||
<span class="nobold {if !$hideButtons}hideOnHover{/if}" data-unformatted="{$audio->getLength()}" style="text-align: center;margin-top: 12px;">{$audio->getFormattedLength()}</span>
|
<span class="nobold {if !$hideButtons}hideOnHover{/if}" data-unformatted="{$audio->getLength()}" style="text-align: center;margin-top: 12px;">{$audio->getFormattedLength()}</span>
|
||||||
<div class="buttons" style="margin-top: 8px;">
|
<div class="buttons">
|
||||||
{php $hasAudio = isset($thisUser) && $audio->isInLibraryOf($thisUser)}
|
{php $hasAudio = isset($thisUser) && $audio->isInLibraryOf($thisUser)}
|
||||||
|
|
||||||
{if !$hideButtons}
|
{if !$hideButtons}
|
||||||
<div class="remove-icon musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && $hasAudio" ></div>
|
<div class="remove-icon musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && $hasAudio" ></div>
|
||||||
<div class="add-icon musicIcon hovermeicon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$hasAudio && !$isWithdrawn" ></div>
|
<div class="add-icon musicIcon hovermeicon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$hasAudio && !$isWithdrawn" ></div>
|
||||||
<div class="remove-icon-group musicIcon" data-id="{$audio->getId()}" data-club="{$club->getId()}" n:if="isset($thisUser) && isset($club) && $club->canBeModifiedBy($thisUser)" ></div>
|
<div class="remove-icon-group musicIcon" data-id="{$audio->getId()}" data-club="{$club->getId()}" n:if="isset($thisUser) && isset($club) && $club->canBeModifiedBy($thisUser)" ></div>
|
||||||
<div class="add-icon-group musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$isWithdrawn" ></div>
|
<div class="add-icon-group musicIcon hidden" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$isWithdrawn" ></div>
|
||||||
|
<a class="download-icon musicIcon" n:if='isset($thisUser) && !$isWithdrawn && $isAvailable && OPENVK_ROOT_CONF["openvk"]["preferences"]["music"]["exposeOriginalURLs"]' href="{$audio->getOriginalURL()}" download="{$audio->getDownloadName()}"></a>
|
||||||
<div class="edit-icon musicIcon" data-lyrics="{$audio->getLyrics()}" data-title="{$audio->getTitle()}" data-performer="{$audio->getPerformer()}" data-explicit="{(int)$audio->isExplicit()}" data-searchable="{(int)!$audio->isUnlisted()}" n:if="isset($thisUser) && $editable && !$isWithdrawn" ></div>
|
<div class="edit-icon musicIcon" data-lyrics="{$audio->getLyrics()}" data-title="{$audio->getTitle()}" data-performer="{$audio->getPerformer()}" data-explicit="{(int)$audio->isExplicit()}" data-searchable="{(int)!$audio->isUnlisted()}" n:if="isset($thisUser) && $editable && !$isWithdrawn" ></div>
|
||||||
<div class="report-icon musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$editable && !$isWithdrawn" ></div>
|
<div class="report-icon musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$editable && !$isWithdrawn" ></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -41,20 +45,20 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="subTracks">
|
<div class="subTracks">
|
||||||
<div style="width: 100%;">
|
<div class="lengthTrackWrapper">
|
||||||
<div class="track lengthTrack" style="margin-top: 3px;display:none">
|
<div class="track lengthTrack">
|
||||||
<div class="selectableTrack" style="width: 100%;" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
<div class="selectableTrack" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||||
<div style="position: relative;width: calc(100% - 18px);">
|
<div class="selectableTrackSlider">
|
||||||
<div class="slider"></div>
|
<div class="slider"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="width: 81px;margin-left: 16px;">
|
<div class="volumeTrackWrapper">
|
||||||
<div class="track volumeTrack" style="margin-top: 3px;display:none">
|
<div class="track volumeTrack">
|
||||||
<div class="selectableTrack" style="width: 100%;" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
<div class="selectableTrack" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||||
<div style="position: relative;width: calc(100% - 18px);">
|
<div class="selectableTrackSlider">
|
||||||
<div class="slider"></div>
|
<div class="slider"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
20
Web/Presenters/templates/Audio/playlistListView.xml
Normal file
20
Web/Presenters/templates/Audio/playlistListView.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<a href="/playlist{$playlist->getPrettyId()}" class='playlistListView'>
|
||||||
|
<div class="playlistCover">
|
||||||
|
<img src="{$playlist->getCoverURL('normal')}" alt="{_playlist_cover}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="playlistInfo">
|
||||||
|
<div class="playlistInfoTopPart">
|
||||||
|
<span class="playlistName noOverflow">
|
||||||
|
{$playlist->getName()}
|
||||||
|
</span>
|
||||||
|
<span n:if='!empty($playlist->getDescription())' class="playlistDesc noOverflow">
|
||||||
|
{$playlist->getDescription()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="playlistMeta">
|
||||||
|
{$playlist->getMetaDescription()|noescape}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
|
@ -1,35 +1,35 @@
|
||||||
<div class="searchOptions newer">
|
<div class='verticalGrayTabsWrapper'>
|
||||||
<div class="searchList" style="margin-top:10px">
|
<div class="verticalGrayTabs">
|
||||||
<a n:attr="id => $mode === 'list' && $isMy ? 'used' : 'ki'" href="/audios{$thisUser->getId()}" n:if="isset($thisUser)">{_my_music}</a>
|
<div class='with_padding'>
|
||||||
<a href="/player/upload{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser)">{_upload_audio}</a>
|
<a n:if="isset($thisUser)" n:attr="id => $mode === 'list' && $isMy ? 'used' : 'ki'" href="/audios{$thisUser->getId()}">{_my_music}</a>
|
||||||
<a n:attr="id => $mode === 'new' ? 'used' : 'ki'" href="/audios/new">{_audio_new}</a>
|
<a n:if="isset($thisUser)" href="/player/upload{if $isMyClub}?gid={abs($ownerId)}{/if}">{_upload_audio}</a>
|
||||||
<a n:attr="id => $mode === 'popular' ? 'used' : 'ki'" href="/audios/popular">{_audio_popular}</a>
|
<a n:if="isset($thisUser)" n:attr="id => $mode === 'new' ? 'used' : 'ki'" href="/search?section=audios">{_audio_new}</a>
|
||||||
<a href="/search?type=audios" n:if="isset($thisUser)">{_audio_search}</a>
|
<a n:if="isset($thisUser)" n:attr="id => $mode === 'popular' ? 'used' : 'ki'" href="/search?section=audios&order=listens">{_audio_popular}</a>
|
||||||
|
|
||||||
<hr n:if="isset($thisUser)">
|
<hr n:if="isset($thisUser)">
|
||||||
|
|
||||||
<a n:attr="id => $mode === 'playlists' && $ownerId == $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$thisUser->getId()}" n:if="isset($thisUser)">{_my_playlists}</a>
|
<a n:attr="id => $mode === 'playlists' && $ownerId == $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$thisUser->getId()}" n:if="isset($thisUser)">{_my_playlists}</a>
|
||||||
|
|
||||||
<a n:if="isset($thisUser)" href="/audios/newPlaylist">{_new_playlist}</a>
|
<a n:if="isset($thisUser)" href="/audios/newPlaylist">{_new_playlist}</a>
|
||||||
|
|
||||||
{if !$isMy && $mode !== 'popular' && $mode !== 'new'}
|
{if !$isMy && $mode !== 'popular' && $mode !== 'new'}
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<a n:if="!$isMy" n:attr="id => $mode === 'list' ? 'used' : 'ki'" href="/audios{$ownerId}">{if $ownerId > 0}{_music_user}{else}{_music_club}{/if}</a>
|
<a n:if="!$isMy" n:attr="id => $mode === 'list' ? 'used' : 'ki'" href="/audios{$ownerId}">{if $ownerId > 0}{_music_user}{else}{_music_club}{/if}</a>
|
||||||
<a href="/player/upload?gid={abs($ownerId)}" n:if="isset($thisUser) && isset($club) && $club->canUploadAudio($thisUser)">{_upload_audio}</a>
|
<a href="/player/upload?gid={abs($ownerId)}" n:if="isset($thisUser) && isset($club) && $club->canUploadAudio($thisUser)">{_upload_audio}</a>
|
||||||
<a n:attr="id => $mode === 'playlists' && $ownerId != $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$ownerId}" n:if="isset($thisUser) && isset($ownerId) && !$isMy">{if $ownerId > 0}{_playlists_user}{else}{_playlists_club}{/if}</a>
|
<a n:attr="id => $mode === 'playlists' && $ownerId != $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$ownerId}" n:if="isset($thisUser) && isset($ownerId) && !$isMy">{if $ownerId > 0}{_playlists_user}{else}{_playlists_club}{/if}</a>
|
||||||
<a href="/audios/newPlaylist{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser) && $isMyClub">{_new_playlist}</a>
|
<a href="/audios/newPlaylist{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser) && $isMyClub">{_new_playlist}</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
{if $friendsAudios}
|
{if $friendsAudios}
|
||||||
<div class="friendsAudiosList">
|
<div class="friendsAudiosList">
|
||||||
<a href="/audios{$fr->getRealId()}" style="width: 94%;padding-left: 10px;" n:foreach="$friendsAudios as $fr">
|
<a href="/audios{$fr->getRealId()}" n:foreach="$friendsAudios as $fr">
|
||||||
<div class="elem">
|
<div class="elem">
|
||||||
<img src="{$fr->getAvatarURL()}" />
|
<img src="{$fr->getAvatarURL()}" />
|
||||||
|
|
||||||
<div class="additionalInfo">
|
<div class="additionalInfo">
|
||||||
{php $audioStatus = $fr->getCurrentAudioStatus()}
|
<span class="name noOverflow">{$fr->getCanonicalName()}</span>
|
||||||
<span class="name">{$fr->getCanonicalName()}</span>
|
|
||||||
<span class="desc">{$audioStatus ? $audioStatus->getName() : tr("audios_count", $fr->getAudiosCollectionSize())}</span>
|
<span class="desc">{$audioStatus ? $audioStatus->getName() : tr("audios_count", $fr->getAudiosCollectionSize())}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getThumbnailURL()}" width="75" alt="{$x->getName(tr('__lang'))}" />
|
<img src="{$x->getThumbnailURL()}" width="75" alt="{$x->getName(tr('__lang'))}" loading=lazy />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
@ -26,4 +26,4 @@
|
||||||
|
|
||||||
{block description}
|
{block description}
|
||||||
{$x->getDescription(tr("__lang"))}
|
{$x->getDescription(tr("__lang"))}
|
||||||
{/block}
|
{/block}
|
|
@ -14,8 +14,8 @@
|
||||||
{block content}
|
{block content}
|
||||||
<div class="gift_grid">
|
<div class="gift_grid">
|
||||||
<div n:foreach="$gifts as $gift" n:class="gift_sel, !$gift->canUse($thisUser) ? disabled" data-gift="{$gift->getId()}">
|
<div n:foreach="$gifts as $gift" n:class="gift_sel, !$gift->canUse($thisUser) ? disabled" data-gift="{$gift->getId()}">
|
||||||
<img class="gift_pic" src="{$gift->getImage(2)}" alt="{_gift}" />
|
<img class="gift_pic" src="{$gift->getImage(2)}" alt="{_gift}" loading=lazy />
|
||||||
|
|
||||||
<strong class="gift_price">
|
<strong class="gift_price">
|
||||||
{if $gift->isFree()}
|
{if $gift->isFree()}
|
||||||
{_free_gift}
|
{_free_gift}
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
{tr('coins', $gift->getPrice())}
|
{tr('coins', $gift->getPrice())}
|
||||||
{/if}
|
{/if}
|
||||||
</strong>
|
</strong>
|
||||||
|
|
||||||
<strong class="gift_limit">
|
<strong class="gift_limit">
|
||||||
{if $gift->getUsagesLeft($thisUser) !== INF}
|
{if $gift->getUsagesLeft($thisUser) !== INF}
|
||||||
{tr("gifts_left", $gift->getUsagesLeft($thisUser))}
|
{tr("gifts_left", $gift->getUsagesLeft($thisUser))}
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
</strong>
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="padding: 8px;">
|
<div style="padding: 8px;">
|
||||||
{include "../components/paginator.xml", conf => (object) [
|
{include "../components/paginator.xml", conf => (object) [
|
||||||
"page" => $page,
|
"page" => $page,
|
||||||
|
@ -48,11 +48,11 @@
|
||||||
let el = $(this);
|
let el = $(this);
|
||||||
if(el.hasClass("disabled"))
|
if(el.hasClass("disabled"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
let link = "/gifts?act=confirm&user={$user->getId()}&pack={$cat->getId()}&elid=";
|
let link = "/gifts?act=confirm&user={$user->getId()}&pack={$cat->getId()}&elid=";
|
||||||
let gift = el.data("gift");
|
let gift = el.data("gift");
|
||||||
|
|
||||||
window.location.assign(link + gift);
|
window.location.assign(link + gift);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{/block}
|
{/block}
|
|
@ -16,7 +16,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->gift->getImage(2)}" width="75" alt="{_gift}" />
|
<img src="{$x->gift->getImage(2)}" width="75" alt="{_gift}" loading=lazy />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
@ -40,4 +40,4 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{/block}
|
{/block}
|
|
@ -83,7 +83,7 @@
|
||||||
<option value="0" n:attr="selected => $club->getWallType() == 0" /> {_group_closed_post}</option>
|
<option value="0" n:attr="selected => $club->getWallType() == 0" /> {_group_closed_post}</option>
|
||||||
<select>
|
<select>
|
||||||
|
|
||||||
<input type="checkbox" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled()" /> {_group_hide_from_global_feed}
|
<input type="checkbox" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled(), disabled => $club->isHidingFromGlobalFeedEnforced()" /> {_group_hide_from_global_feed}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -54,8 +54,8 @@
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top"><span class="nobold">{_gender}: </span></td>
|
<td width="120" valign="top"><span class="nobold">{_pronouns}: </span></td>
|
||||||
<td>{$user->isFemale() ? tr("female"): tr("male")}</td>
|
<td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top"><span class="nobold">{_registration_date}: </span></td>
|
<td width="120" valign="top"><span class="nobold">{_registration_date}: </span></td>
|
||||||
|
|
|
@ -127,25 +127,19 @@
|
||||||
<div class="right_small_block">
|
<div class="right_small_block">
|
||||||
{var $avatarPhoto = $club->getAvatarPhoto()}
|
{var $avatarPhoto = $club->getAvatarPhoto()}
|
||||||
{var $avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
|
{var $avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
|
||||||
<div class="avatar_block" style="position:relative;">
|
<div class="avatar_block" style="position:relative;" data-club="{$club->getId()}">
|
||||||
{var $hasAvatar = !str_contains($club->getAvatarUrl('miniscule'), "/assets/packages/static/openvk/img/camera_200.png")}
|
{if $thisUser && $club->canBeModifiedBy($thisUser)}
|
||||||
{if !is_null($thisUser) && $hasAvatar == false && $club->canBeModifiedBy($thisUser)}
|
<a {if $avatarPhoto}style="display:none"{/if} class="add_image_text" id="add_image">{_add_image}</a>
|
||||||
<a href="javascript:addAvatarImage(true, {$club->getId()})" class="text_add_image">{_add_image_group}</a>
|
<div {if !$avatarPhoto}style="display:none"{/if} class="avatar_controls">
|
||||||
{elseif !is_null($thisUser) && $hasAvatar == true && $club->canBeModifiedBy($thisUser)}
|
<div class="avatarDelete hoverable"></div>
|
||||||
<div class="avatar_controls">
|
|
||||||
<div class="avatarDelete">
|
|
||||||
<a id="upl" href="javascript:deleteAvatar('{$club->getAvatarPhoto()->getPrettyId()}')"><img src="/assets/packages/static/openvk/img/delete.png"/></a>
|
|
||||||
</div>
|
|
||||||
<div class="avatar_variants">
|
<div class="avatar_variants">
|
||||||
<div class="variant">
|
<a class="_add_image hoverable" id="add_image"><span>{_upload_new_picture}</span></a>
|
||||||
<img src="/assets/packages/static/openvk/img/upload.png" style="margin-left:15px;height: 10px;">
|
|
||||||
<a href="javascript:addAvatarImage(true, {$club->getId()})"><p>{_upload_new_picture}</p></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<a href="{$avatarLink|nocheck}">
|
<a href="{$avatarLink|nocheck}">
|
||||||
<img src="{$club->getAvatarUrl('normal')}" id="thisGroupAvatar" style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
<img src="{$club->getAvatarUrl('normal')}" id="bigAvatar" style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div n:ifset="$thisUser" id="profile_links">
|
<div n:ifset="$thisUser" id="profile_links">
|
||||||
|
@ -292,7 +286,7 @@
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURL()}"
|
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURL()}"
|
||||||
style="max-width: 80px; max-height: 54pt;" />
|
style="max-width: 80px; max-height: 54pt;" loading=lazy />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<b><a href="/album{$album->getPrettyId()}">{$album->getName()}</a></b><br>
|
<b><a href="/album{$album->getPrettyId()}">{$album->getName()}</a></b><br>
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
<a id="act_tab_a" href="javascript:false">{_all_messages}</a>
|
<a id="act_tab_a" href="javascript:false">{_all_messages}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container_gray">
|
<div class="container_gray">
|
||||||
<form action="/im/search" method="POST" style="margin: 0;">
|
<form action="/im/search" method="POST" style="margin: 0;">
|
||||||
<input type="text" name="pattern" placeholder="{_search_messages}" required />
|
<input type="text" name="pattern" placeholder="{_search_messages}" required />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{if sizeof($corresps) > 0}
|
{if sizeof($corresps) > 0}
|
||||||
<div class="crp-list">
|
<div class="crp-list">
|
||||||
<div n:foreach="$corresps as $coresp"
|
<div n:foreach="$corresps as $coresp"
|
||||||
|
@ -23,10 +23,10 @@
|
||||||
onmousedown="window.location.href = {$coresp->getURL()};" >
|
onmousedown="window.location.href = {$coresp->getURL()};" >
|
||||||
{var $recipient = $coresp->getCorrespondents()[1]}
|
{var $recipient = $coresp->getCorrespondents()[1]}
|
||||||
{var $lastMsg = $coresp->getPreviewMessage()}
|
{var $lastMsg = $coresp->getPreviewMessage()}
|
||||||
|
|
||||||
<div class="crp-entry--image">
|
<div class="crp-entry--image">
|
||||||
<img src="{$recipient->getAvatarURL('miniscule')}"
|
<img src="{$recipient->getAvatarURL('miniscule')}"
|
||||||
alt="Фотография пользователя" />
|
alt="Фотография пользователя" loading=lazy />
|
||||||
</div>
|
</div>
|
||||||
<div class="crp-entry--info">
|
<div class="crp-entry--info">
|
||||||
<a href="{$recipient->getURL()}">{$recipient->getCanonicalName()}</a><br/>
|
<a href="{$recipient->getURL()}">{$recipient->getCanonicalName()}</a><br/>
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div n:class="crp-entry--message, $lastMsg->getUnreadState() ? unread">
|
<div n:class="crp-entry--message, $lastMsg->getUnreadState() ? unread">
|
||||||
{var $_author = $lastMsg->getSender()}
|
{var $_author = $lastMsg->getSender()}
|
||||||
|
|
||||||
<div class="crp-entry--message---av" n:if="$_author->getId() === $thisUser->getId()">
|
<div class="crp-entry--message---av" n:if="$_author->getId() === $thisUser->getId()">
|
||||||
<img src="{$_author->getAvatarURL('miniscule')}"
|
<img src="{$_author->getAvatarURL('miniscule')}"
|
||||||
alt="Фотография пользователя" />
|
alt="Фотография пользователя" />
|
||||||
|
@ -53,4 +53,4 @@
|
||||||
<br/>
|
<br/>
|
||||||
<center>{_no_messages}</center>
|
<center>{_no_messages}</center>
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
|
@ -41,7 +41,7 @@
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="/photo{$photo->getPrettyId()}?from=album{$album->getId()}">
|
<a href="/photo{$photo->getPrettyId()}?from=album{$album->getId()}">
|
||||||
<img class="album-photo--image" src="{$photo->getURLBySizeId('tinier')}" alt="{$photo->getDescription()}" />
|
<img class="album-photo--image" src="{$photo->getURLBySizeId('tinier')}" alt="{$photo->getDescription()}" loading=lazy />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
|
@ -50,4 +50,4 @@
|
||||||
{else}
|
{else}
|
||||||
{include "../components/nothing.xml"}
|
{include "../components/nothing.xml"}
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
|
@ -23,7 +23,7 @@
|
||||||
{else}
|
{else}
|
||||||
{tr("albums", $count)}
|
{tr("albums", $count)}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<span n:if="$canEdit" style="float: right;">
|
<span n:if="$canEdit" style="float: right;">
|
||||||
|
|
|
|
||||||
{var $isClub = ($owner instanceof \openvk\Web\Models\Entities\Club)}
|
{var $isClub = ($owner instanceof \openvk\Web\Models\Entities\Club)}
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block actions}
|
{block actions}
|
||||||
|
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||||
|
@ -46,9 +46,9 @@
|
||||||
{block preview}
|
{block preview}
|
||||||
{var $cover = $x->getCoverPhoto()}
|
{var $cover = $x->getCoverPhoto()}
|
||||||
{var $preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURLBySizeId("normal")}
|
{var $preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURLBySizeId("normal")}
|
||||||
|
|
||||||
<a href="/album{$x->getPrettyId()}">
|
<a href="/album{$x->getPrettyId()}">
|
||||||
<img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" />
|
<img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" loading=lazy />
|
||||||
</a>
|
</a>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
|
@ -61,4 +61,4 @@
|
||||||
<span style="color: grey;">{$x->getPhotosCount()} {_photos}</span><br />
|
<span style="color: grey;">{$x->getPhotosCount()} {_photos}</span><br />
|
||||||
<span style="color: grey;">{tr("updated_at", $x->getEditTime() ?? $x->getCreationTime())}</span><br />
|
<span style="color: grey;">{tr("updated_at", $x->getEditTime() ?? $x->getCreationTime())}</span><br />
|
||||||
<span style="color: grey;">{_created} {$x->getCreationTime()}</span><br />
|
<span style="color: grey;">{_created} {$x->getCreationTime()}</span><br />
|
||||||
{/block}
|
{/block}
|
|
@ -22,7 +22,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография пользователя" />
|
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография пользователя" loading=lazy />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
@ -37,4 +37,4 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block actions}
|
{block actions}
|
||||||
{/block}
|
{/block}
|
|
@ -23,7 +23,7 @@
|
||||||
<form n:if="$report->getContentType() != 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
<form n:if="$report->getContentType() != 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}"/>
|
<input type="hidden" name="hash" value="{$csrfToken}"/>
|
||||||
<input type="submit" name="ban" value="{_ban_user_action}" class="button">
|
<input type="submit" name="ban" value="{_ban_user_action}" class="button">
|
||||||
<input n:if="$report->getContentType() !== 'user'" type="submit" name="delete" value="{_delete}" class="button">
|
<input n:if="$report->getContentType() !== 'user'" type="submit" name="delete" value="{_delete_content}" class="button">
|
||||||
<input type="submit" name="ignore" value="{_ignore_report}" class="button">
|
<input type="submit" name="ignore" value="{_ignore_report}" class="button">
|
||||||
</form>
|
</form>
|
||||||
<form n:if="$report->getContentType() == 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
<form n:if="$report->getContentType() == 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
||||||
|
|
|
@ -1,378 +1,405 @@
|
||||||
{extends "../@layout.xml"}
|
{extends "../@layout.xml"}
|
||||||
|
|
||||||
{block title}
|
{block title}
|
||||||
{tr("search_for_$type")}
|
{tr("search_for_$section")}
|
||||||
{if $_GET['query']}
|
{if $_REQUEST['q']}
|
||||||
- {$_GET['query']}
|
- {$_REQUEST['q']}
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
{=OPENVK_ROOT_CONF["openvk"]["appearance"]["name"]} »
|
{tr("search_for_$section")}
|
||||||
{tr("search_for_$type")}
|
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
{block wrap}
|
||||||
|
<div class="wrap2">
|
||||||
|
<div class="wrap1">
|
||||||
|
<div class="page_wrap">
|
||||||
|
{if $section == 'audios' && $count > 1}
|
||||||
|
{include "../Audio/bigplayer.xml", tidy => true}
|
||||||
|
|
||||||
{block link|strip|stripHtml}
|
<input type="hidden" name="bigplayer_context" data-type="classic_search_context" data-entity='{"order":"{$order}","query":"{$query}","invert":{$invert ? 1 : 0},"only_performers":{$_REQUEST['only_performers'] ? 1 : 0},"genre":"{$_REQUEST['genre']}","with_lyrics":"{$_REQUEST['with_lyrics'] ? 1 : 0}"}' data-page="{$page}">
|
||||||
{if $type != "apps"}
|
|
||||||
{$x->getURL()}
|
|
||||||
{else}
|
|
||||||
/app{$x->getId()}
|
|
||||||
{/if}
|
|
||||||
{/block}
|
|
||||||
|
|
||||||
{block preview}
|
|
||||||
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" />
|
|
||||||
{/block}
|
|
||||||
|
|
||||||
{block name}
|
|
||||||
{if $type != "apps"}
|
|
||||||
<text style="overflow: hidden;"> {$x->getCanonicalName()}
|
|
||||||
{if $_GET['sort'] == "rating"}({$x->getRating()}%)
|
|
||||||
{elseif $_GET['sort'] == "id"}(id{$x->getId()}){/if}</text>
|
|
||||||
<img n:if="$x->isVerified()"
|
|
||||||
class="name-checkmark"
|
|
||||||
src="/assets/packages/static/openvk/img/checkmark.png"
|
|
||||||
/>
|
|
||||||
{else}
|
|
||||||
{$x->getName()}
|
|
||||||
{/if}
|
|
||||||
{/block}
|
|
||||||
|
|
||||||
{block description}
|
|
||||||
<table class="ugc-table">
|
|
||||||
<tbody>
|
|
||||||
{if $type === "users"}
|
|
||||||
{if !is_null($_GET['status']) && $_GET['status'] != ""}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_status}:</span></td>
|
|
||||||
<td>{$x->getStatus()}</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
{/if}
|
||||||
{if !is_null($_GET['city']) && $_GET['city'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
<div class='summaryBar summaryBarFlex padding'>
|
||||||
<tr>
|
<div class='summary'>
|
||||||
<td><span class="nobold">{_city}:</span></td>
|
<b>{tr("results", $count)} {tr("showing_x_y", $page, $count)}</b>
|
||||||
<td>{$x->getCity()}</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if !is_null($_GET['city']) && $_GET['hometown'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_hometown}:</span></td>
|
|
||||||
<td>{$x->getHometown()}</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if !is_null($_GET['politViews']) && $_GET['politViews'] != 0 && $x->getPrivacySetting("page.info.read") > 1}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_politViews}:</span></td>
|
|
||||||
<td>{tr("politViews_".$x->getPoliticalViews())}</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if !is_null($_GET['email']) && $_GET['email'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_email}:</span></td>
|
|
||||||
<td>{$x->getContactEmail()}</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if !is_null($_GET['telegram']) && $_GET['telegram'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_telegram}:</span></td>
|
|
||||||
<td><a href="tg://resolve?domain={$x->getTelegram()}">@{$x->getTelegram()}</a></td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if !is_null($_GET['site']) && $_GET['site'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_personal_website}:</span></td>
|
|
||||||
<td><a href="{$x->getWebsite()}">{$x->getWebsite()}</a></td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if !is_null($_GET['address']) && $_GET['address'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_address}:</span></td>
|
|
||||||
<td>{$x->getPhysicalAddress()}</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if $x->getPrivacySetting("page.info.read") > 1}
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_pronouns}: </span></td>
|
|
||||||
<td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_relationship}:</span></td>
|
|
||||||
<td>{$x->getLocalizedMaritalStatus()}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><span class="nobold">{_registration_date}: </span></td>
|
|
||||||
<td>{$x->getRegistrationTime()}</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
<tr>
|
|
||||||
{if !empty($x->getDescription())}
|
|
||||||
{if $type != "apps"}
|
|
||||||
<td>
|
|
||||||
<span class="nobold">{_description}:</span>
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
<td {if $type == "apps"}style="width:400px"{/if}>
|
|
||||||
{$x->getDescription() ?? '(' . tr("none") . ')'}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{if $type == "groups"}
|
|
||||||
<td>
|
|
||||||
<span class="nobold">{_size}:</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{tr("participants", $x->getFollowersCount())}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{/block}
|
|
||||||
|
|
||||||
{block content}
|
|
||||||
<style>
|
|
||||||
.comment, .post-divider
|
|
||||||
{
|
|
||||||
border:none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div style="margin-top:-7px">
|
|
||||||
{var $data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
|
||||||
|
|
||||||
{include "../components/paginator.xml", conf => (object) [
|
|
||||||
"page" => $page,
|
|
||||||
"count" => $count,
|
|
||||||
"amount" => sizeof($data),
|
|
||||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
|
||||||
"atBottom" => false,
|
|
||||||
]}
|
|
||||||
</div>
|
|
||||||
<p style="margin-left: 15px; margin-top: 0;">
|
|
||||||
<b>{tr("results", $count)}</b>
|
|
||||||
</p>
|
|
||||||
<div>
|
|
||||||
{include searchOptions}
|
|
||||||
|
|
||||||
<div class="container_gray borderup" style="float:left;width:73.3%;">
|
|
||||||
{if sizeof($data) > 0}
|
|
||||||
{if $type == "users" || $type == "groups" || $type == "apps"}
|
|
||||||
<div class="content" n:foreach="$data as $dat">
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td valign="top">
|
|
||||||
<a href="{include link, x => $dat}">
|
|
||||||
{include preview, x => $dat}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td valign="top" style="width: 100%">
|
|
||||||
{ifset infotable}
|
|
||||||
{include infotable, x => $dat}
|
|
||||||
{else}
|
|
||||||
<a href="{include link, x => $dat}">
|
|
||||||
<b>
|
|
||||||
{include name, x => $dat}
|
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
<br/>
|
|
||||||
{include description, x => $dat}
|
|
||||||
{/ifset}
|
|
||||||
</td>
|
|
||||||
<td n:ifset="actions" valign="top" class="action_links" style="width: 150px;">
|
|
||||||
{include actions, x => $dat}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{elseif $type == "posts"}
|
|
||||||
<div n:foreach="$data as $dat" class="content">
|
|
||||||
{if !$dat || $dat->getTargetWall() < 0 && $dat->getWallOwner()->isHideFromGlobalFeedEnabled() || !$dat->canBeViewedBy($thisUser)}
|
|
||||||
{_closed_group_post}.
|
|
||||||
{else}
|
|
||||||
{include "../components/post.xml", post => $dat, commentSection => true, onWallOf => true}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{elseif $type == "comments"}
|
|
||||||
<div n:foreach="$data as $dat" class="content">
|
|
||||||
{if !$dat->getTarget() || $dat->getTarget()->isDeleted()}
|
|
||||||
{_deleted_target_comment}.
|
|
||||||
{else}
|
|
||||||
{include "../components/comment.xml", comment => $dat, linkW => true}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{elseif $type == "videos"}
|
|
||||||
{foreach $data as $dat}
|
|
||||||
<div class="content">
|
|
||||||
{include "../components/video.xml", video => $dat}
|
|
||||||
</div>
|
</div>
|
||||||
{/foreach}
|
|
||||||
{elseif $type == "audios"}
|
{include "../components/paginator.xml", conf => $paginatorConf}
|
||||||
{foreach $data as $dat}
|
</div>
|
||||||
{include "../Audio/player.xml", audio => $dat}
|
|
||||||
{/foreach}
|
<div class='page_wrap_content' id='search_page'>
|
||||||
{/if}
|
<div n:class='page_wrap_content_main, $section == "audios" && $count > 0 ? audios_padding'>
|
||||||
{else}
|
{if $count > 0}
|
||||||
{ifset customErrorMessage}
|
{if $section === 'users'}
|
||||||
{include customErrorMessage}
|
<div class='search_content def_row_content' n:foreach="$data as $dat">
|
||||||
{else}
|
<table>
|
||||||
{include "../components/nothing.xml"}
|
<tbody>
|
||||||
{/ifset}
|
<tr>
|
||||||
{/if}
|
<td valign="top">
|
||||||
|
<a href="{$dat->getURL()}">
|
||||||
|
<img src="{$dat->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" loading='lazy' />
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td valign="top" style="width: 100%">
|
||||||
|
<a href="{$dat->getURL()}">
|
||||||
|
<b>
|
||||||
|
<text style="overflow: hidden;"> {$dat->getCanonicalName()}
|
||||||
|
{if $order == "rating"}
|
||||||
|
({$dat->getProfileCompletenessReport()->total}%)
|
||||||
|
{/if}
|
||||||
|
</text>
|
||||||
|
<img n:if="$dat->isVerified()"
|
||||||
|
class="name-checkmark"
|
||||||
|
src="/assets/packages/static/openvk/img/checkmark.png"
|
||||||
|
/>
|
||||||
|
</b>
|
||||||
|
{if $dat->getId() == $thisUser->getId()}
|
||||||
|
({_s_it_is_you})
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<table class="ugc-table">
|
||||||
|
<tbody>
|
||||||
|
{if $_REQUEST["order"] == "id"}
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">ID:</span></td>
|
||||||
|
<td>{$dat->getId()}</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if $dat->getPrivacySetting("page.info.read") > 1}
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">{_pronouns}: </span></td>
|
||||||
|
<td>{$dat->isFemale() ? tr("female") : ($dat->isNeutral() ? tr("neutral") : tr("male"))}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">{_relationship}:</span></td>
|
||||||
|
<td>{$dat->getLocalizedMaritalStatus()}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">{_registration_date}: </span></td>
|
||||||
|
<td>{$dat->getRegistrationTime()}</td>
|
||||||
|
</tr>
|
||||||
|
{if !empty($dat->getDescription())}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="nobold">{_description}:</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{$dat->getDescription() ?? '(' . tr("none") . ')'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if !empty($_REQUEST["fav_mus"])}
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">{_favorite_music}:</span></td>
|
||||||
|
<td>{$dat->getFavoriteMusic()}</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if !empty($_REQUEST["fav_films"])}
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">{_favorite_films}:</span></td>
|
||||||
|
<td>{$dat->getFavoriteFilms()}</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if !empty($_REQUEST["fav_shows"])}
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">{_favorite_shows}:</span></td>
|
||||||
|
<td>{$dat->getFavoriteShows()}</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if !empty($_REQUEST["fav_books"])}
|
||||||
|
<tr>
|
||||||
|
<td><span class="nobold">{_favorite_books}:</span></td>
|
||||||
|
<td>{$dat->getFavoriteBooks()}</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if='$count > 0 && !empty($query)'>
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', ['text'])
|
||||||
|
</script>
|
||||||
|
{elseif $section === 'groups'}
|
||||||
|
<div class='search_content def_row_content' n:foreach="$data as $dat">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<a href="{$dat->getURL()}">
|
||||||
|
<img src="{$dat->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" loading='lazy' />
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td valign="top" style="width: 100%">
|
||||||
|
<a href="{$dat->getURL()}">
|
||||||
|
<b>
|
||||||
|
<text style="overflow: hidden;"> {$dat->getCanonicalName()}
|
||||||
|
{if $order == "id"}
|
||||||
|
(id{$dat->getId()})
|
||||||
|
{/if}
|
||||||
|
</text>
|
||||||
|
<img n:if="$dat->isVerified()"
|
||||||
|
class="name-checkmark"
|
||||||
|
src="/assets/packages/static/openvk/img/checkmark.png"
|
||||||
|
/>
|
||||||
|
</b>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<table class="ugc-table">
|
||||||
|
<tbody>
|
||||||
|
{if !empty($dat->getDescription())}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="nobold">{_description}:</span>
|
||||||
|
</td>
|
||||||
|
<td data-highlight='_clubDesc'>
|
||||||
|
{$dat->getDescription() ?? '(' . tr("none") . ')'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
<td>
|
||||||
|
<span class="nobold">{_size}:</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{tr("participants", $dat->getFollowersCount())}
|
||||||
|
</td>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if='$count > 0 && !empty($query)'>
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', ['text', "td[data-highlight='_clubDesc']"])
|
||||||
|
</script>
|
||||||
|
{elseif $section === 'apps'}
|
||||||
|
<div class='search_content def_row_content' n:foreach="$data as $dat">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<a href="/app{$dat->getId()}">
|
||||||
|
<img src="{$dat->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" loading='lazy' />
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td valign="top" style="width: 100%">
|
||||||
|
<a href="/app{$dat->getId()}">
|
||||||
|
<b>
|
||||||
|
<text style="overflow: hidden;">
|
||||||
|
{$dat->getName()}
|
||||||
|
</text>
|
||||||
|
</b>
|
||||||
|
</a><br/>
|
||||||
|
<span style='margin-left: 2px;' data-highlight='_appDesc'>
|
||||||
|
{$dat->getDescription() ?? '(' . tr("none") . ')'}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if='$count > 0 && !empty($query)'>
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', ['text', "span[data-highlight='_appDesc']"])
|
||||||
|
</script>
|
||||||
|
{elseif $section === 'posts'}
|
||||||
|
<div class='search_content' n:foreach="$data as $dat">
|
||||||
|
{if !$dat || $dat->getWallOwner()->isHideFromGlobalFeedEnabled()}
|
||||||
|
{_closed_group_post}.
|
||||||
|
{else}
|
||||||
|
{include "../components/post.xml", post => $dat, commentSection => true, onWallOf => true}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if='$count > 0 && !empty($query)'>
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', [".post:not(.comment) > tbody > tr > td > .post-content > .text .really_text"])
|
||||||
|
</script>
|
||||||
|
{elseif $section === 'videos'}
|
||||||
|
<div class='search_content' n:foreach="$data as $dat">
|
||||||
|
{include "../components/video.xml", video => $dat}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if='$count > 0 && !empty($query)'>
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', [".video_name", ".video_description"])
|
||||||
|
</script>
|
||||||
|
{elseif $section === 'audios'}
|
||||||
|
<div class='search_content' n:foreach="$data as $dat">
|
||||||
|
{include "../Audio/player.xml", audio => $dat}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if="$count > 0 && !empty($query) && empty($_REQUEST['only_performers'])">
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', [".mediaInfo .performer a", ".mediaInfo .title"])
|
||||||
|
</script>
|
||||||
|
{elseif $section === 'audios_playlists'}
|
||||||
|
<div class='search_content' n:foreach="$data as $dat">
|
||||||
|
{include "../Audio/playlistListView.xml", playlist => $dat}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if="$count > 0 && !empty($query) && empty($_REQUEST['only_performers'])">
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', [".playlistName", ".playlistDesc"])
|
||||||
|
</script>
|
||||||
|
{/if}
|
||||||
|
{else}
|
||||||
|
{include "../components/content_error.xml", description => tr("no_results_by_this_query")}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class='page_wrap_content_options verticalGrayTabsWrapper'>
|
||||||
|
<div class="page_wrap_content_options_list verticalGrayTabs with_padding">
|
||||||
|
<a n:attr="id => $section === 'users' ? 'used'" href="/search?section=users&q={urlencode($query)}"> {_s_people}</a>
|
||||||
|
<a n:attr="id => $section === 'groups' ? 'used'" href="/search?section=groups&q={urlencode($query)}"> {_s_groups}</a>
|
||||||
|
<a n:attr="id => $section === 'posts' ? 'used'" href="/search?section=posts&q={urlencode($query)}"> {_s_posts}</a>
|
||||||
|
<a n:attr="id => $section === 'videos' ? 'used'" href="/search?section=videos&q={urlencode($query)}"> {_s_videos}</a>
|
||||||
|
<a n:attr="id => $section === 'apps' ? 'used'" href="/search?section=apps&q={urlencode($query)}"> {_s_apps}</a>
|
||||||
|
<a n:attr="id => $section === 'audios' ? 'used'" href="/search?section=audios&q={urlencode($query)}"> {_s_audios}</a>
|
||||||
|
<a n:attr="id => $section === 'audios_playlists' ? 'used'" href="/search?section=audios_playlists&q={urlencode($query)}">{_s_audios_playlists}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='page_search_options'>
|
||||||
|
{include searchOptions}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div n:if='$paginatorConf->pageCount > 1' class='page_content_paginator_bottom'>
|
||||||
|
{include "../components/paginator.xml", conf => $extendedPaginatorConf}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
|
||||||
window.addEventListener("load", (event) => {
|
|
||||||
document.getElementsByClassName("container_gray")[0].style.minHeight = document.getElementsByClassName("searchOptions")[0].clientHeight+"px";
|
|
||||||
document.getElementsByClassName("searchOptions")[0].style.minHeight = document.getElementsByClassName("container_gray")[0].clientHeight-3+"px";
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block searchOptions}
|
{block searchOptions}
|
||||||
<div class="searchOptions">
|
<div class="search_option">
|
||||||
<ul class="searchList">
|
<div class="search_option_name">
|
||||||
<a {if $type === "users"} id="used"{/if} href="/search?type=users{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_people} {if $type === "users"} ({$count}){/if}</a>
|
<div class='search_option_name_ico'></div>
|
||||||
<a {if $type === "groups"} id="used"{/if} href="/search?type=groups{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_groups} {if $type === "groups"} ({$count}){/if}</a>
|
{_s_order_by}
|
||||||
<a {if $type === "comments"}id="used"{/if} href="/search?type=comments{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id">{_s_comments} {if $type === "comments"}({$count}){/if}</a>
|
</div>
|
||||||
<a {if $type === "posts"} id="used"{/if} href="/search?type=posts{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_posts} {if $type === "posts"} ({$count}){/if}</a>
|
<div class="search_option_content">
|
||||||
<a {if $type === "videos"} id="used"{/if} href="/search?type=videos{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_videos} {if $type === "videos"} ({$count}){/if}</a>
|
<select name="order" form="search_form" data-default='id'>
|
||||||
<a {if $type === "apps"} id="used"{/if} href="/search?type=apps{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_apps} {if $type === "apps"} ({$count}){/if}</a>
|
{if $section == "users"}
|
||||||
<a {if $type === "audios"} id="used"{/if} href="/search?type=audios{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_audios} {if $type === "audios"} ({$count}){/if}</a>
|
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_reg_date}</option>
|
||||||
</ul>
|
|
||||||
|
{if OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"]}
|
||||||
<div class="searchOption">
|
<option value="rating" n:attr="selected => $order == 'rating'">{_s_order_by_rating}</option>
|
||||||
<div class="searchOptionName" id="n_sort" onclick="hideParams('sort')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_s_order_by}</div>
|
|
||||||
<div class="searchOptionBlock" id="s_sort">
|
|
||||||
<select name="sort" form="searcher" id="sortyor">
|
|
||||||
<option value="id" {if $_GET["sort"] == "name"}selected{/if}>{_s_order_by_id}</option>
|
|
||||||
{if $type == "users"}
|
|
||||||
<option value="name" {if $_GET["sort"] == "name"}selected{/if}>{_s_order_by_name}</option>
|
|
||||||
{if OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"]}
|
|
||||||
<option value="rating" {if $_GET["sort"] == "rating"}selected{/if}>{_s_order_by_rating}</option>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
{elseif $section == "posts"}
|
||||||
{if $type == "audios"}
|
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_publishing_date}</option>
|
||||||
<option value="length" n:attr="selected => $_GET['sort'] == 'length'">{_s_order_by_length}</option>
|
{elseif $section == "audios"}
|
||||||
<option value="listens" n:attr="selected => $_GET['sort'] == 'listens'">{_s_order_by_listens}</option>
|
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_upload_date}</option>
|
||||||
{/if}
|
|
||||||
</select>
|
|
||||||
<div id="invertor">
|
|
||||||
<input type="checkbox" name="invert" value="1" form="searcher" {if !is_null($_GET['invert']) && $_GET['invert'] == "1"}checked{/if}>{_s_order_invert}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{if $type !== "groups" && $type !== "apps"} {* В OpenVK не сохраняется дата создания групп и приложений *}
|
|
||||||
<div class="searchOption">
|
|
||||||
<div class="searchOptionName" id="n_dates" onclick="hideParams('dates')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_s_by_date}</div>
|
|
||||||
<div class="searchOptionBlock" id="s_dates">
|
|
||||||
{if $type != "users"}
|
|
||||||
<p id="bydate">{_s_date_before}:<br>
|
|
||||||
{else}
|
{else}
|
||||||
<p id="bydate">{_s_registered_before}:<br>
|
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_creation_date}</option>
|
||||||
{/if}
|
{/if}
|
||||||
<input type="date" name="datebefore"
|
|
||||||
form="searcher"
|
{if $section == "audios" || $section == "audios_playlists"}
|
||||||
id="bydate"
|
<option value="length" n:attr="selected => $order == 'length'">{_s_order_by_length}</option>
|
||||||
style="width:100%"
|
<option value="listens" n:attr="selected => $order == 'listens'">{_s_order_by_listens}</option>
|
||||||
value="{if !is_null($_GET['datebefore'])}{$_GET['datebefore']}{/if}"
|
|
||||||
min="2019-11-19"
|
|
||||||
max={date('Y-m-d')}></p>
|
|
||||||
{if $type != "users"}
|
|
||||||
<p id="bydate">{_s_date_after}:<br>
|
|
||||||
{else}
|
|
||||||
<p id="bydate">{_s_registered_after}:<br>
|
|
||||||
{/if}
|
{/if}
|
||||||
<input type="date" name="dateafter"
|
</select>
|
||||||
form="searcher"
|
|
||||||
style="width:100%"
|
<label n:if="$order != 'rating'">
|
||||||
id="bydate"
|
<input type="checkbox" name="invert" value="1" form="search_form" n:attr="checked => $_REQUEST['invert'] == '1'">
|
||||||
value="{if !is_null($_GET['dateafter'])}{$_GET['dateafter']}{/if}"
|
{_s_order_invert}
|
||||||
min="2019-11-18"
|
</label>
|
||||||
max={date('Y-m-d')}></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
|
|
||||||
{if $type === "users"}
|
<div n:if="$section == 'users'" class="search_option">
|
||||||
<div class="searchOption">
|
<div class="search_option_name">
|
||||||
<div class="searchOptionName" id="n_main" onclick="hideParams('main')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_main}</div>
|
<div class='search_option_name_ico'></div>
|
||||||
<div class="searchOptionBlock" id="s_main">
|
{_main}
|
||||||
<input type="text" value="{if !is_null($_GET['status'])}{$_GET['status']}{/if}" form="searcher" placeholder="{_status}" name="status">
|
|
||||||
<input type="text" value="{if !is_null($_GET['city'])}{$_GET['city']}{/if}" form="searcher" placeholder="{_city}" name="city">
|
|
||||||
<input type="text" value="{if !is_null($_GET['hometown'])}{$_GET['hometown']}{/if}" form="searcher" placeholder="{_hometown}" name="hometown">
|
|
||||||
<input name="is_online" type="checkbox" {if !is_null($_GET['is_online']) && $_GET['is_online'] == "1"}checked{/if} form="searcher" value="1">{_s_now_on_site}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search_option_content">
|
||||||
<!-- <div class="searchOption">
|
<input type="text" n:attr="value => $_REQUEST['city']" form="search_form" placeholder="{_city}" name="city">
|
||||||
<div class="searchOptionName" id="n_gender" onclick="hideParams('gender')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_gender}</div>
|
<input type="text" n:attr="value => $_REQUEST['hometown']" form="search_form" placeholder="{_hometown}" name="hometown">
|
||||||
<div class="searchOptionBlock" id="s_gender">
|
|
||||||
<p><input type="radio" form="searcher" id="gend" {if $_GET['gender'] == 0}checked{/if} name="gender" value="0">{_male}</p>
|
<label>
|
||||||
<p><input type="radio" form="searcher" id="gend1"{if $_GET['gender'] == 1}checked{/if} name="gender" value="1">{_female}</p>
|
<input name="is_online" type="checkbox" n:attr="checked => $_REQUEST['is_online'] == '1'" form="search_form" value="1">
|
||||||
<p><input type="radio" form="searcher" id="gend2"{if $_GET['gender'] == 2 || is_null($_GET['gender'])}checked{/if} name="gender" value="2">{_s_any}</p>
|
{_s_now_on_site}
|
||||||
</div>
|
</label>
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<div class="searchOption">
|
|
||||||
<div class="searchOptionName" id="n_relationship" onclick="hideParams('relationship')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{ovk_proc_strtr(tr("relationship"), 14)}</div>
|
|
||||||
<div class="searchOptionBlock" id="s_relationship">
|
|
||||||
<select name="maritalstatus" form="searcher">
|
|
||||||
<option n:foreach="range(0, 8) as $i" value="{$i}" {if $_GET['maritalstatus'] == $i}selected{/if} form="searcher">
|
|
||||||
{tr("relationship_".$i)}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="searchOption">
|
<div n:if="$section == 'users'" class="search_option">
|
||||||
<div class="searchOptionName" id="n_politViews" onclick="hideParams('politViews')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_politViews}</div>
|
<div class="search_option_name">
|
||||||
<div class="searchOptionBlock" id="s_politViews">
|
<div class='search_option_name_ico'></div>
|
||||||
<select name="politViews" form="searcher">
|
{_pronouns}
|
||||||
<option n:foreach="range(0, 9) as $i" value="{$i}" {if $_GET['politViews'] == $i}selected{/if} form="searcher">
|
</div>
|
||||||
|
<div class="search_option_content">
|
||||||
|
<label><input type="radio" form="search_form" n:attr="checked => $_REQUEST['gender'] == 0" name="gender" value="0">{_male}</label>
|
||||||
|
<label><input type="radio" form="search_form" n:attr="checked => $_REQUEST['gender'] == 1" name="gender" value="1">{_female}</label>
|
||||||
|
<label><input type="radio" form="search_form" n:attr="checked => $_REQUEST['gender'] == 2" name="gender" value="2">{_neutral}</label>
|
||||||
|
<label><input type="radio" form="search_form" n:attr="checked => is_null($_REQUEST['gender']) || $_REQUEST['gender'] == 3" name="gender" data-default='1' value="3">{_s_any}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div n:if="$section == 'users'" n:class="search_option, !isset($_REQUEST['polit_views']) && !isset($_REQUEST['marital_status']) ? search_option_hidden">
|
||||||
|
<div class="search_option_name">
|
||||||
|
<div class='search_option_name_ico'></div>
|
||||||
|
{_s_additional}
|
||||||
|
</div>
|
||||||
|
<div class="search_option_content">
|
||||||
|
<label>
|
||||||
|
{_politViews}
|
||||||
|
<select name="polit_views" form="search_form" data-default='0'>
|
||||||
|
<option n:foreach="range(0, 9) as $i" value="{$i}" n:attr="selected => $_REQUEST['polit_views'] == $i">
|
||||||
{tr("politViews_".$i)}
|
{tr("politViews_".$i)}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</label>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="searchOption">
|
<label>
|
||||||
<div class="searchOptionName" id="n_contacts" onclick="hideParams('contacts')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_contacts}</div>
|
{_relationship}
|
||||||
<div class="searchOptionBlock" id="s_contacts">
|
<select name="marital_status" form="search_form" data-default='0'>
|
||||||
<input type="text" name="email" value="{if !is_null($_GET['email'])}{$_GET['email']}{/if}" form="searcher" placeholder="{_email}">
|
<option n:foreach="range(0, 8) as $i" value="{$i}" n:attr="selected => $_REQUEST['marital_status'] == $i">
|
||||||
<input type="text" name="telegram" value="{if !is_null($_GET['telegram'])}{$_GET['telegram']}{/if}" form="searcher" placeholder="{_telegram}"><br id="contacts">
|
{tr("relationship_".$i)}
|
||||||
<input type="text" name="site" value="{if !is_null($_GET['site'])}{$_GET['site']}{/if}" form="searcher" placeholder="{_personal_website}"><br id="contacts">
|
</option>
|
||||||
<input type="text" name="address" value="{if !is_null($_GET['address'])}{$_GET['address']}{/if}" form="searcher" placeholder="{_address}">
|
</select>
|
||||||
</div>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="searchOption">
|
<div n:if="$section == 'videos'" class="search_option">
|
||||||
<div class="searchOptionName" id="n_interests" onclick="hideParams('interests')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_interests}</div>
|
<div class="search_option_name">
|
||||||
<div class="searchOptionBlock" id="s_interests">
|
<div class='search_option_name_ico'></div>
|
||||||
<input type="text" value="{if !is_null($_GET['interests'])}{$_GET['interests']}{/if}" form="searcher" placeholder="{_interests}" name="interests">
|
{_s_main}
|
||||||
<input type="text" value="{if !is_null($_GET['fav_mus'])}{$_GET['fav_mus']}{/if}" form="searcher" placeholder="{_favorite_music}" name="fav_mus">
|
|
||||||
<input type="text" value="{if !is_null($_GET['fav_films'])}{$_GET['fav_films']}{/if}" form="searcher" placeholder="{_favorite_films}" name="fav_films">
|
|
||||||
<input type="text" value="{if !is_null($_GET['fav_shows'])}{$_GET['fav_shows']}{/if}" form="searcher" placeholder="{_favorite_shows}" name="fav_shows">
|
|
||||||
<input type="text" value="{if !is_null($_GET['fav_books'])}{$_GET['fav_books']}{/if}" form="searcher" placeholder="{_favorite_books}" name="fav_books">
|
|
||||||
<input type="text" value="{if !is_null($_GET['fav_quote'])}{$_GET['fav_quote']}{/if}" form="searcher" placeholder="{_favorite_quotes}" name="fav_quote">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<div class="search_option_content">
|
||||||
|
<label>
|
||||||
{if $type == "audios"}
|
<input type="checkbox" value='1' name="only_youtube" n:attr="checked => !empty($_REQUEST['only_youtube'])" form="search_form">{_s_only_youtube}
|
||||||
<div class="searchOption">
|
</label>
|
||||||
<div class="searchOptionName" id="n_main_audio" onclick="hideParams('main_audio')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_s_main}</div>
|
</div>
|
||||||
<div class="searchOptionBlock" id="s_main_audio">
|
</div>
|
||||||
<label><input type="checkbox" name="only_performers" n:attr="checked => !empty($_GET['only_performers'])" form="searcher">{_s_only_performers}</label><br>
|
<div n:if="$section == 'audios'" class="search_option">
|
||||||
<label><input type="checkbox" name="with_lyrics" n:attr="checked => !empty($_GET['with_lyrics'])" form="searcher">{_s_with_lyrics}</label>
|
<div class="search_option_name">
|
||||||
</div>
|
<div class='search_option_name_ico'></div>
|
||||||
|
{_s_main}
|
||||||
|
</div>
|
||||||
|
<div class="search_option_content">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="only_performers" n:attr="checked => !empty($_REQUEST['only_performers'])" form="search_form">{_s_only_performers}
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="with_lyrics" n:attr="checked => !empty($_REQUEST['with_lyrics'])" form="search_form">{_s_with_lyrics}
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
{_genre}
|
||||||
|
<select name='genre' form="search_form" data-default='any'>
|
||||||
|
<option n:attr="selected: empty($_REQUEST['genre'])" value="any">{_s_any_single}</option>
|
||||||
|
<option n:foreach='\openvk\Web\Models\Entities\Audio::genres as $genre' n:attr="selected: $_REQUEST['genre'] == $genre" value="{$genre}">
|
||||||
|
{$genre}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<input class="button" type="button" id="dnt" value="{_reset}" onclick="resetSearch()">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<input class="button" id="search_reset" type="button" value="{_reset}">
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
<input type="text" name="pseudo" value="{$user->getPseudo()}" />
|
<input type="text" name="pseudo" value="{$user->getPseudo()}" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{if OPENVK_ROOT_CONF['openvk']['credentials']['zadarma']['enable']}
|
{if OPENVK_ROOT_CONF['openvk']['credentials']['smsc']['enable']}
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top">
|
<td width="120" valign="top">
|
||||||
<span class="nobold">{_phone}: </span>
|
<span class="nobold">{_phone}: </span>
|
||||||
|
|
|
@ -4,11 +4,14 @@
|
||||||
{var $act = $_GET["act"] ?? "friends"}
|
{var $act = $_GET["act"] ?? "friends"}
|
||||||
|
|
||||||
{if $act == "incoming"}
|
{if $act == "incoming"}
|
||||||
{var $iterator = iterator_to_array($user->getFollowers($page))}
|
{var $iterator = iterator_to_array($user->getRequests($page))}
|
||||||
{var $count = $user->getFollowersCount()}
|
{var $count = $user->getRequestsCount()}
|
||||||
{elseif $act == "outcoming"}
|
{elseif $act == "outcoming"}
|
||||||
{var $iterator = iterator_to_array($user->getSubscriptions($page))}
|
{var $iterator = iterator_to_array($user->getSubscriptions($page))}
|
||||||
{var $count = $user->getSubscriptionsCount()}
|
{var $count = $user->getSubscriptionsCount()}
|
||||||
|
{elseif $act == "followers"}
|
||||||
|
{var $iterator = iterator_to_array($user->getFollowers($page))}
|
||||||
|
{var $count = $user->getFollowersCount()}
|
||||||
{elseif $act == "online"}
|
{elseif $act == "online"}
|
||||||
{var $iterator = iterator_to_array($user->getFriendsOnline($page))}
|
{var $iterator = iterator_to_array($user->getFriendsOnline($page))}
|
||||||
{var $count = $user->getFriendsOnlineCount()}
|
{var $count = $user->getFriendsOnlineCount()}
|
||||||
|
@ -22,6 +25,8 @@
|
||||||
{_incoming_req}
|
{_incoming_req}
|
||||||
{elseif $act == "outcoming"}
|
{elseif $act == "outcoming"}
|
||||||
{_outcoming_req}
|
{_outcoming_req}
|
||||||
|
{elseif $act == "followers"}
|
||||||
|
{_followers}
|
||||||
{elseif $act == "online"}
|
{elseif $act == "online"}
|
||||||
{_friends_online}
|
{_friends_online}
|
||||||
{else}
|
{else}
|
||||||
|
@ -38,6 +43,8 @@
|
||||||
{_incoming_req}
|
{_incoming_req}
|
||||||
{elseif $act == "outcoming"}
|
{elseif $act == "outcoming"}
|
||||||
{_outcoming_req}
|
{_outcoming_req}
|
||||||
|
{elseif $act == "followers"}
|
||||||
|
{_followers}
|
||||||
{elseif $act == "online"}
|
{elseif $act == "online"}
|
||||||
{_friends_online}
|
{_friends_online}
|
||||||
{else}
|
{else}
|
||||||
|
@ -53,18 +60,23 @@
|
||||||
<div n:attr="id => ($act === 'online' ? 'activetabs' : 'ki')" class="tab">
|
<div n:attr="id => ($act === 'online' ? 'activetabs' : 'ki')" class="tab">
|
||||||
<a n:attr="id => ($act === 'online' ? 'act_tab_a' : 'ki')" href="?act=online">{_online}</a>
|
<a n:attr="id => ($act === 'online' ? 'act_tab_a' : 'ki')" href="?act=online">{_online}</a>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="!is_null($thisUser) && $user->getId() === $thisUser->getId()" n:attr="id => ($act === 'incoming' || $act === 'outcoming' ? 'activetabs' : 'ki')" class="tab">
|
<div n:if="!is_null($thisUser) && $user->getId() === $thisUser->getId()" n:attr="id => ($act === 'incoming' || $act === 'followers' || $act === 'outcoming' ? 'activetabs' : 'ki')" class="tab">
|
||||||
<a n:attr="id => ($act === 'incoming' || $act === 'outcoming' ? 'act_tab_a' : 'ki')" href="?act=incoming">{_req}</a>
|
<a n:attr="id => ($act === 'incoming' || $act === 'followers' || $act === 'outcoming' ? 'act_tab_a' : 'ki')" href="?act=incoming">{_req}</a>
|
||||||
</div>
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block size}
|
{block size}
|
||||||
<div n:if="$act === 'incoming' || $act === 'outcoming'" class="mb_tabs">
|
<div n:if="$act === 'incoming' || $act === 'followers' || $act === 'outcoming'" class="mb_tabs">
|
||||||
<div n:attr="id => ($act === 'incoming' ? 'active' : 'ki')" class="mb_tab">
|
<div n:attr="id => ($act === 'incoming' ? 'active' : 'ki')" class="mb_tab">
|
||||||
<div>
|
<div>
|
||||||
<a href="?act=incoming">{_incoming_req}</a>
|
<a href="?act=incoming">{_incoming_req}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div n:attr="id => ($act === 'followers' ? 'active' : 'ki')" class="mb_tab">
|
||||||
|
<div>
|
||||||
|
<a href="?act=followers">{_followers}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div n:attr="id => ($act === 'outcoming' ? 'active' : 'ki')" class="mb_tab">
|
<div n:attr="id => ($act === 'outcoming' ? 'active' : 'ki')" class="mb_tab">
|
||||||
<div>
|
<div>
|
||||||
<a href="?act=outcoming">{_outcoming_req}</a>
|
<a href="?act=outcoming">{_outcoming_req}</a>
|
||||||
|
@ -78,6 +90,8 @@
|
||||||
{tr("req", $count)}
|
{tr("req", $count)}
|
||||||
{elseif $act == "outcoming"}
|
{elseif $act == "outcoming"}
|
||||||
{tr("req", $count)}
|
{tr("req", $count)}
|
||||||
|
{elseif $act == "followers"}
|
||||||
|
{tr("followers", $count)}
|
||||||
{elseif $act == "online"}
|
{elseif $act == "online"}
|
||||||
{tr("friends_list_online", $count)}
|
{tr("friends_list_online", $count)}
|
||||||
{else}
|
{else}
|
||||||
|
@ -97,7 +111,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография пользователя" />
|
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография пользователя" loading=lazy />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
@ -112,8 +126,8 @@
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top"><span class="nobold">{_gender}: </span></td>
|
<td width="120" valign="top"><span class="nobold">{_pronouns}: </span></td>
|
||||||
<td>{$x->isFemale() ? tr("female") : tr("male")}</td>
|
<td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top"><span class="nobold">{_relationship}:</span></td>
|
<td width="120" valign="top"><span class="nobold">{_relationship}:</span></td>
|
||||||
|
@ -131,21 +145,29 @@
|
||||||
{if ($x->getId() !== $thisUser->getId()) && ($thisUser->getId() === $user->getId())}
|
{if ($x->getId() !== $thisUser->getId()) && ($thisUser->getId() === $user->getId())}
|
||||||
{var $subStatus = $x->getSubscriptionStatus($thisUser)}
|
{var $subStatus = $x->getSubscriptionStatus($thisUser)}
|
||||||
{if $subStatus === 0}
|
{if $subStatus === 0}
|
||||||
<form action="/setSub/user" method="post" class="profile_link_form">
|
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
|
||||||
<input type="hidden" name="act" value="add" />
|
<input type="hidden" name="act" value="add" />
|
||||||
<input type="hidden" name="id" value="{$x->getId()}" />
|
<input type="hidden" name="id" value="{$x->getId()}" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
<input type="submit" class="profile_link" value="{_friends_add}" />
|
<input type="submit" class="profile_link" value="{_friends_add}" />
|
||||||
</form>
|
</form>
|
||||||
{elseif $subStatus === 1}
|
{elseif $subStatus === 1}
|
||||||
<form action="/setSub/user" method="post" class="profile_link_form">
|
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
|
||||||
<input type="hidden" name="act" value="add" />
|
<input type="hidden" name="act" value="add" />
|
||||||
<input type="hidden" name="id" value="{$x->getId()}" />
|
<input type="hidden" name="id" value="{$x->getId()}" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
<input type="submit" class="profile_link" value="{_friends_accept}" />
|
<input type="submit" class="profile_link" value="{_friends_accept}" />
|
||||||
</form>
|
</form>
|
||||||
|
{if $act !== 'followers'}
|
||||||
|
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
|
||||||
|
<input type="hidden" name="act" value="rej" />
|
||||||
|
<input type="hidden" name="id" value="{$x->getId()}" />
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<input type="submit" class="profile_link" value="{_friends_leave_in_flw}" />
|
||||||
|
</form>
|
||||||
|
{/if}
|
||||||
{elseif $subStatus === 2}
|
{elseif $subStatus === 2}
|
||||||
<form action="/setSub/user" method="post" class="profile_link_form">
|
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
|
||||||
<input type="hidden" name="act" value="rem" />
|
<input type="hidden" name="act" value="rem" />
|
||||||
<input type="hidden" name="id" value="{$x->getId()}" />
|
<input type="hidden" name="id" value="{$x->getId()}" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
@ -153,7 +175,7 @@
|
||||||
</form>
|
</form>
|
||||||
{elseif $subStatus === 3}
|
{elseif $subStatus === 3}
|
||||||
<a href="/im?sel={$x->getId()}" class="profile_link">{_send_message}</a>
|
<a href="/im?sel={$x->getId()}" class="profile_link">{_send_message}</a>
|
||||||
<form action="/setSub/user" method="post" class="profile_link_form">
|
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
|
||||||
<input type="hidden" name="act" value="rem" />
|
<input type="hidden" name="act" value="rem" />
|
||||||
<input type="hidden" name="id" value="{$x->getId()}" />
|
<input type="hidden" name="id" value="{$x->getId()}" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
@ -161,4 +183,4 @@
|
||||||
</form>
|
</form>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
|
@ -48,7 +48,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография группы" />
|
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография группы" loading=lazy />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}{/block}
|
{block name}{/block}
|
||||||
|
@ -128,4 +128,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
|
@ -69,27 +69,22 @@
|
||||||
{else}
|
{else}
|
||||||
|
|
||||||
<div class="left_small_block">
|
<div class="left_small_block">
|
||||||
<div style="margin-left: auto;margin-right: auto;display: table;position:relative;" class="avatar_block" id="av">
|
<div class="avatar_block">
|
||||||
{var $hasAvatar = !str_contains($user->getAvatarUrl('miniscule'), "/assets/packages/static/openvk/img/camera_200.png")}
|
{var $hasAvatar = !str_contains($user->getAvatarUrl('miniscule'), "/assets/packages/static/openvk/img/camera_200.png")}
|
||||||
{if !is_null($thisUser) && $hasAvatar == false && $user->getId() == $thisUser->getId()}
|
|
||||||
<a href="javascript:addAvatarImage(false)" class="text_add_image">{_add_image}</a>
|
{if $thisUser && $user->getId() == $thisUser->getId()}
|
||||||
{elseif !is_null($thisUser) && $user && $hasAvatar == true && $user->getId() == $thisUser->getId()}
|
<a {if $hasAvatar}style="display:none"{/if} class="add_image_text" id="add_image">{_add_image}</a>
|
||||||
<div class="avatar_controls">
|
<div {if !$hasAvatar}style="display:none"{/if} class="avatar_controls">
|
||||||
<div class="avatarDelete">
|
<div class="avatarDelete hoverable"></div>
|
||||||
<a id="upl" href="javascript:deleteAvatar('{$user->getAvatarPhoto()->getPrettyId()}')"><img src="/assets/packages/static/openvk/img/delete.png"/></a>
|
|
||||||
</div>
|
|
||||||
<div class="avatar_variants">
|
<div class="avatar_variants">
|
||||||
<div class="variant">
|
<a class="_add_image hoverable" id="add_image"><span>{_upload_new_picture}</span></a>
|
||||||
<img src="/assets/packages/static/openvk/img/upload.png" style="margin-left:15px;height: 10px;">
|
|
||||||
<a href="javascript:addAvatarImage(false)"><p>{_upload_new_picture}</p></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<a href="{$user->getAvatarLink()|nocheck}">
|
<a href="{$user->getAvatarLink()|nocheck}">
|
||||||
<img src="{$user->getAvatarUrl('normal')}"
|
<img src="{$user->getAvatarUrl('normal')}"
|
||||||
alt="{$user->getCanonicalName()}"
|
alt="{$user->getCanonicalName()}"
|
||||||
id="thisUserAvatar"
|
id="bigAvatar"
|
||||||
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -307,7 +302,7 @@
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURLBySizeId('small')}"
|
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURLBySizeId('small')}"
|
||||||
style="max-width: 80px; max-height: 54pt;" />
|
style="max-width: 80px; max-height: 54pt;" loading=lazy />
|
||||||
</div>
|
</div>
|
||||||
<div style="overflow: hidden; overflow-wrap: break-word;">
|
<div style="overflow: hidden; overflow-wrap: break-word;">
|
||||||
<b><a href="/album{$album->getPrettyId()}">{$album->getName()}</a></b><br>
|
<b><a href="/album{$album->getPrettyId()}">{$album->getName()}</a></b><br>
|
||||||
|
@ -475,11 +470,11 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr n:if="!is_null($user->getHometown())">
|
<tr n:if="!is_null($user->getHometown())">
|
||||||
<td class="label"><span class="nobold">{_hometown}:</span></td>
|
<td class="label"><span class="nobold">{_hometown}:</span></td>
|
||||||
<td class="data"><a href="/search?type=users&query=&hometown={urlencode($user->getHometown())}">{$user->getHometown()}</a></td>
|
<td class="data"><a href="/search?section=users&q=&hometown={urlencode($user->getHometown())}">{$user->getHometown()}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label"><span class="nobold">{_politViews}:</span></td>
|
<td class="label"><span class="nobold">{_politViews}:</span></td>
|
||||||
<td class="data"><a {if $user->getPoliticalViews() != 0}href="/search?type=users&query=&politViews={$user->getPoliticalViews()}"{/if}>{var $pviews = $user->getPoliticalViews()}{_"politViews_$pviews"}</a></td>
|
<td class="data">{var $pviews = $user->getPoliticalViews()}{_"politViews_$pviews"}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr n:if="!is_null($user->getBirthday())">
|
<tr n:if="!is_null($user->getBirthday())">
|
||||||
<td class="label"><span class="nobold">{_birth_date}:</span></td>
|
<td class="label"><span class="nobold">{_birth_date}:</span></td>
|
||||||
|
@ -525,7 +520,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr n:if="!is_null($user->getCity())">
|
<tr n:if="!is_null($user->getCity())">
|
||||||
<td class="label"><span class="nobold">{_city}:</span></td>
|
<td class="label"><span class="nobold">{_city}:</span></td>
|
||||||
<td class="data"><a href="/search?type=users&query=&city={$user->getCity()}">{$user->getCity()}</a></td>
|
<td class="data"><a href="/search?type=section&q=&city={$user->getCity()}">{$user->getCity()}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr n:if="!is_null($user->getPhysicalAddress())">
|
<tr n:if="!is_null($user->getPhysicalAddress())">
|
||||||
<td class="label"><span class="nobold">{_address}:</span></td>
|
<td class="label"><span class="nobold">{_address}:</span></td>
|
||||||
|
@ -543,7 +538,7 @@
|
||||||
{var $interests = explode(", ", $user->getInterests())}
|
{var $interests = explode(", ", $user->getInterests())}
|
||||||
|
|
||||||
{foreach $interests as $interest}
|
{foreach $interests as $interest}
|
||||||
<a href="/search?type=users&query=&interests={urlencode($interest)}">{$interest}</a>{if $interest != end($interests)},{/if}
|
<span>{$interest}</span>{if $interest != end($interests)},{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -554,7 +549,7 @@
|
||||||
{var $musics = explode(", ", $user->getFavoriteMusic())}
|
{var $musics = explode(", ", $user->getFavoriteMusic())}
|
||||||
|
|
||||||
{foreach $musics as $music}
|
{foreach $musics as $music}
|
||||||
<a href="/search?type=audios&query={urlencode($music)}">{$music}</a>{if $music != end($musics)},{/if}
|
<a href="/search?section=audios&q={urlencode($music)}">{$music}</a>{if $music != end($musics)},{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -564,7 +559,7 @@
|
||||||
{var $films = explode(", ", $user->getFavoriteFilms())}
|
{var $films = explode(", ", $user->getFavoriteFilms())}
|
||||||
|
|
||||||
{foreach $films as $film}
|
{foreach $films as $film}
|
||||||
<a href="/search?type=users&query=&fav_films={urlencode($film)}">{$film}</a>{if $film != end($films)},{/if}
|
<a href="/search?section=users&q=&fav_films={urlencode($film)}">{$film}</a>{if $film != end($films)},{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -574,7 +569,7 @@
|
||||||
{var $shows = explode(", ", $user->getFavoriteShows())}
|
{var $shows = explode(", ", $user->getFavoriteShows())}
|
||||||
|
|
||||||
{foreach $shows as $show}
|
{foreach $shows as $show}
|
||||||
<a href="/search?type=users&query=&fav_shows={urlencode($show)}">{$show}</a>{if $show != end($shows)},{/if}
|
<a href="/search?section=users&q=&fav_shows={urlencode($show)}">{$show}</a>{if $show != end($shows)},{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -584,7 +579,7 @@
|
||||||
{var $books = explode(", ", $user->getFavoriteBooks())}
|
{var $books = explode(", ", $user->getFavoriteBooks())}
|
||||||
|
|
||||||
{foreach $books as $book}
|
{foreach $books as $book}
|
||||||
<a href="/search?type=users&query=&fav_books={urlencode($book)}">{$book}</a>{if $book != end($books)},{/if}
|
<a href="/search?section=users&q=&fav_books={urlencode($book)}">{$book}</a>{if $book != end($books)},{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -659,7 +654,7 @@
|
||||||
<img style="width: 70px; max-height: 70px;"
|
<img style="width: 70px; max-height: 70px;"
|
||||||
src="{$giftDescriptor->gift->getImage(2)}"
|
src="{$giftDescriptor->gift->getImage(2)}"
|
||||||
alt="{$hideInfo ? tr('gift') : ($giftDescriptor->caption ?? tr('gift'))}"
|
alt="{$hideInfo ? tr('gift') : ($giftDescriptor->caption ?? tr('gift'))}"
|
||||||
title="{$hideInfo ? tr('gift') : ($giftDescriptor->caption ?? tr('gift'))}" />
|
title="{$hideInfo ? tr('gift') : ($giftDescriptor->caption ?? tr('gift'))}" loading=lazy />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -769,8 +764,6 @@
|
||||||
<script n:if="isset($thisUser) && $user->getId() == $thisUser->getId()" n:syntax="off">
|
<script n:if="isset($thisUser) && $user->getId() == $thisUser->getId()" n:syntax="off">
|
||||||
function setStatusEditorShown(shown) {
|
function setStatusEditorShown(shown) {
|
||||||
document.getElementById("status_editor").style.display = shown ? "block" : "none";
|
document.getElementById("status_editor").style.display = shown ? "block" : "none";
|
||||||
if(!document.status_popup_form.submit.style.width)
|
|
||||||
document.status_popup_form.submit.style.width = document.status_popup_form.submit.offsetWidth + 4 + "px"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("click", event => {
|
document.addEventListener("click", event => {
|
||||||
|
@ -823,4 +816,4 @@
|
||||||
|
|
||||||
{block bodyScripts}
|
{block bodyScripts}
|
||||||
{script "js/al_despacito_wall.js"}
|
{script "js/al_despacito_wall.js"}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
193
Web/Presenters/templates/VKAPI/OAuthLogin.xml
Normal file
193
Web/Presenters/templates/VKAPI/OAuthLogin.xml
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Получение доступа | OpenVK</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
background-color: #ebedf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 10px #d4d6d8;
|
||||||
|
padding: 13px 0;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > div {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 620px;
|
||||||
|
margin: auto;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ovkUser a:not(#pfpLink) {
|
||||||
|
color: #000;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ovkUser img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ovkLogo a {
|
||||||
|
display: flex;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #fff;
|
||||||
|
background: #606060;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 21px;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body > div {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 620px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
border: 1px solid #e1e3e6;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 18px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authHeading, #authExplainer {
|
||||||
|
color: #818c99;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(#authHeading, #authExplainer) b {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authButtons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authButtons a {
|
||||||
|
color: #818c99;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authButtons a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authButtons button {
|
||||||
|
cursor: pointer;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
background-color: #606060;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 7px;
|
||||||
|
border-radius: 7px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<div>
|
||||||
|
<div style="width: 85px;">
|
||||||
|
</div>
|
||||||
|
<div id="ovkLogo">
|
||||||
|
<a href="/" target="_blank">O</a>
|
||||||
|
</div>
|
||||||
|
<div id="ovkUser">
|
||||||
|
<a href="/logout?hash={rawurlencode($csrfToken)}">{_header_log_out}</a>
|
||||||
|
<a id="pfpLink" href="/id0" target="_blank">
|
||||||
|
<img src="{$thisUser->getAvatarUrl('miniscule')}" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<main>
|
||||||
|
<div id="authHeading">
|
||||||
|
{_app},
|
||||||
|
<b>
|
||||||
|
{if is_null($origin)}
|
||||||
|
{tr("identifies_itself_as", $clientName)}{else}
|
||||||
|
{tr("located_at_url", $origin)}{/if}</b>, {_wants_your_token}.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="authExplainer">
|
||||||
|
<b>{_app_will_have_access_to}</b><br/>
|
||||||
|
{_oauth_scope_all|noescape}.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="authButtons">
|
||||||
|
<button id="authAllow">{_oauth_grant}</button>
|
||||||
|
<a id="authDeny" href="javascript:void(0)">{_oauth_deny}</a>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{script "js/node_modules/msgpack-lite/dist/msgpack.min.js"}
|
||||||
|
{script "js/al_api.js"}
|
||||||
|
<script>
|
||||||
|
//<![CDATA[
|
||||||
|
let clientName = {$clientName};
|
||||||
|
let usePostMessage = {$usePostMessage} && window.opener != null;
|
||||||
|
let acceptsStale = {$acceptsStale};
|
||||||
|
let origin = {$origin};
|
||||||
|
let redirectUri = {$redirectUri};
|
||||||
|
|
||||||
|
document.querySelector("#authDeny").addEventListener("click", () => {
|
||||||
|
if (usePostMessage) {
|
||||||
|
window.opener.postMessage({
|
||||||
|
error: 'access_denied',
|
||||||
|
error_reason: 'user_denied',
|
||||||
|
error_description: 'User denied your request'
|
||||||
|
}, origin);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.href = redirectUri + 'error=access_denied&error_reason=user_denied&error_description=User%20denied%20your%20request';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector("#authAllow").addEventListener("click", async () => {
|
||||||
|
let response = await API.Apps.getRegularToken(clientName, acceptsStale);
|
||||||
|
let ret = {
|
||||||
|
access_token: response.token,
|
||||||
|
expires_in: 0,
|
||||||
|
user_id: {$thisUser->getId()},
|
||||||
|
is_stale: response.is_stale
|
||||||
|
};
|
||||||
|
|
||||||
|
if (usePostMessage) {
|
||||||
|
window.opener.postMessage(ret, origin);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.href = redirectUri + (new URLSearchParams(ret)).toString();
|
||||||
|
});
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -33,7 +33,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<div class="video-preview" id="videoOpen" data-id="{$x->getId()}">
|
<div class="video-preview" data-id="{$x->getId()}">
|
||||||
<img src="{$x->getThumbnailURL()}"
|
<img src="{$x->getThumbnailURL()}"
|
||||||
alt="{$x->getName()}"
|
alt="{$x->getName()}"
|
||||||
style="max-width: 170px; max-height: 127px; margin: auto;" />
|
style="max-width: 170px; max-height: 127px; margin: auto;" />
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
<span id="videoOpen" data-id="{$x->getId()}" style="color:unset;">{$x->getName()}</span>
|
<span data-id="{$x->getId()}" style="color:unset;">{$x->getName()}</span>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block description}
|
{block description}
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
<span style="color: grey;">{_video_uploaded} {$x->getPublicationTime()}</span><br/>
|
<span style="color: grey;">{_video_uploaded} {$x->getPublicationTime()}</span><br/>
|
||||||
<span style="color: grey;">{_video_updated} {$x->getEditTime() ?? $x->getPublicationTime()}</span>
|
<span style="color: grey;">{_video_updated} {$x->getEditTime() ?? $x->getPublicationTime()}</span>
|
||||||
<p>
|
<p>
|
||||||
<a href="/video{$x->getPrettyId()}" id="videoOpen" data-id="{$x->getId()}">{_view_video}</a>
|
<a href="/video{$x->getPrettyId()}" data-id="{$x->getId()}">{_view_video}</a>
|
||||||
{if $x->getCommentsCount() > 0}| <a href="/video{$x->getPrettyId()}#comments">{_comments} ({$x->getCommentsCount()})</a>{/if}
|
{if $x->getCommentsCount() > 0}| <a href="/video{$x->getPrettyId()}#comments">{_comments} ({$x->getCommentsCount()})</a>{/if}
|
||||||
</p>
|
</p>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{css "css/bsdn.css"}
|
{css "css/bsdn.css"}
|
||||||
{css "css/dialog.css"}
|
{css "css/dialog.css"}
|
||||||
{css "css/notifications.css"}
|
{css "css/notifications.css"}
|
||||||
{css "css/avataredit.css"}
|
{css "css/avatar-edit.css"}
|
||||||
{css "css/audios.css"}
|
{css "css/audios.css"}
|
||||||
|
|
||||||
{if $isXmas}
|
{if $isXmas}
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
{css "css/bsdn.css"}
|
{css "css/bsdn.css"}
|
||||||
{css "css/dialog.css"}
|
{css "css/dialog.css"}
|
||||||
{css "css/notifications.css"}
|
{css "css/notifications.css"}
|
||||||
{css "css/avataredit.css"}
|
{css "css/avatar-edit.css"}
|
||||||
{css "css/audios.css"}
|
{css "css/audios.css"}
|
||||||
|
|
||||||
{if $isXmas}
|
{if $isXmas}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{if !$attachment->isDeleted()}
|
{if !$attachment->isDeleted()}
|
||||||
{var $link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
{var $link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
||||||
<a href="{$link}" onclick="OpenMiniature(event, {$attachment->getURLBySizeId('normal')}, {$parent->getPrettyId()}, {$attachment->getPrettyId()}, {$parentType})">
|
<a href="{$link}" onclick="OpenMiniature(event, {$attachment->getURLBySizeId('normal')}, {$parent->getPrettyId()}, {$attachment->getPrettyId()}, {$parentType})">
|
||||||
<img class="media media_makima" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" />
|
<img class="media media_makima" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" loading=lazy />
|
||||||
</a>
|
</a>
|
||||||
{else}
|
{else}
|
||||||
<a href="javascript:alert('{_attach_no_longer_available}');">
|
<a href="javascript:alert('{_attach_no_longer_available}');">
|
||||||
|
@ -58,4 +58,4 @@
|
||||||
<span style="color:red;">{_version_incompatibility}</span>
|
<span style="color:red;">{_version_incompatibility}</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{php $GLOBALS["_nesAttGloCou"] = NULL}
|
{php $GLOBALS["_nesAttGloCou"] = NULL}
|
|
@ -36,21 +36,26 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
||||||
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}
|
<a href="{if $correctLink}{$comment->getTargetURL()}{/if}#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}
|
||||||
<span n:if="$comment->getEditTime()" class="edited editedMark">({_edited_short})</span>
|
<span n:if="$comment->getEditTime()" class="edited editedMark">({_edited_short})</span>
|
||||||
</a>
|
</a>
|
||||||
{if !$timeOnly}
|
{if !$timeOnly}
|
||||||
|
|
|
|
||||||
{if $comment->canBeDeletedBy($thisUser)}
|
{if $comment->canBeDeletedBy($thisUser)}
|
||||||
<a href="/comment{$comment->getId()}/delete">{_delete}</a> |
|
<a href="/comment{$comment->getId()}/delete">{_delete}</a>
|
||||||
{/if}
|
{/if}
|
||||||
{if $comment->canBeEditedBy($thisUser)}
|
{if $comment->canBeEditedBy($thisUser)}
|
||||||
<a id="editPost" data-id="{$comment->getId()}">{_edit}</a> |
|
|
|
||||||
|
<a id="editPost" data-id="{$comment->getId()}">{_edit}</a>
|
||||||
{/if}
|
{/if}
|
||||||
<a class="comment-reply">{_reply}</a>
|
{if !$no_reply_button}
|
||||||
{if $thisUser->getId() != $comment->getOwner()->getId()}
|
|
|
||||||
|
<a class="comment-reply">{_reply}</a>
|
||||||
|
{/if}
|
||||||
|
{if $thisUser->getId() != $author->getRealId()}
|
||||||
|
|
|
||||||
{var $canReport = true}
|
{var $canReport = true}
|
||||||
| <a href="javascript:reportComment()">{_report}</a>
|
<a href="javascript:reportComment()">{_report}</a>
|
||||||
{/if}
|
{/if}
|
||||||
<div style="float: right; font-size: .7rem;">
|
<div style="float: right; font-size: .7rem;">
|
||||||
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
||||||
|
@ -59,29 +64,11 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{var $target = "wall"}
|
|
||||||
|
|
||||||
{if get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Note"}
|
|
||||||
{php $target = "note"}
|
|
||||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Post"}
|
|
||||||
{php $target = "wall"}
|
|
||||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Photo"}
|
|
||||||
{php $target = "photo"}
|
|
||||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Video"}
|
|
||||||
{php $target = "video"}
|
|
||||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Topic"}
|
|
||||||
{php $target = "topic"}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
|
|
||||||
<span n:if="$compact ?? false">
|
<span n:if="$compact ?? false">
|
||||||
|
|
||||||
| <a
|
| <a
|
||||||
{if is_null($linkW)}
|
href="#_comment{$comment->getId()}"
|
||||||
href="#_comment{$comment->getId()}"
|
|
||||||
{else}
|
|
||||||
href="{$target}{!is_null($comment->getTarget()) ? $comment->getTarget()->getPrettyId() : $comment->getOwner()->getId()}#_comment{$comment->getId()}"
|
|
||||||
{/if}
|
|
||||||
class="date"
|
class="date"
|
||||||
>{$comment->getPublicationTime()}</a>
|
>{$comment->getPublicationTime()}</a>
|
||||||
|
|
||||||
|
|
6
Web/Presenters/templates/components/content_error.xml
Normal file
6
Web/Presenters/templates/components/content_error.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<div class='content_page_error'>
|
||||||
|
<span>
|
||||||
|
<b n:if="!empty($title)">{$title}<br><br></b>
|
||||||
|
{$description}
|
||||||
|
</span>
|
||||||
|
</div>
|
|
@ -1,8 +1,8 @@
|
||||||
{var $space = 3}
|
{var $space = $conf->space ?? 3}
|
||||||
{var $pageCount = ceil($conf->count / $conf->perPage)}
|
{var $pageCount = ceil($conf->count / $conf->perPage)}
|
||||||
|
|
||||||
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" style="padding: 8px;">
|
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" n:attr="style => (!$conf->tidy ? 'padding: 8px;')">
|
||||||
<div n:class="paginator, ($conf->atBottom ?? false) ? paginator-at-bottom">
|
<div n:class="paginator, ($conf->atBottom ?? false) ? paginator-at-bottom, ($conf->tidy ? 'tidy')">
|
||||||
<a n:if="$conf->page > $space" n:attr="class => ($conf->page === 1 ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => 1]), 'k', '&', PHP_QUERY_RFC3986)}">«</a>
|
<a n:if="$conf->page > $space" n:attr="class => ($conf->page === 1 ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => 1]), 'k', '&', PHP_QUERY_RFC3986)}">«</a>
|
||||||
{for $j = $conf->page - ($space-1); $j <= $conf->page + ($space-1); $j++}
|
{for $j = $conf->page - ($space-1); $j <= $conf->page + ($space-1); $j++}
|
||||||
<a n:if="$j > 0 && $j <= $pageCount" n:attr="class => ($conf->page === $j ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $j]), 'k', '&', PHP_QUERY_RFC3986)}">{$j}</a>
|
<a n:if="$j > 0 && $j <= $pageCount" n:attr="class => ($conf->page === $j ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $j]), 'k', '&', PHP_QUERY_RFC3986)}">{$j}</a>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
<a href="{$author->getURL()}">
|
<a href="{$author->getURL()}">
|
||||||
<img src="{$author->getAvatarURL('miniscule')}" class="post-avatar" width="50" />
|
<img src="{$author->getAvatarURL('miniscule')}" class="post-avatar" width="50" loading=lazy />
|
||||||
<span n:if="!$post->isPostedOnBehalfOfGroup() && !($compact ?? false) && $author->isOnline()" class="post-online">{_online}</span>
|
<span n:if="!$post->isPostedOnBehalfOfGroup() && !($compact ?? false) && $author->isOnline()" class="post-online">{_online}</span>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -165,4 +165,4 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
|
@ -4,7 +4,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<div class="video-preview">
|
<div class="video-preview">
|
||||||
<a href="/video{$video->getPrettyId()}" id="videoOpen" data-id="{$video->getId()}">
|
<a href="/video{$video->getPrettyId()}" {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">
|
||||||
<img src="{$video->getThumbnailURL()}"
|
<img src="{$video->getThumbnailURL()}"
|
||||||
style="max-width: 170px; max-height: 127px; margin: auto;" >
|
style="max-width: 170px; max-height: 127px; margin: auto;" >
|
||||||
</a>
|
</a>
|
||||||
|
@ -15,18 +15,18 @@
|
||||||
{include infotable, x => $dat}
|
{include infotable, x => $dat}
|
||||||
{else}
|
{else}
|
||||||
<a href="/video{$video->getPrettyId()}">
|
<a href="/video{$video->getPrettyId()}">
|
||||||
<b id="videoOpen" data-id="{$video->getId()}">
|
<b class='video_name' {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">
|
||||||
{$video->getName()}
|
{$video->getName()}
|
||||||
</b>
|
</b>
|
||||||
</a>
|
</a>
|
||||||
<br/>
|
<br/>
|
||||||
<p>
|
<p>
|
||||||
<span>{$video->getDescription() ?? ""}</span>
|
<span class='video_description'>{$video->getDescription() ?? ""}</span>
|
||||||
</p>
|
</p>
|
||||||
<span style="color: grey;">{_video_uploaded} {$video->getPublicationTime()}</span><br/>
|
<span style="color: grey;">{_video_uploaded} {$video->getPublicationTime()}</span><br/>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="/video{$video->getPrettyId()}" id="videoOpen" data-id="{$video->getId()}">{_view_video}</a>
|
<a href="/video{$video->getPrettyId()}" {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">{_view_video}</a>
|
||||||
{if $video->getCommentsCount() > 0}| <a href="/video{$video->getPrettyId()}#comments">{_comments} ({$video->getCommentsCount()})</a>{/if}
|
{if $video->getCommentsCount() > 0}| <a href="/video{$video->getPrettyId()}#comments">{_comments} ({$video->getCommentsCount()})</a>{/if}
|
||||||
</p>
|
</p>
|
||||||
{/ifset}
|
{/ifset}
|
||||||
|
|
|
@ -62,7 +62,7 @@ class Themepacks implements \ArrayAccess
|
||||||
return $offset === Themepacks::DEFAULT_THEME_ID ? false : isset($this->loadedThemepacks[$offset]);
|
return $offset === Themepacks::DEFAULT_THEME_ID ? false : isset($this->loadedThemepacks[$offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function offsetGet($offset)
|
function offsetGet($offset) : mixed
|
||||||
{
|
{
|
||||||
return $this->loadedThemepacks[$offset];
|
return $this->loadedThemepacks[$offset];
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,21 +22,21 @@ class DateTime
|
||||||
$now = date_create();
|
$now = date_create();
|
||||||
$diff = date_diff($now, $then);
|
$diff = date_diff($now, $then);
|
||||||
if($diff->invert === 0)
|
if($diff->invert === 0)
|
||||||
return ovk_strftime_safe("%e %B %Y ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
return ovk_strftime_safe("%e %B %Y ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R", $this->timestamp);
|
||||||
|
|
||||||
if($this->timestamp >= strtotime("midnight")) { # Today
|
if($this->timestamp >= strtotime("midnight")) { # Today
|
||||||
if($diff->h >= 1)
|
if($diff->h >= 1)
|
||||||
return tr("time_today") . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
return tr("time_today") . tr("time_at_sp") . ovk_strftime_safe(" %R", $this->timestamp);
|
||||||
else if($diff->i < 2)
|
else if($diff->i < 2)
|
||||||
return tr("time_just_now");
|
return tr("time_just_now");
|
||||||
else
|
else
|
||||||
return $diff->i === 5 ? tr("time_exactly_five_minutes_ago") : tr("time_minutes_ago", $diff->i);
|
return $diff->i === 5 ? tr("time_exactly_five_minutes_ago") : tr("time_minutes_ago", $diff->i);
|
||||||
} else if($this->timestamp >= strtotime("-1day midnight")) { # Yesterday
|
} else if($this->timestamp >= strtotime("-1day midnight")) { # Yesterday
|
||||||
return tr("time_yesterday") . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
return tr("time_yesterday") . tr("time_at_sp") . ovk_strftime_safe(" %R", $this->timestamp);
|
||||||
} else if(ovk_strftime_safe("%Y", $this->timestamp) === ovk_strftime_safe("%Y", time())) { # In this year
|
} else if(ovk_strftime_safe("%Y", $this->timestamp) === ovk_strftime_safe("%Y", time())) { # In this year
|
||||||
return ovk_strftime_safe("%e %h ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
return ovk_strftime_safe("%e %h ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R", $this->timestamp);
|
||||||
} else {
|
} else {
|
||||||
return ovk_strftime_safe("%e %B %Y ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
return ovk_strftime_safe("%e %B %Y ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R", $this->timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ class Makima
|
||||||
$result->tiles = [
|
$result->tiles = [
|
||||||
new ThumbTile(1, 3, $wCover, $maxHeight), new ThumbTile(1, 1, $w, $h0),
|
new ThumbTile(1, 3, $wCover, $maxHeight), new ThumbTile(1, 1, $w, $h0),
|
||||||
new ThumbTile(1, 1, $w, $h1),
|
new ThumbTile(1, 1, $w, $h1),
|
||||||
new ThumbTile(1, 1, $w, $h1),
|
new ThumbTile(1, 1, $w, $h2),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -183,6 +183,8 @@ routes:
|
||||||
handler: "Photos->deletePhoto"
|
handler: "Photos->deletePhoto"
|
||||||
- url: "/al_avatars"
|
- url: "/al_avatars"
|
||||||
handler: "User->setAvatar"
|
handler: "User->setAvatar"
|
||||||
|
- url: "/delete_avatar"
|
||||||
|
handler: "User->deleteAvatar"
|
||||||
- url: "/videos{num}"
|
- url: "/videos{num}"
|
||||||
handler: "Videos->list"
|
handler: "Videos->list"
|
||||||
- url: "/videos/upload"
|
- url: "/videos/upload"
|
||||||
|
@ -231,6 +233,8 @@ routes:
|
||||||
handler: "Group->edit"
|
handler: "Group->edit"
|
||||||
- url: "/club{num}/al_avatar"
|
- url: "/club{num}/al_avatar"
|
||||||
handler: "Group->setAvatar"
|
handler: "Group->setAvatar"
|
||||||
|
- url: "/club{num}/delete_avatar"
|
||||||
|
handler: "Group->deleteAvatar"
|
||||||
- url: "/club{num}/backdrop"
|
- url: "/club{num}/backdrop"
|
||||||
handler: "Group->editBackdrop"
|
handler: "Group->editBackdrop"
|
||||||
- url: "/club{num}/stats"
|
- url: "/club{num}/stats"
|
||||||
|
@ -375,6 +379,8 @@ routes:
|
||||||
handler: "VKAPI->route"
|
handler: "VKAPI->route"
|
||||||
- url: "/token"
|
- url: "/token"
|
||||||
handler: "VKAPI->tokenLogin"
|
handler: "VKAPI->tokenLogin"
|
||||||
|
- url: "/authorize"
|
||||||
|
handler: "VKAPI->OAuthLogin"
|
||||||
- url: "/admin/sandbox"
|
- url: "/admin/sandbox"
|
||||||
handler: "About->sandbox"
|
handler: "About->sandbox"
|
||||||
- url: "/admin/chandler/groups"
|
- url: "/admin/chandler/groups"
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflowedName {
|
.audiosPaddingContainer {
|
||||||
position: absolute;
|
padding: 8px;
|
||||||
z-index: 99;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.musicIcon {
|
.musicIcon {
|
||||||
|
@ -15,10 +14,6 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.musicIcon:hover {
|
|
||||||
filter: brightness(99%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.musicIcon.pressed {
|
.musicIcon.pressed {
|
||||||
filter: brightness(150%);
|
filter: brightness(150%);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +26,15 @@
|
||||||
height: 46px;
|
height: 46px;
|
||||||
border-bottom: 1px solid #d8d8d8;
|
border-bottom: 1px solid #d8d8d8;
|
||||||
box-shadow: 1px 0px 8px 0px rgba(34, 60, 80, 0.2);
|
box-shadow: 1px 0px 8px 0px rgba(34, 60, 80, 0.2);
|
||||||
position: relative;
|
position: sticky;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bigPlayer.tidy {
|
||||||
|
width: 100%;
|
||||||
|
margin-left: unset;
|
||||||
|
margin-top: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bigPlayer.floating {
|
.bigPlayer.floating {
|
||||||
|
@ -171,11 +174,16 @@
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bigPlayer .paddingLayer .trackInfo .timer .elapsedTime {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.bigPlayer .paddingLayer .trackInfo .trackName {
|
.bigPlayer .paddingLayer .trackInfo .trackName {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 81%;
|
width: 81%;
|
||||||
|
height: 13px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,11 +191,26 @@
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bigPlayer .paddingLayer .trackInfo b:hover {
|
.bigPlayer .paddingLayer .trackInfo a {
|
||||||
|
font-weight: bold;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bigPlayer .paddingLayer .trackInfo a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bigPlayer .paddingLayer .trackPanel .track .selectableTrack > div {
|
||||||
|
width: 95%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bigPlayer .paddingLayer .volumePanel .selectableTrack > div {
|
||||||
|
position: relative;
|
||||||
|
width:72%
|
||||||
|
}
|
||||||
|
|
||||||
.audioEmbed .track > .selectableTrack, .bigPlayer .selectableTrack {
|
.audioEmbed .track > .selectableTrack, .bigPlayer .selectableTrack {
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
width: calc(100% - 8px);
|
width: calc(100% - 8px);
|
||||||
|
@ -214,7 +237,7 @@
|
||||||
|
|
||||||
.audioEntry.nowPlaying {
|
.audioEntry.nowPlaying {
|
||||||
background: #606060;
|
background: #606060;
|
||||||
border: 1px solid #4f4f4f;
|
outline: 1px solid #4f4f4f;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +247,7 @@
|
||||||
|
|
||||||
.audioEntry.nowPlaying:hover {
|
.audioEntry.nowPlaying:hover {
|
||||||
background: #4e4e4e !important;
|
background: #4e4e4e !important;
|
||||||
|
border-radius: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry.nowPlaying .performer a {
|
.audioEntry.nowPlaying .performer a {
|
||||||
|
@ -246,8 +270,32 @@
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry.nowPlaying .buttons .musicIcon, .audioEntry.nowPlaying .explicitMark {
|
.audioEntry.nowPlaying .explicitMark path {
|
||||||
filter: brightness(187%) opacity(72%);
|
fill: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEntry.nowPlaying .buttons .musicIcon.edit-icon {
|
||||||
|
background-position: -152px -51px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEntry.nowPlaying .buttons .musicIcon.download-icon {
|
||||||
|
background-position: -151px -67px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEntry.nowPlaying .buttons .musicIcon.add-icon {
|
||||||
|
background-position: -94px -52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEntry.nowPlaying .buttons .musicIcon.report-icon {
|
||||||
|
background-position: -66px -67px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEntry.nowPlaying .buttons .musicIcon.remove-icon-group {
|
||||||
|
background-position: -122px -67px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEntry.nowPlaying .buttons .musicIcon.remove-icon {
|
||||||
|
background-position: -108px -67px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry {
|
.audioEntry {
|
||||||
|
@ -264,12 +312,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry .subTracks {
|
.audioEntry .subTracks {
|
||||||
display: flex;
|
display: none;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audioEntry .subTracks.shown {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.audioEntry .playerButton .playIcon {
|
.audioEntry .playerButton .playIcon {
|
||||||
background-image: url('/assets/packages/static/openvk/img/play_buttons.gif');
|
background-image: url('/assets/packages/static/openvk/img/play_buttons.gif');
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -290,16 +342,45 @@
|
||||||
height: 23px;
|
height: 23px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audioEntry .status .mediaInfo {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflowedName {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 99;
|
||||||
|
width: 80% !important;
|
||||||
|
}
|
||||||
|
|
||||||
.audioEntry .status strong {
|
.audioEntry .status strong {
|
||||||
color: #4C4C4C;
|
color: #4C4C4C;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEmbed .track {
|
.audioEmbed .track {
|
||||||
display: none;
|
padding: 0px 0;
|
||||||
padding: 4px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEmbed .track, .audioEmbed.playing .track {
|
.audioEmbed .track .selectableTrack {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEmbed .track .selectableTrack .selectableTrackSlider {
|
||||||
|
position: relative;
|
||||||
|
width: calc(100% - 18px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEmbed .subTracks .lengthTrackWrapper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEmbed .subTracks .volumeTrackWrapper {
|
||||||
|
width: 81px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEmbed.playing .track {
|
||||||
display: unset;
|
display: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +390,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry:hover .buttons {
|
.audioEntry:hover .buttons {
|
||||||
display: block;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry:hover .volume .hideOnHover {
|
.audioEntry:hover .volume .hideOnHover {
|
||||||
|
@ -318,11 +399,16 @@
|
||||||
|
|
||||||
.audioEntry .buttons {
|
.audioEntry .buttons {
|
||||||
display: none;
|
display: none;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
gap: 5px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
width: 62px;
|
width: 62px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 3%;
|
right: 3%;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
|
margin-top: 7px;
|
||||||
/* чтоб избежать заедания во время ховера кнопки добавления */
|
/* чтоб избежать заедания во время ховера кнопки добавления */
|
||||||
clip-path: inset(0 0 0 0);
|
clip-path: inset(0 0 0 0);
|
||||||
}
|
}
|
||||||
|
@ -331,18 +417,21 @@
|
||||||
width: 11px;
|
width: 11px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 4px;
|
|
||||||
margin-top: 3px;
|
|
||||||
background-position: -137px -51px;
|
background-position: -137px -51px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audioEntry .buttons .download-icon {
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
float: right;
|
||||||
|
background-position: -136px -67px;
|
||||||
|
}
|
||||||
|
|
||||||
.audioEntry .buttons .add-icon {
|
.audioEntry .buttons .add-icon {
|
||||||
width: 11px;
|
width: 11px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
float: right;
|
float: right;
|
||||||
background-position: -80px -52px;
|
background-position: -80px -52px;
|
||||||
margin-top: 3px;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry .buttons .add-icon-group {
|
.audioEntry .buttons .add-icon-group {
|
||||||
|
@ -350,7 +439,6 @@
|
||||||
height: 11px;
|
height: 11px;
|
||||||
float: right;
|
float: right;
|
||||||
background-position: -94px -52px;
|
background-position: -94px -52px;
|
||||||
margin-top: 3px;
|
|
||||||
transition: margin-right 0.1s ease-out, opacity 0.1s ease-out;
|
transition: margin-right 0.1s ease-out, opacity 0.1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,9 +446,7 @@
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
float: right;
|
float: right;
|
||||||
background-position: -67px -51px;
|
background-position: -50px -67px;
|
||||||
margin-top: 3px;
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-icon-noaction {
|
.add-icon-noaction {
|
||||||
|
@ -374,22 +460,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry .buttons .remove-icon {
|
.audioEntry .buttons .remove-icon {
|
||||||
margin-top: 3px;
|
|
||||||
width: 11px;
|
width: 11px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
margin-left: 2px;
|
|
||||||
float: right;
|
float: right;
|
||||||
background-position: -108px -52px;
|
background-position: -108px -52px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry .buttons .remove-icon-group {
|
.audioEntry .buttons .remove-icon-group {
|
||||||
margin-top: 3px;
|
|
||||||
width: 13px;
|
width: 13px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
float: right;
|
float: right;
|
||||||
background-position: -122px -52px;
|
background-position: -122px -52px;
|
||||||
margin-left: 3px;
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEmbed .lyrics {
|
.audioEmbed .lyrics {
|
||||||
|
@ -410,12 +491,12 @@
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEmbed.withdrawn .status > *, .audioEmbed.processed .status > *, .audioEmbed.withdrawn .playerButton > *, .audioEmbed.processed .playerButton > * {
|
.audioEmbed.withdrawn .status > *, .audioEmbed.processed .playerButton > *, .audioEmbed.withdrawn .playerButton > * {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEmbed.withdrawn {
|
.audioEmbed.withdrawn {
|
||||||
filter: opacity(0.8);
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlistCover img {
|
.playlistCover img {
|
||||||
|
@ -427,25 +508,55 @@
|
||||||
margin-top: 14px;
|
margin-top: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlistContainer {
|
.playlistBlock .playlistWrapper {
|
||||||
display: grid;
|
float: left;
|
||||||
grid-template-columns: repeat(3, 146px);
|
padding-left: 13px;
|
||||||
gap: 18px 10px;
|
width:75%
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlistContainer .playlistCover {
|
.playlistCover .profile_links .profile_link {
|
||||||
width: 111px;
|
width: 100%;
|
||||||
height: 111px;
|
}
|
||||||
|
|
||||||
|
/* playlist listview */
|
||||||
|
|
||||||
|
.playlistListView {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: #c4c4c4;
|
padding: 7px;
|
||||||
|
gap: 9px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlistContainer .playlistCover img {
|
.playlistListView:hover, .playlistListView .playlistCover {
|
||||||
max-width: 111px;
|
background: #ebebeb;
|
||||||
max-height: 111px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playlistListView .playlistCover img {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlistListView .playlistInfo, .playlistListView .playlistInfo .playlistInfoTopPart {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlistListView .playlistInfo {
|
||||||
|
gap: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlistListView .playlistInfo .playlistName {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlistListView .playlistInfo .playlistMeta, .playlistListView .playlistInfo .playlistMeta span {
|
||||||
|
color: #676767;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* other */
|
||||||
|
|
||||||
.ovk-diag-body .searchBox {
|
.ovk-diag-body .searchBox {
|
||||||
background: #e6e6e6;
|
background: #e6e6e6;
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
@ -490,17 +601,16 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlistCover img {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explicitMark {
|
.explicitMark {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
width: 11px;
|
width: 11px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
background: url('/assets/packages/static/openvk/img/explicit.svg');
|
}
|
||||||
background-repeat: no-repeat;
|
|
||||||
|
.explicitMark path {
|
||||||
|
fill: #828a99;
|
||||||
|
fill-opacity: .7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioStatus span {
|
.audioStatus span {
|
||||||
|
@ -517,8 +627,14 @@
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audiosDiv {
|
||||||
|
width: 103.1%;
|
||||||
|
display: flex;
|
||||||
|
margin: 0px 0px -10px -12px;
|
||||||
|
}
|
||||||
|
|
||||||
/* <center> 🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣*/
|
/* <center> 🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣*/
|
||||||
.audiosDiv center span {
|
.audiosDiv center span, .error_full_wrapper center span {
|
||||||
color: #707070;
|
color: #707070;
|
||||||
margin: 120px 0px !important;
|
margin: 120px 0px !important;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -528,15 +644,6 @@
|
||||||
margin-left: -10px;
|
margin-left: -10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlistInfo {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playlistInfo .playlistName {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchList.floating {
|
.searchList.floating {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 199;
|
z-index: 199;
|
||||||
|
@ -583,10 +690,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.friendsAudiosList {
|
.friendsAudiosList {
|
||||||
margin-left: -7px;
|
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.friendsAudiosList > a {
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.friendsAudiosList .elem {
|
.friendsAudiosList .elem {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1px 1px;
|
padding: 1px 1px;
|
||||||
|
@ -659,3 +769,27 @@
|
||||||
.addToPlaylist {
|
.addToPlaylist {
|
||||||
width: 22%;
|
width: 22%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#_addAudioAdditional {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#_addAudioAdditional #_tabs {
|
||||||
|
margin: 0px -6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#_addAudioAdditional #_tabs .mb_tabs {
|
||||||
|
background-color: unset;
|
||||||
|
border-bottom: unset;
|
||||||
|
padding: 0px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#_addAudioAdditional #_tip {
|
||||||
|
margin: 5px 0px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#_addAudioAdditional #_content {
|
||||||
|
margin-top: 6px;
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
|
182
Web/static/css/avatar-edit.css
Normal file
182
Web/static/css/avatar-edit.css
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
.avatar_block {
|
||||||
|
position: relative;
|
||||||
|
clip-path: inset(0 0 0.7% 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar_block .add_image_text {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #2B587A;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
left: 0px;
|
||||||
|
bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar_block .add_image_text:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#temp_uploadPic {
|
||||||
|
width: 40%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hoverable {
|
||||||
|
transition: all 200ms ease-in-out;
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hoverable:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar_block *, .avatar_block .avatarDelete::before {
|
||||||
|
-webkit-transition: all 200ms ease-in-out;
|
||||||
|
-moz-transition: all 200ms ease-in-out;
|
||||||
|
-o-transition: all 200ms ease-in-out;
|
||||||
|
transition: all 200ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
._add_image::before {
|
||||||
|
margin-top: 2px;
|
||||||
|
content: ' ';
|
||||||
|
background: url('/assets/packages/static/openvk/img/upload.png');
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatarDelete {
|
||||||
|
position: absolute;
|
||||||
|
right: 0%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.75);
|
||||||
|
padding: 1px 0px 4px 3px;
|
||||||
|
border-radius: 0px 0px 0px 5px;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 15px;
|
||||||
|
height: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatarDelete::before {
|
||||||
|
content: ' ';
|
||||||
|
background: url('/assets/packages/static/openvk/img/upload.png');
|
||||||
|
background-position: -10px 2px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 12px;
|
||||||
|
height: 14px;
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.avatar_block:hover .avatarDelete {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.avatar_block:hover .avatar_variants {
|
||||||
|
opacity: 1 !important;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar_controls .avatar_variants {
|
||||||
|
opacity:0;
|
||||||
|
position:absolute;
|
||||||
|
background-color: rgba(0, 0, 0, 0.75);
|
||||||
|
width:100%;
|
||||||
|
bottom:0;
|
||||||
|
margin-bottom:-8px;
|
||||||
|
color:white;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar_controls .avatar_variants a {
|
||||||
|
opacity: 60%;
|
||||||
|
display: flex;
|
||||||
|
user-select: none;
|
||||||
|
padding: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar_controls .avatar_variants span {
|
||||||
|
color: white;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar_controls .avatar_variants a:hover, .avatarDelete:hover::before {
|
||||||
|
opacity: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-container.moving .cropper-point {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-modal {
|
||||||
|
opacity: 0.7;
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point {
|
||||||
|
transition: opacity 200ms ease-in-out;
|
||||||
|
background-color: #fff !important;
|
||||||
|
height: 7px !important;
|
||||||
|
width: 9px !important;
|
||||||
|
opacity: 0.6;
|
||||||
|
box-shadow: black 0px 0px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-line {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-container {
|
||||||
|
width: 421px;
|
||||||
|
height: 279px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-view-box {
|
||||||
|
outline: none;
|
||||||
|
outline-color: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-image-cont {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-image-cont img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-image-cont .rotateButtons {
|
||||||
|
height: 20px;
|
||||||
|
margin-top: -31px;
|
||||||
|
margin-right: 5px;
|
||||||
|
width: 45px;
|
||||||
|
float: right;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
padding: 3px 5px 3px 2px;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-image-cont .rotateButtons div {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-image-cont .rotateButtons ._rotateLeft {
|
||||||
|
background: url(/assets/packages/static/openvk/img/upload.png);
|
||||||
|
height: 20px;
|
||||||
|
width: 23px;
|
||||||
|
background-position: -23px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-image-cont .rotateButtons ._rotateRight {
|
||||||
|
background: url(/assets/packages/static/openvk/img/upload.png);
|
||||||
|
height: 18px;
|
||||||
|
width: 22px;
|
||||||
|
background-position: -46px 0px;
|
||||||
|
}
|
|
@ -1,88 +0,0 @@
|
||||||
.text_add_image
|
|
||||||
{
|
|
||||||
position:absolute;
|
|
||||||
font-size:12px;
|
|
||||||
color: #2B587A;
|
|
||||||
text-align:center;
|
|
||||||
width: 100%;
|
|
||||||
left: 0px;
|
|
||||||
bottom:30px;
|
|
||||||
}
|
|
||||||
.text_add_image:hover
|
|
||||||
{
|
|
||||||
color:rgb(48, 41, 141);
|
|
||||||
}
|
|
||||||
.text_add_image, .avatarDelete img, .avatarDelete, .avatar_variants, .variant {
|
|
||||||
-webkit-transition: all 200ms ease-in-out;
|
|
||||||
-moz-transition: all 200ms ease-in-out;
|
|
||||||
-o-transition: all 200ms ease-in-out;
|
|
||||||
transition: all 200ms ease-in-out;
|
|
||||||
}
|
|
||||||
.avatarDelete
|
|
||||||
{
|
|
||||||
position:absolute;
|
|
||||||
right:0%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.75);
|
|
||||||
padding: 1px 0px 4px 3px;
|
|
||||||
border-radius: 0px 0px 0px 5px;
|
|
||||||
opacity:0;
|
|
||||||
cursor:pointer;
|
|
||||||
}
|
|
||||||
.avatarDelete img
|
|
||||||
{
|
|
||||||
width:77%;
|
|
||||||
opacity:60%;
|
|
||||||
vertical-align:middle;
|
|
||||||
}
|
|
||||||
.avatarDelete img:hover
|
|
||||||
{
|
|
||||||
opacity:100%
|
|
||||||
}
|
|
||||||
|
|
||||||
div.avatar_block:hover .avatarDelete
|
|
||||||
{
|
|
||||||
opacity:1 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.avatar_block:hover .avatar_variants
|
|
||||||
{
|
|
||||||
opacity:1 !important;
|
|
||||||
margin-bottom:1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar_variants
|
|
||||||
{
|
|
||||||
opacity:0;
|
|
||||||
position:absolute;
|
|
||||||
background-color: rgba(0, 0, 0, 0.75);
|
|
||||||
width:100%;
|
|
||||||
bottom:0;
|
|
||||||
margin-bottom:-8px;
|
|
||||||
color:white;
|
|
||||||
padding-top: 2px;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.variant
|
|
||||||
{
|
|
||||||
opacity:60%;
|
|
||||||
display:flex;
|
|
||||||
user-select:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.variant p
|
|
||||||
{
|
|
||||||
color:white;
|
|
||||||
margin-left: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.variant img
|
|
||||||
{
|
|
||||||
color:white;
|
|
||||||
margin-top: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.variant:hover
|
|
||||||
{
|
|
||||||
opacity:100%;
|
|
||||||
}
|
|
|
@ -97,16 +97,15 @@ h1 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 29px;
|
height: 29px;
|
||||||
padding: 11px 4px 0 7px;
|
padding: 11px 4px 0 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation .link, .header_navigation .header_divider_stick {
|
||||||
background: url('../img/divider.png') no-repeat;
|
background: url('../img/divider.png') no-repeat;
|
||||||
background-size: 1.5px 41px;
|
background-size: 1.5px 41px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_navigation .nodivider {
|
.page_header.search_expanded .header_navigation .header_divider_stick {
|
||||||
display: inline-block;
|
background: unset;
|
||||||
height: 29px;
|
|
||||||
padding: 11px 4px 0 7px;
|
|
||||||
background: none;
|
|
||||||
background-size: 1.5px 41px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_navigation .link a {
|
.header_navigation .link a {
|
||||||
|
@ -427,6 +426,22 @@ h1 {
|
||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action_links.disable>a,
|
||||||
|
.action_links.disable>form>input,
|
||||||
|
.action_links.disable {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action_links.loading::after {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
background-image: url('/assets/packages/static/openvk/img/loading_mini.gif');
|
||||||
|
width: 30px;
|
||||||
|
height: 7px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.profile_link.disable>a,
|
.profile_link.disable>a,
|
||||||
.profile_link.disable {
|
.profile_link.disable {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
|
@ -587,6 +602,11 @@ input[type=radio]:hover {
|
||||||
background-position: 0 -28px;
|
background-position: 0 -28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type=checkbox]:disabled {
|
||||||
|
background-position: 0 -28px;
|
||||||
|
cursor: initial;
|
||||||
|
}
|
||||||
|
|
||||||
input[type=checkbox]:checked,
|
input[type=checkbox]:checked,
|
||||||
input[type=radio]:checked {
|
input[type=radio]:checked {
|
||||||
background-position: 0 -14px;
|
background-position: 0 -14px;
|
||||||
|
@ -597,6 +617,10 @@ input[type=radio]:checked:hover {
|
||||||
background-position: 0 -42px;
|
background-position: 0 -42px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type=checkbox]:checked:disabled {
|
||||||
|
background-position: 0 -42px;
|
||||||
|
}
|
||||||
|
|
||||||
#auth {
|
#auth {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
@ -1827,6 +1851,10 @@ body.scrolled .toTop:hover {
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paginator.tidy {
|
||||||
|
float: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.paginator-at-bottom {
|
.paginator-at-bottom {
|
||||||
margin-top: -6px;
|
margin-top: -6px;
|
||||||
}
|
}
|
||||||
|
@ -1970,6 +1998,18 @@ body.scrolled .toTop:hover {
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.summaryBar.summaryBarFlex {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summaryBar.padding {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
height: 23px;
|
||||||
|
}
|
||||||
|
|
||||||
.summaryBar .summary {
|
.summaryBar .summary {
|
||||||
color: #45688E;
|
color: #45688E;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -2059,18 +2099,16 @@ table td[width="120"] {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb_tab div {
|
.mb_tab div, .mb_tab > a {
|
||||||
padding: 3px 7px;
|
padding: 5px 9px;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb_tab#active {
|
.mb_tab#active {
|
||||||
background-color: #898989;
|
background-color: #606060;
|
||||||
}
|
|
||||||
|
|
||||||
.mb_tab#active div {
|
|
||||||
border: 2px solid #5f5f5f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb_tab#active a {
|
.mb_tab#active a {
|
||||||
|
@ -2476,159 +2514,332 @@ a.poll-retract-vote {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchOptions {
|
/* Da search */
|
||||||
overflow: hidden;
|
|
||||||
width:25.5%;
|
/* Header part */
|
||||||
border-top:1px solid #E5E7E6;
|
|
||||||
float:right;
|
.header_navigation #search_box {
|
||||||
scrollbar-width: none;
|
display: inline-block;
|
||||||
font-size:12px;
|
height: 29px;
|
||||||
background-color:#f7f7f7;
|
padding: 11px 4px 0 7px;
|
||||||
margin-right: -7px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchBtn {
|
.header_navigation #search_box input[type='search'] {
|
||||||
|
height: 20px;
|
||||||
|
background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
padding-left: 18px;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box input[type='search']::-webkit-search-cancel-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box #search_box_fr form, .header_navigation #search_box #search_box_fr #search_and_one_more_wrapper {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box #searchBoxFastTips {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #d8d8d8;
|
||||||
|
border-top: unset;
|
||||||
|
margin-top: -1px;
|
||||||
|
box-shadow: 2px 3px 4px -1px rgba(34, 60, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box #searchBoxFastTips a {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box #searchBoxFastTips a b, .header_navigation #search_box #searchBoxFastTips a span {
|
||||||
|
display: block;
|
||||||
|
text-transform: initial;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box #searchBoxFastTips a:hover, .header_navigation #search_box #searchBoxFastTips a:focus {
|
||||||
|
background: #f3f3f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box #searchBoxFastTips a .search_tip_info_block {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box #searchBoxFastTips a img {
|
||||||
|
width: 33px;
|
||||||
|
height: 33px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_header.search_expanded .header_navigation #search_box #searchBoxFastTips.shown {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_header.search_expanded .link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_header.search_expanded #search_and_one_more_wrapper {
|
||||||
|
width: 627px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* не говновёрстка, а пиксель-пёрфект) */
|
||||||
|
.page_header.search_expanded.search_expanded_at_all #search_and_one_more_wrapper {
|
||||||
|
width: 547px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_header.search_expanded #search_box input[type='search'] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box select[name='section'], .header_navigation #search_box .search_box_button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_header.search_expanded select[name='section'] {
|
||||||
|
display: inline-block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_header.search_expanded_at_all .search_box_button {
|
||||||
|
display: inline-block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_header select[name='section'] {
|
||||||
|
width: auto;
|
||||||
|
height: 20px;
|
||||||
|
position: absolute;
|
||||||
|
padding: 0px 0px;
|
||||||
|
right: 0;
|
||||||
|
text-align: right;
|
||||||
|
border-left: 0px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box .search_box_button {
|
||||||
border: solid 1px #575757;
|
border: solid 1px #575757;
|
||||||
background-color: #696969;
|
background-color: #696969;
|
||||||
color:white;
|
color: #ffffff;
|
||||||
margin-left: -11px;
|
padding: 1px 0px 1px 0px;
|
||||||
padding-bottom:2px;
|
width: 80px;
|
||||||
width:80px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0px 2px 0px 0px rgba(255, 255, 255, 0.18) inset;
|
box-shadow: 0px 2px 0px 0px rgba(255, 255, 255, 0.18) inset;
|
||||||
margin-top: 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchBtn:active {
|
.header_navigation #search_box .search_box_button span {
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box .search_box_button:active {
|
||||||
border: solid 1px #666666;
|
border: solid 1px #666666;
|
||||||
background-color: #696969;
|
background-color: #696969;
|
||||||
color:white;
|
color:white;
|
||||||
box-shadow: 0px -2px 0px 0px rgba(255, 255, 255, 0.18) inset;
|
box-shadow: 0px -2px 0px 0px rgba(255, 255, 255, 0.18) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchList {
|
|
||||||
list-style: none;
|
|
||||||
user-select: none;
|
|
||||||
padding-left:0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchList #used {
|
|
||||||
margin-left:0px;
|
|
||||||
color: white !important;
|
|
||||||
padding:2px;
|
|
||||||
padding-top:5px;
|
|
||||||
padding-bottom:5px;
|
|
||||||
border: solid 0.125rem #4F4F4F;
|
|
||||||
background: #606060;
|
|
||||||
margin-bottom:2px;
|
|
||||||
padding-left:9px;
|
|
||||||
width:87%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchList #used a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sr:focus {
|
|
||||||
outline:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHide {
|
.searchHide {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchList li, .searchList a
|
/* Search layout */
|
||||||
{
|
#search_page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_content_paginator_bottom {
|
||||||
|
background: #f7f7f7;
|
||||||
|
border-top: 1px solid #d8d8d8;
|
||||||
|
padding: 8px 8px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content_main {
|
||||||
|
padding: 3px 3px;
|
||||||
|
width: 74%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content_main.audios_padding {
|
||||||
|
padding: 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content_main .def_row_content {
|
||||||
|
border-bottom: #ECECEC solid 1px;
|
||||||
|
padding: 3px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content_main .def_row_content:first-of-type {
|
||||||
|
padding: 0px 1px 3px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content_main .search_content:first-of-type .post {
|
||||||
|
border-top: unset;
|
||||||
|
padding-top: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content_main .search_content:last-of-type .post, .page_wrap_content_main .def_row_content:last-of-type {
|
||||||
|
border-bottom: unset;
|
||||||
|
padding-bottom: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verticalGrayTabsWrapper {
|
||||||
|
width: 158px;
|
||||||
|
border-top: 1px solid #E5E7E6;
|
||||||
|
border-left: 1px solid #d8d8d8;
|
||||||
|
scrollbar-width: none;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color:#f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchList, .verticalGrayTabs {
|
||||||
|
list-style: none;
|
||||||
|
user-select: none;
|
||||||
|
padding-left: 0px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchList hr, .verticalGrayTabs hr {
|
||||||
|
width: 153px;
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verticalGrayTabs.with_padding, .verticalGrayTabs > .with_padding {
|
||||||
|
padding: 4px 4px 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchList #used, .verticalGrayTabs #used {
|
||||||
|
color: #ffffff !important;
|
||||||
|
padding: 5px 9px 5px 9px;
|
||||||
|
border: solid 0.125rem #4F4F4F;
|
||||||
|
background: #606060;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchList #used a, .verticalGrayTabs #used a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchList li, .searchList a, .verticalGrayTabs a {
|
||||||
display: block;
|
display: block;
|
||||||
margin-left:0px;
|
font-size: 12px;
|
||||||
color: #2B587A !important;
|
color: #2B587A !important;
|
||||||
cursor:pointer;
|
cursor: pointer;
|
||||||
padding:2px;
|
padding: 5px 9px 5px 9px;
|
||||||
padding-top:5px;
|
|
||||||
padding-bottom:5px;
|
|
||||||
margin-bottom:2px;
|
|
||||||
padding-left:9px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchList li a {
|
.searchList a:hover, .verticalGrayTabs a:hover {
|
||||||
min-width:100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchList a {
|
|
||||||
min-width: 88%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchList a:hover {
|
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
color: #2B587A !important;
|
color: #2B587A !important;
|
||||||
background: #ebebeb;
|
background: #ebebeb;
|
||||||
padding: 2px;
|
|
||||||
padding-top: 5px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
padding-left: 9px;
|
|
||||||
width: 89.9%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.whatFind {
|
.highlight {
|
||||||
color:rgb(128, 128, 128);
|
background: #ffea6d;
|
||||||
background:none;
|
border-bottom: 1px solid #c7c727;
|
||||||
border:none;
|
font-weight: bolder;
|
||||||
position:absolute;
|
padding: 0px 1px;
|
||||||
width:150px;
|
|
||||||
cursor:pointer;
|
|
||||||
right:80px;
|
|
||||||
text-align:right;
|
|
||||||
margin-top: 0.5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchOptionName {
|
/* Options */
|
||||||
cursor:pointer;
|
|
||||||
background-color: #EAEAEA;
|
.page_wrap_content .page_search_options {
|
||||||
padding-left:5px;
|
padding: 0px 4px 4px 4px;
|
||||||
padding-top:5px;
|
|
||||||
padding-bottom:5px;
|
|
||||||
width: 90%;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #585858;
|
|
||||||
border-bottom: 2px solid #E4E4E4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchOption {
|
.page_wrap_content .page_search_options .search_option {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchOptionBlock
|
.page_wrap_content .page_search_options .search_option .search_option_name_ico {
|
||||||
{
|
width: 9px;
|
||||||
|
height: 8px;
|
||||||
|
display: inline-block;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background: url('/assets/packages/static/openvk/img/arrows.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content .page_search_options .search_option.search_option_hidden .search_option_name_ico {
|
||||||
|
background-position: -9px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content .page_search_options .search_option.search_option_hidden .search_option_content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content .page_search_options .search_option .search_option_name {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #EAEAEA;
|
||||||
|
padding: 5px 5px 5px 5px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #585858;
|
||||||
|
border-bottom: 2px solid #E4E4E4;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_wrap_content .page_search_options .search_option .search_option_content {
|
||||||
margin-top: -5px;
|
margin-top: -5px;
|
||||||
padding-top:10px;
|
padding-top: 10px;
|
||||||
max-width:92%;
|
padding-bottom: 6px;
|
||||||
padding-bottom:6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchOptionBlock select
|
.page_wrap_content .page_search_options .search_option .search_option_content label {
|
||||||
{
|
display: block;
|
||||||
padding-left:7px;
|
|
||||||
padding-top:3px;
|
|
||||||
padding-bottom:3px;
|
|
||||||
cursor:pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchOptionBlock input[type=text], input[type=date]
|
.page_wrap_content .page_search_options .search_option .search_option_content select {
|
||||||
{
|
padding-left: 3px;
|
||||||
margin-bottom:5px;
|
padding-top: 3px;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.borderup
|
.page_wrap_content .page_search_options #search_reset {
|
||||||
{
|
margin-top: 5px;
|
||||||
border-top:1px solid #E5E7E6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchInput
|
.page_wrap_content .page_search_options .search_option .search_option_content input[type=text], .page_wrap_content .page_search_options .search_option .search_option_content input[type=date] {
|
||||||
{
|
margin-bottom: 5px;
|
||||||
transition: .3s linear;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content_page_error {
|
||||||
|
background: white;
|
||||||
|
border: #DEDEDE solid 1px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_page_error span {
|
||||||
|
color: #707070;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Da search end. */
|
||||||
|
|
||||||
#standaloneCommentBox {
|
#standaloneCommentBox {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -2646,52 +2857,6 @@ a.poll-retract-vote {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchTips
|
|
||||||
{
|
|
||||||
position: absolute;
|
|
||||||
background: white;
|
|
||||||
padding-left: 6px;
|
|
||||||
padding-right: 6px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
border: 1px solid #C0CAD5;
|
|
||||||
border-top: 0px;
|
|
||||||
width: fit-content;
|
|
||||||
z-index: 666666;
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchTips td
|
|
||||||
{
|
|
||||||
color: black;
|
|
||||||
padding: 3px;
|
|
||||||
font-weight: lighter;
|
|
||||||
position:relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchTips td .desq
|
|
||||||
{
|
|
||||||
margin-top: -9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.restip td a:hover
|
|
||||||
{
|
|
||||||
color: black;
|
|
||||||
font-weight: lighter;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchTips .restip
|
|
||||||
{
|
|
||||||
padding-right: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchTips .restip:hover
|
|
||||||
{
|
|
||||||
background: rgb(236, 235, 235);
|
|
||||||
}
|
|
||||||
|
|
||||||
.attachment_note_icon {
|
.attachment_note_icon {
|
||||||
max-width: 9px;
|
max-width: 9px;
|
||||||
}
|
}
|
||||||
|
@ -3066,12 +3231,6 @@ hr {
|
||||||
height: 1px;
|
height: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchList hr {
|
|
||||||
width: 153px;
|
|
||||||
margin-left: 0px;
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.showMore, .showMoreAudiosPlaylist {
|
.showMore, .showMoreAudiosPlaylist {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -3089,3 +3248,54 @@ hr {
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
background-position: 50% !important;
|
background-position: 50% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entity_vertical_list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
height: 197px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity_vertical_list .entity_vertical_list_item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity_vertical_list .entity_vertical_list_item .first_column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity_vertical_list .entity_vertical_list_item .avatar {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity_vertical_list .entity_vertical_list_item img {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity_vertical_list .entity_vertical_list_item .info {
|
||||||
|
width: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity_vertical_list.mini .entity_vertical_list_item img {
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gif_loader {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
background-image: url('/assets/packages/static/openvk/img/loading_mini.gif');
|
||||||
|
width: 30px;
|
||||||
|
height: 7px;
|
||||||
|
}
|
||||||
|
|
72
Web/static/img/app_icons_mini/wphone.svg
Normal file
72
Web/static/img/app_icons_mini/wphone.svg
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
id="windowskey"
|
||||||
|
version="1.1"
|
||||||
|
width="13"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 13 12"
|
||||||
|
sodipodi:docname="wphone.svg"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs79" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview77"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="45.254834"
|
||||||
|
inkscape:cx="4.6514368"
|
||||||
|
inkscape:cy="5.0381358"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1009"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="windowskey" />
|
||||||
|
<g
|
||||||
|
id="g26"
|
||||||
|
transform="matrix(1.1345617,0,0,1.1369577,0.2820346,-0.32489569)"
|
||||||
|
style="stroke:none;fill:#b1bfcd;fill-opacity:1">
|
||||||
|
<path
|
||||||
|
id="rbyll"
|
||||||
|
d="M 10.7,5.95 V 10.8 L 5.13,9.93 V 5.94 Z"
|
||||||
|
style="fill:#b1bfcd;stroke-width:0;stroke:none;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="rtgrn"
|
||||||
|
d="M 5.13,1.13 10.7,0.326 V 5.1 H 5.13 Z"
|
||||||
|
style="fill:#b1bfcd;stroke-width:0;stroke:none;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="lbblu"
|
||||||
|
d="M 4.39,5.91 V 9.86 L 0.264,9.29 v -3.4 z"
|
||||||
|
style="fill:#b1bfcd;stroke-width:0;stroke:none;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="ltred"
|
||||||
|
d="M 0.261,1.77 4.39,1.2 V 5.15 H 0.263 Z"
|
||||||
|
style="fill:#b1bfcd;stroke-width:0;stroke:none;fill-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style="fill:#b1bfcd;stroke-width:0.019;stroke-dasharray:none;stroke:none;fill-opacity:1"
|
||||||
|
d="M 0.59279246,5.1581071 C 0.58639332,4.9590688 0.58035022,4.0999853 0.57936334,3.2490325 l -0.001794,-1.5471867 0.0538026,-0.010946 C 0.66096303,1.6848789 1.0412718,1.6310397 1.4765021,1.5712567 1.9117325,1.5114737 2.93877,1.3697978 3.7588077,1.2564213 L 5.2497853,1.0502822 V 3.2851385 5.5199949 H 2.9271062 0.60442726 Z"
|
||||||
|
id="path277" />
|
||||||
|
<path
|
||||||
|
style="fill:#b1bfcd;stroke-width:0.019;stroke-dasharray:none;stroke:none;fill-opacity:1"
|
||||||
|
d="m 6.118316,3.2135634 c 0,-1.2366911 0.00303,-2.24852933 0.00672,-2.24852933 0.0037,0 0.4575049,-0.0654202 1.0084606,-0.14537825 0.5509557,-0.079958 1.422975,-0.2061814 1.9378206,-0.2804964 0.5148457,-0.074315 1.4729638,-0.2129995 2.1291498,-0.30818778 0.656188,-0.0951883 1.196848,-0.1730696 1.201468,-0.1730696 0.0046,0 0.0084,1.21594296 0.0084,2.70209536 V 5.4620928 H 9.2643271 6.118316 Z"
|
||||||
|
id="path279" />
|
||||||
|
<path
|
||||||
|
style="fill:#b1bfcd;stroke-width:0;stroke-dasharray:none;stroke:none;fill-opacity:1"
|
||||||
|
d="M 11.802367,11.85061 C 11.483905,11.79947 10.658801,11.669367 9.9688019,11.561492 9.2788026,11.453616 8.1371252,11.274777 7.4317409,11.164071 6.7263567,11.053365 6.1422699,10.962787 6.1337701,10.962787 c -0.0085,0 -0.015454,-1.0161809 -0.015454,-2.2581797 V 6.4464276 h 3.1460111 3.1460108 v 2.7503471 c 0,1.5126913 -0.0065,2.7495523 -0.01447,2.7485813 -0.008,-9.71e-4 -0.275035,-0.04361 -0.593496,-0.09475 z"
|
||||||
|
id="path281" />
|
||||||
|
<path
|
||||||
|
style="fill:#b1bfcd;stroke-width:0.019;stroke-dasharray:none;stroke:none;fill-opacity:1"
|
||||||
|
d="M 4.8830724,10.826259 C 4.5998231,10.784852 3.2581997,10.598446 1.7756627,10.394512 1.1971248,10.31493 0.6955483,10.244822 0.66104834,10.238715 l -0.0627272,-0.0111 V 8.3080688 6.3885255 L 2.0989491,6.38855 c 0.8253454,1.36e-5 1.8719248,0.00577 2.3257321,0.012793 l 0.8251041,0.012769 v 2.2260859 2.2260861 l -0.062727,-0.0024 c -0.0345,-0.0013 -0.1712935,-0.01825 -0.3039857,-0.03765 z"
|
||||||
|
id="path283" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
BIN
Web/static/img/arrows.png
Normal file
BIN
Web/static/img/arrows.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 219 B |
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 263 B |
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue