Compare commits

...

73 commits

Author SHA1 Message Date
koke228666
c63579ac6e
Merge 225f031cfc into b90a0fa013 2025-06-02 01:21:29 +03:00
mr❤️🤢
b90a0fa013
fix(photo upload): fix own page upload error (#1336) 2025-06-01 15:02:00 +00:00
ZAZiOs
dd19163e27
feat(graffiti: CtrlZ): Added script for basic keyboard support in graffiti (#1314)
Добавил поддержку CTRL+Z для отмены действия и CTRL+SHIFT+Z или CTRL+Y
для повтора действия в редакторе граффити.
2025-06-01 17:06:32 +03:00
mrilyew
0649a75d56 feat(account.saveProfileInfo): add "telegram" 2025-06-01 17:04:44 +03:00
mrilyew
003350beaf fix: contacts field that duplicated to each item 2025-06-01 17:04:44 +03:00
mrilyew
782046349a fix(saveProfileInfo): fix value overflow 2025-06-01 17:04:44 +03:00
mrilyew
911e03980c feat(doc picker): add margin before upload button 2025-06-01 17:04:44 +03:00
mrilyew
8d734ae528 fix(repost window): change margins 2025-06-01 17:04:44 +03:00
mrilyew
0be8514619 fix(nospam): attempt to fix club rollback 2025-06-01 17:04:44 +03:00
mrilyew
99176789ae fix(scrolling): wrong scrolling that causes dups 2025-06-01 17:04:44 +03:00
mrilyew
808d622061 fix(photo upload): unhardcode size and make redir 2025-06-01 17:04:44 +03:00
mrilyew
5d1d39a527 fix(/album{num}/remove_photo/{num}): wrong wording 2025-06-01 17:04:44 +03:00
mrilyew
878df31084 fix(photos): don't check rights of deleted album 2025-06-01 17:04:44 +03:00
mrilyew
1a03a31dfa fix: revert previous 2025-06-01 17:04:44 +03:00
mrilyew
00ca8d65d0 fix: hide anon gift name 2025-06-01 17:04:44 +03:00
mrilyew
b85e74a3d8 feat: "sent" at gifts page 2025-06-01 17:04:44 +03:00
mrilyew
40b19ec561 feat: ajloader styles change 2025-06-01 17:04:44 +03:00
mrilyew
31bd11cae8 feat(topic create) delete deprec. js 2025-06-01 17:04:44 +03:00
mrilyew
4693d2f92d feat(topic edit): label for checkboxes 2025-06-01 17:04:44 +03:00
mrilyew
7e65f25d7b fix: hide reply button at closed topic 2025-06-01 17:04:44 +03:00
mrilyew
53115cb946 fix: undefined fields 2025-06-01 17:04:44 +03:00
mrilyew
6e87ac3e38 feat(wall.delete): explain condition 2025-06-01 17:04:44 +03:00
mrilyew
686ce928dd feat: add focus on status edit 2025-06-01 17:04:44 +03:00
mrilyew
c858a119d1 fix(albums): "you have" on same id 2025-06-01 17:04:44 +03:00
mrilyew
a2ac608936 fix(albums): "my photos" on same id 2025-06-01 17:04:44 +03:00
mrilyew
aedbfe364e fix(picker): albums select 2025-06-01 17:04:44 +03:00
mrilyew
a906e27f19 fix: not add photo to album if wrong 2025-06-01 17:04:44 +03:00
mrilyew
ca309aa14e feat: provide id on upload context 2025-06-01 17:04:44 +03:00
mrilyew
da6e90b777 feat: playlist cover is unlisted 2025-06-01 17:04:44 +03:00
mrilyew
0771fbabd3 fix: theme id != "mobile_ovk" 2025-06-01 17:04:44 +03:00
mrilyew
fda9ff415b fix: space between types 2025-06-01 17:04:44 +03:00
mrilyew
c7bcd1c36e feat: showArticle() css changes 2025-06-01 17:04:44 +03:00
mrilyew
126e5e2c1b feat: warning on post delete button 2025-06-01 17:04:44 +03:00
mrilyew
16700ad304 feat: tickets text length to 200 2025-06-01 17:04:44 +03:00
mrilyew
1424ca2708 fix: audio playing on report page 2025-06-01 17:04:44 +03:00
mrilyew
8d01f9b0f3 feat(comms): warning before deletion 2025-06-01 17:04:44 +03:00
mrilyew
e7faa45050 feat: video not unlisted af. editing 2025-06-01 17:04:44 +03:00
mrilyew
b63d2c24bd feat: autostart gif 2025-06-01 17:04:44 +03:00
mrilyew
33f44eb19e fix: careless topic deletion 2025-06-01 17:04:44 +03:00
mrilyew
8f9a303ce9 fix: wrong comments when editing 2025-06-01 17:04:44 +03:00
mrilyew
3727e4cd40 feat: make doc width 60% 2025-06-01 17:04:44 +03:00
mrilyew
f843132d5e fix: router recursion 2025-06-01 17:04:44 +03:00
mrilyew
626770ef0c feat: add comments sort 2025-06-01 17:04:44 +03:00
mrilyew
dce143a48e fix: infinty scroll for high screens 2025-06-01 17:04:44 +03:00
mrilyew
1af6cd83e4 fix: followers scroll 2025-06-01 17:04:44 +03:00
mrilyew
bf87ab9858 fix: add warning at nospam 2025-06-01 17:04:44 +03:00
mrilyew
1d1eae3da2 feat: count of comments on microblog 2025-06-01 17:04:44 +03:00
mrilyew
3c6ce6e22f fix: add margin at post page 2025-06-01 17:04:44 +03:00
mrilyew
352cfa9831 feat: enlarge graffiti 2025-06-01 17:04:44 +03:00
mrilyew
54f40a7296 fix: source window paddings 2025-06-01 17:04:44 +03:00
mrilyew
930ef8add2 fix: textarea paddings 2025-06-01 17:04:44 +03:00
mrilyew
e1cbffc10e fix: notes picker 2025-06-01 17:04:44 +03:00
mrilyew
1552483dbe fix: 500 on followers page 2025-06-01 17:04:44 +03:00
mrilyew
f542651a56 fix: ajax on tickets 2025-06-01 17:04:44 +03:00
mrilyew
6b583a2870 fix: blacklist paddings 2025-06-01 17:04:44 +03:00
mrilyew
7f33389277 fix(scroll): don't set hash 2025-06-01 17:04:44 +03:00
mrilyew
5a41f3b1b3 fix(api): simplification 2025-06-01 17:04:44 +03:00
mrilyew
a16734648c feat: skip theme styles 2025-06-01 17:04:44 +03:00
mrilyew
fa7681edb8 fix: wrong i18n xhtml text 2025-06-01 17:04:44 +03:00
mrilyew
7e22964c2e fix: wide avatars at tips 2025-06-01 17:04:44 +03:00
mrilyew
a64b903f15 fix: don't show age of dead 2025-06-01 17:04:44 +03:00
mrilyew
401b417d67 fix: typo in privacy 2025-06-01 17:04:44 +03:00
mrilyew
ba8b12f81d feat: add link to audiostatus 2025-06-01 17:04:44 +03:00
mrilyew
d9cd394547 feat: auto set "from group" 2025-06-01 17:04:44 +03:00
mrilyew
89f724587f fix(picker): invalid album 2025-06-01 17:04:44 +03:00
mrilyew
58b2d8ece5 fix: move all apps to search 2025-06-01 17:04:44 +03:00
mrilyew
1cacf6a8b5 feat(docs): ux changes 2025-06-01 17:04:44 +03:00
mrilyew
7c887e9f9c fix(docs): set correct margins 2025-06-01 17:04:44 +03:00
mrilyew
7bf7050cdc feat(tips): add delay 2025-06-01 17:04:44 +03:00
mrilyew
cf09251a90 feat(ajax): show loading cursor 2025-06-01 17:04:44 +03:00
mrilyew
6a882aeeb4 feat(wall): remove hidePanel() 2025-06-01 17:04:44 +03:00
mrilyew
b2d389a7b8 fix(video api): fix items bug 2025-06-01 17:04:44 +03:00
koke228666
225f031cfc /dev 2025-05-22 16:34:05 +03:00
80 changed files with 1661 additions and 678 deletions

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace openvk\VKAPI\Handlers;
use openvk\Web\Models\Exceptions\InvalidUserNameException;
use openvk\Web\Util\Validator;
final class Account extends VKAPIRequestHandler
{
@ -95,7 +96,7 @@ final class Account extends VKAPIRequestHandler
# TODO: Filter
}
public function saveProfileInfo(string $first_name = "", string $last_name = "", string $screen_name = "", int $sex = -1, int $relation = -1, string $bdate = "", int $bdate_visibility = -1, string $home_town = "", string $status = ""): object
public function saveProfileInfo(string $first_name = "", string $last_name = "", string $screen_name = "", int $sex = -1, int $relation = -1, string $bdate = "", int $bdate_visibility = -1, string $home_town = "", string $status = "", string $telegram = null): object
{
$this->requireUser();
$this->willExecuteWriteAction();
@ -138,13 +139,13 @@ final class Account extends VKAPIRequestHandler
$user->setSex($sex == 1 ? 1 : 0);
}
if ($relation > -1) {
if ($relation > -1 && $relation <= 8) {
$user->setMarital_Status($relation);
}
if (!empty($bdate)) {
$birthday = strtotime($bdate);
if (!is_int($birthday)) {
if (!is_int($birthday) || $birthday > time()) {
$this->fail(100, "invalid value of bdate.");
}
@ -171,9 +172,26 @@ final class Account extends VKAPIRequestHandler
$user->setStatus($status);
}
if ($sex > 0 || $relation > -1 || $bdate_visibility > 1 || !empty("$first_name$last_name$screen_name$bdate$home_town$status")) {
if (!is_null($telegram)) {
if (empty($telegram)) {
$user->setTelegram(null);
} elseif (Validator::i()->telegramValid($telegram)) {
if (strpos($telegram, "t.me/") === 0) {
$user->setTelegram($telegram);
} else {
$user->setTelegram(ltrim($telegram, "@"));
}
}
}
if ($sex > 0 || $relation > -1 || $bdate_visibility > 1 || !is_null($telegram) || !empty("$first_name$last_name$screen_name$bdate$home_town$status")) {
$output["changed"] = 1;
$user->save();
try {
$user->save();
} catch (\TypeError $e) {
$output["changed"] = 0;
}
}
return (object) $output;
@ -183,7 +201,7 @@ final class Account extends VKAPIRequestHandler
{
$this->requireUser();
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");
}
return (object) ['votes' => $this->getUser()->getCoins()];

View file

@ -14,7 +14,7 @@ use openvk\Web\Models\Entities\{Topic, Comment, User, Photo, Video};
final class Board extends VKAPIRequestHandler
{
public function addTopic(int $group_id, string $title, string $text = "", bool $from_group = true)
public function addTopic(int $group_id, string $title, string $text = null, bool $from_group = true)
{
$this->requireUser();
$this->willExecuteWriteAction();
@ -30,6 +30,7 @@ final class Board extends VKAPIRequestHandler
}
$flags = 0;
if ($from_group == true && $club->canBeModifiedBy($this->getUser())) {
$flags |= 0b10000000;
}
@ -40,17 +41,23 @@ final class Board extends VKAPIRequestHandler
$topic->setTitle(ovk_proc_strtr($title, 127));
$topic->setCreated(time());
$topic->setFlags($flags);
$topic->save();
if (!empty($text)) {
$comment = new Comment();
$comment->setOwner($this->getUser()->getId());
$comment->setModel(get_class($topic));
$comment->setTarget($topic->getId());
$comment->setContent($text);
$comment->setCreated(time());
$comment->setFlags($flags);
$comment->save();
try {
if (!empty($text)) {
$comment = new Comment();
$comment->setOwner($this->getUser()->getId());
$comment->setModel(get_class($topic));
$comment->setTarget($topic->getId());
$comment->setContent($text);
$comment->setCreated(time());
$comment->setFlags($flags);
$comment->save();
}
} catch (\Throwable $e) {
return $topic->getId();
}
return $topic->getId();
@ -75,32 +82,35 @@ final class Board extends VKAPIRequestHandler
return 1;
}
public function createComment(int $group_id, int $topic_id, string $message = "", string $attachments = "", bool $from_group = true)
public function createComment(int $group_id, int $topic_id, string $message = "", bool $from_group = true)
{
$this->requireUser();
$this->willExecuteWriteAction();
if (empty($message) && empty($attachments)) {
if (empty($message)) {
$this->fail(100, "Required parameter 'message' missing.");
}
$topic = (new TopicsRepo())->getTopicById($group_id, $topic_id);
if (!$topic || $topic->isDeleted() || $topic->isClosed()) {
$this->fail(15, "Access denied");
}
$flags = 0;
if ($from_group != 0 && !is_null($topic->getClub()) && $topic->getClub()->canBeModifiedBy($this->user)) {
if ($from_group != 0 && ($topic->getClub()->canBeModifiedBy($this->user))) {
$flags |= 0b10000000;
}
$comment = new Comment();
$comment->setOwner($this->getUser()->getId());
$comment->setModel(get_class($topic));
$comment->setTarget($topic->getId());
$comment->setContent($message);
$comment->setCreated(time());
$comment->setFlags($flags);
$comment->save();
return $comment->getId();
@ -113,7 +123,7 @@ final class Board extends VKAPIRequestHandler
$topic = (new TopicsRepo())->getTopicById($group_id, $topic_id);
if (!$topic || !$topic->getClub() || $topic->isDeleted() || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
if (!$topic || $topic->isDeleted() || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
return 0;
}
@ -129,7 +139,7 @@ final class Board extends VKAPIRequestHandler
$topic = (new TopicsRepo())->getTopicById($group_id, $topic_id);
if (!$topic || !$topic->getClub() || $topic->isDeleted() || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
if (!$topic || $topic->isDeleted() || !$topic->canBeModifiedBy($this->getUser())) {
return 0;
}
@ -147,7 +157,7 @@ final class Board extends VKAPIRequestHandler
$topic = (new TopicsRepo())->getTopicById($group_id, $topic_id);
if (!$topic || !$topic->getClub() || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
if (!$topic || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
return 0;
}
@ -158,75 +168,92 @@ final class Board extends VKAPIRequestHandler
return 1;
}
public function getComments(int $group_id, int $topic_id, bool $need_likes = false, int $start_comment_id = 0, int $offset = 0, int $count = 40, bool $extended = false, string $sort = "asc")
public function getComments(int $group_id, int $topic_id, bool $need_likes = false, int $offset = 0, int $count = 10, bool $extended = false)
{
# start_comment_id ne robit
$this->requireUser();
if ($count < 1 || $count > 100) {
$this->fail(4, "Invalid count");
}
$topic = (new TopicsRepo())->getTopicById($group_id, $topic_id);
if (!$topic || !$topic->getClub() || $topic->isDeleted()) {
$this->fail(5, "Invalid topic");
if (!$topic || $topic->isDeleted()) {
$this->fail(5, "Not found");
}
$arr = [
$obj = (object) [
"items" => [],
];
$comms = array_slice(iterator_to_array($topic->getComments(1, $count + $offset)), $offset);
foreach ($comms as $comm) {
$arr["items"][] = $this->getApiBoardComment($comm, $need_likes);
if ($extended) {
$obj->profiles = [];
$obj->groups = [];
}
$comments = array_slice(iterator_to_array($topic->getComments(1, $count + $offset)), $offset);
foreach ($comments as $comment) {
$obj->items[] = $comment->toVkApiStruct($this->getUser(), $need_likes);
if ($extended) {
if ($comm->getOwner() instanceof \openvk\Web\Models\Entities\User) {
$arr["profiles"][] = $comm->getOwner()->toVkApiStruct();
$owner = $comment->getOwner();
if ($owner instanceof \openvk\Web\Models\Entities\User) {
$obj->profiles[] = $owner->toVkApiStruct();
}
if ($comm->getOwner() instanceof \openvk\Web\Models\Entities\Club) {
$arr["groups"][] = $comm->getOwner()->toVkApiStruct();
if ($owner instanceof \openvk\Web\Models\Entities\Club) {
$obj->groups[] = $owner->toVkApiStruct();
}
}
}
return $arr;
return $obj;
}
public function getTopics(int $group_id, string $topic_ids = "", int $order = 1, int $offset = 0, int $count = 40, bool $extended = false, int $preview = 0, int $preview_length = 90)
public function getTopics(int $group_id, string $topic_ids = "", int $offset = 0, int $count = 10, bool $extended = false, int $preview = 0, int $preview_length = 90)
{
# order и extended ничё не делают
# TODO: $extended
$this->requireUser();
$arr = [];
if ($count < 1 || $count > 100) {
$this->fail(4, "Invalid count");
}
$obj = (object) [];
$club = (new ClubsRepo())->get($group_id);
if (!$club || !$club->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access denied");
}
$topics = array_slice(iterator_to_array((new TopicsRepo())->getClubTopics($club, 1, $count + $offset)), $offset);
$arr["count"] = (new TopicsRepo())->getClubTopicsCount($club);
$arr["items"] = [];
$arr["default_order"] = $order;
$arr["can_add_topics"] = $club->canBeModifiedBy($this->getUser()) ? true : ($club->isEveryoneCanCreateTopics() ? true : false);
$arr["profiles"] = [];
$obj->count = (new TopicsRepo())->getClubTopicsCount($club);
$obj->items = [];
$obj->profiles = [];
$obj->can_add_topics = $club->canBeModifiedBy($this->getUser()) ? true : ($club->isEveryoneCanCreateTopics() ? true : false);
if (empty($topic_ids)) {
foreach ($topics as $topic) {
if ($topic->isDeleted()) {
continue;
}
$arr["items"][] = $topic->toVkApiStruct($preview, $preview_length > 1 ? $preview_length : 90);
$obj->items[] = $topic->toVkApiStruct($preview, $preview_length > 1 ? $preview_length : 90);
}
} else {
$topics = explode(',', $topic_ids);
foreach ($topics as $topic) {
$id = explode("_", $topic);
$topicy = (new TopicsRepo())->getTopicById((int) $id[0], (int) $id[1]);
foreach ($topics as $topic_id) {
$topic = (new TopicsRepo())->getTopicById($group_id, (int) $topic_id);
if ($topicy && !$topicy->isDeleted()) {
$arr["items"][] = $topicy->toVkApiStruct($preview, $preview_length > 1 ? $preview_length : 90);
if ($topic && !$topic->isDeleted()) {
$obj->items[] = $topic->toVkApiStruct($preview, $preview_length > 1 ? $preview_length : 90);
}
}
}
return $arr;
return $obj;
}
public function openTopic(int $group_id, int $topic_id)
@ -236,7 +263,7 @@ final class Board extends VKAPIRequestHandler
$topic = (new TopicsRepo())->getTopicById($group_id, $topic_id);
if (!$topic || !$topic->getClub() || !$topic->isDeleted() || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
if (!$topic || !$topic->isDeleted() || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
return 0;
}
@ -248,11 +275,6 @@ final class Board extends VKAPIRequestHandler
return 1;
}
public function restoreComment(int $group_id, int $topic_id, int $comment_id)
{
$this->fail(501, "Not implemented");
}
public function unfixTopic(int $group_id, int $topic_id)
{
$this->requireUser();
@ -260,7 +282,7 @@ final class Board extends VKAPIRequestHandler
$topic = (new TopicsRepo())->getTopicById($group_id, $topic_id);
if (!$topic || !$topic->getClub() || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
if (!$topic || !$topic->getClub()->canBeModifiedBy($this->getUser())) {
return 0;
}
@ -275,33 +297,4 @@ final class Board extends VKAPIRequestHandler
return 1;
}
private function getApiBoardComment(?Comment $comment, bool $need_likes = false)
{
$res = (object) [];
$res->id = $comment->getId();
$res->from_id = $comment->getOwner()->getId();
$res->date = $comment->getPublicationTime()->timestamp();
$res->text = $comment->getText(false);
$res->attachments = [];
$res->likes = [];
if ($need_likes) {
$res->likes = [
"count" => $comment->getLikesCount(),
"user_likes" => (int) $comment->hasLikeFrom($this->getUser()),
"can_like" => 1, # а чё типо не может ахахаххахах
];
}
foreach ($comment->getChildren() as $attachment) {
if ($attachment->isDeleted()) {
continue;
}
$res->attachments[] = $attachment->toVkApiStruct();
}
return $res;
}
}

View file

@ -10,62 +10,43 @@ use openvk\Web\Models\Entities\Notifications\GiftNotification;
final class Gifts extends VKAPIRequestHandler
{
public function get(int $user_id = null, int $count = 10, int $offset = 0)
public function get(int $user_id = 0, int $count = 10, int $offset = 0)
{
# There is no extended :)
$this->requireUser();
$i = 0;
$i += $offset;
$server_url = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
if ($user_id) {
$user = (new UsersRepo())->get($user_id);
} else {
$user = $this->getUser();
if ($user_id < 1) {
$user_id = $this->getUser()->getId();
}
$user = (new UsersRepo())->get($user_id);
if (!$user || $user->isDeleted()) {
$this->fail(177, "Invalid user");
}
if (!$user->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access denied");
}
/*
if(!$user->getPrivacyPermission('gifts.read', $this->getUser()))
$this->fail(15, "Access denied: this user chose to hide his gifts");*/
if (!$user->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access denied");
}
$gift_item = [];
$user_gifts = array_slice(iterator_to_array($user->getGifts(1, $count)), $offset, $count);
$userGifts = array_slice(iterator_to_array($user->getGifts(1, $count, false)), $offset);
if (sizeof($userGifts) < 0) {
return null;
}
foreach ($userGifts as $gift) {
if ($i < $count) {
$gift_item[] = [
"id" => $i,
"from_id" => $gift->anon == true ? 0 : $gift->sender->getId(),
"message" => $gift->caption == null ? "" : $gift->caption,
"date" => $gift->sent->timestamp(),
"gift" => [
"id" => $gift->gift->getId(),
"thumb_256" => $server_url . $gift->gift->getImage(2),
"thumb_96" => $server_url . $gift->gift->getImage(2),
"thumb_48" => $server_url . $gift->gift->getImage(2),
],
"privacy" => 0,
];
}
$i += 1;
foreach ($user_gifts as $gift) {
$gift_item[] = [
"from_id" => $gift->anon == true ? 0 : $gift->sender->getId(),
"message" => $gift->caption == null ? "" : $gift->caption,
"date" => $gift->sent->timestamp(),
"gift" => [
"id" => $gift->gift->getId(),
"thumb_256" => $server_url . $gift->gift->getImage(2),
"thumb_96" => $server_url . $gift->gift->getImage(2),
"thumb_48" => $server_url . $gift->gift->getImage(2),
],
];
}
return $gift_item;
@ -76,14 +57,14 @@ final class Gifts extends VKAPIRequestHandler
$this->requireUser();
$this->willExecuteWriteAction();
$user = (new UsersRepo())->get((int) $user_ids);
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");
}
$user = (new UsersRepo())->get((int) $user_ids); # FAKE прогноз погоды (в данном случае user_ids)
if (!$user || $user->isDeleted()) {
$this->fail(177, "Invalid user");
$this->fail(15, "Access denied");
}
if (!$user->canBeViewedBy($this->getUser())) {
@ -93,7 +74,7 @@ final class Gifts extends VKAPIRequestHandler
$gift = (new GiftsRepo())->get($gift_id);
if (!$gift) {
$this->fail(165, "Invalid gift");
$this->fail(15, "Invalid gift");
}
$price = $gift->getPrice();
@ -134,24 +115,17 @@ final class Gifts extends VKAPIRequestHandler
];
}
public function delete()
{
$this->requireUser();
$this->willExecuteWriteAction();
$this->fail(501, "Not implemented");
}
# в vk кстати называется gifts.getCatalog
public function getCategories(bool $extended = false, int $page = 1)
{
$this->requireUser();
$cats = (new GiftsRepo())->getCategories($page);
$categ = [];
$i = 0;
$server_url = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
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");
}
foreach ($cats as $cat) {
@ -184,17 +158,19 @@ final class Gifts extends VKAPIRequestHandler
$this->requireUser();
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");
}
if (!(new GiftsRepo())->getCat($id)) {
$this->fail(177, "Category not found");
$gift_category = (new GiftsRepo())->getCat($id);
if (!$gift_category) {
$this->fail(15, "Category not found");
}
$giftz = ((new GiftsRepo())->getCat($id))->getGifts($page);
$gifts_list = $gift_category->getGifts($page);
$gifts = [];
foreach ($giftz as $gift) {
foreach ($gifts_list as $gift) {
$gifts[] = [
"name" => $gift->getName(),
"image" => $gift->getImage(2),

View file

@ -107,7 +107,6 @@ final class Groups extends VKAPIRequestHandler
$backgrounds = $usr->getBackDropPictureURLs();
$rClubs[$i]->background = $backgrounds;
break;
# unstandard feild
case "suggested_count":
if ($usr->getWallType() != 2) {
$rClubs[$i]->suggested_count = null;
@ -246,7 +245,7 @@ final class Groups extends VKAPIRequestHandler
$response[$i]->suggested_count = $clb->getSuggestedPostsCount($this->getUser());
break;
case "contacts":
$contacts;
$contacts = [];
$contactTmp = $clb->getManagers(1, true);
foreach ($contactTmp as $contact) {
@ -335,23 +334,6 @@ final class Groups extends VKAPIRequestHandler
return 1;
}
public function create(string $title, string $description = "", string $type = "group", int $public_category = 1, int $public_subcategory = 1, int $subtype = 1)
{
$this->requireUser();
$this->willExecuteWriteAction();
$club = new Club();
$club->setName($title);
$club->setAbout($description);
$club->setOwner($this->getUser()->getId());
$club->save();
$club->toggleSubscription($this->getUser());
return $this->getById((string) $club->getId());
}
public function edit(
int $group_id,
string $title = null,
@ -371,13 +353,15 @@ final class Groups extends VKAPIRequestHandler
$club = (new ClubsRepo())->get($group_id);
if (!$club) {
$this->fail(203, "Club not found");
$this->fail(15, "Access denied");
}
if (!$club || !$club->canBeModifiedBy($this->getUser())) {
$this->fail(15, "You can't modify this group.");
$this->fail(15, "Access denied");
}
if (!empty($screen_name) && !$club->setShortcode($screen_name)) {
$this->fail(103, "Invalid shortcode.");
$this->fail(103, "Invalid screen_name");
}
!empty($title) ? $club->setName($title) : null;
@ -404,260 +388,86 @@ final class Groups extends VKAPIRequestHandler
try {
$club->save();
} catch (\TypeError $e) {
$this->fail(15, "Nothing changed");
return 1;
} catch (\Exception $e) {
$this->fail(18, "An unknown error occurred: maybe you set an incorrect value?");
return 0;
}
return 1;
}
public function getMembers(string $group_id, string $sort = "id_asc", int $offset = 0, int $count = 100, string $fields = "", string $filter = "any")
public function getMembers(int $group_id, int $offset = 0, int $count = 10, string $fields = "")
{
# bdate,can_post,can_see_all_posts,can_see_audio,can_write_private_message,city,common_count,connections,contacts,country,domain,education,has_mobile,last_seen,lists,online,online_mobile,photo_100,photo_200,photo_200_orig,photo_400_orig,photo_50,photo_max,photo_max_orig,relation,relatives,schools,sex,site,status,universities
$club = (new ClubsRepo())->get((int) $group_id);
if (!$club) {
$this->fail(125, "Invalid group id");
$this->requireUser();
$club = (new ClubsRepo())->get($group_id);
if (!$club || !$club->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access denied");
}
$sorter = "follower ASC";
$sort_string = "follower ASC";
$members = array_slice(iterator_to_array($club->getFollowers(1, $count, $sort_string)), $offset, $count);
switch ($sort) {
default:
case "time_asc":
case "id_asc":
$sorter = "follower ASC";
break;
case "time_desc":
case "id_desc":
$sorter = "follower DESC";
break;
}
$obj = (object) [
"count" => sizeof($members),
"items" => [],
];
$members = array_slice(iterator_to_array($club->getFollowers(1, $count, $sorter)), $offset);
$arr = (object) [
"count" => count($members),
"items" => []];
$filds = explode(",", $fields);
$i = 0;
foreach ($members as $member) {
if ($i > $count) {
break;
}
$arr->items[] = (object) [
"id" => $member->getId(),
"first_name" => $member->getFirstName(),
"last_name" => $member->getLastName(),
];
foreach ($filds as $fild) {
$canView = $member->canBeViewedBy($this->getUser());
switch ($fild) {
case "bdate":
if (!$canView) {
$arr->items[$i]->bdate = "01.01.1970";
break;
}
$arr->items[$i]->bdate = $member->getBirthday() ? $member->getBirthday()->format('%e.%m.%Y') : null;
break;
case "can_post":
$arr->items[$i]->can_post = $club->canBeModifiedBy($member);
break;
case "can_see_all_posts":
$arr->items[$i]->can_see_all_posts = 1;
break;
case "can_see_audio":
$arr->items[$i]->can_see_audio = 1;
break;
case "can_write_private_message":
$arr->items[$i]->can_write_private_message = 0;
break;
case "common_count":
$arr->items[$i]->common_count = 420;
break;
case "connections":
$arr->items[$i]->connections = 1;
break;
case "contacts":
if (!$canView) {
$arr->items[$i]->contacts = "secret@gmail.com";
break;
}
$arr->items[$i]->contacts = $member->getContactEmail();
break;
case "country":
$arr->items[$i]->country = 1;
break;
case "domain":
$arr->items[$i]->domain = "";
break;
case "education":
$arr->items[$i]->education = "";
break;
case "has_mobile":
$arr->items[$i]->has_mobile = false;
break;
case "last_seen":
if (!$canView) {
$arr->items[$i]->last_seen = 0;
break;
}
$arr->items[$i]->last_seen = $member->getOnline()->timestamp();
break;
case "lists":
$arr->items[$i]->lists = "";
break;
case "online":
if (!$canView) {
$arr->items[$i]->online = false;
break;
}
$arr->items[$i]->online = $member->isOnline();
break;
case "online_mobile":
if (!$canView) {
$arr->items[$i]->online_mobile = false;
break;
}
$arr->items[$i]->online_mobile = $member->getOnlinePlatform() == "android" || $member->getOnlinePlatform() == "iphone" || $member->getOnlinePlatform() == "mobile";
break;
case "photo_100":
$arr->items[$i]->photo_100 = $member->getAvatarURL("tiny");
break;
case "photo_200":
$arr->items[$i]->photo_200 = $member->getAvatarURL("normal");
break;
case "photo_200_orig":
$arr->items[$i]->photo_200_orig = $member->getAvatarURL("normal");
break;
case "photo_400_orig":
$arr->items[$i]->photo_400_orig = $member->getAvatarURL("normal");
break;
case "photo_max":
$arr->items[$i]->photo_max = $member->getAvatarURL("original");
break;
case "photo_max_orig":
$arr->items[$i]->photo_max_orig = $member->getAvatarURL();
break;
case "relation":
$arr->items[$i]->relation = $member->getMaritalStatus();
break;
case "relatives":
$arr->items[$i]->relatives = 0;
break;
case "schools":
$arr->items[$i]->schools = 0;
break;
case "sex":
if (!$canView) {
$arr->items[$i]->sex = -1;
break;
}
$arr->items[$i]->sex = $member->isFemale() ? 1 : 2;
break;
case "site":
if (!$canView) {
$arr->items[$i]->site = null;
break;
}
$arr->items[$i]->site = $member->getWebsite();
break;
case "status":
if (!$canView) {
$arr->items[$i]->status = "r";
break;
}
$arr->items[$i]->status = $member->getStatus();
break;
case "universities":
$arr->items[$i]->universities = 0;
break;
}
}
$i++;
$obj->items[] = $member->toVkApiStruct($this->getUser(), $fields);
}
return $arr;
return $obj;
}
public function getSettings(string $group_id)
{
$this->requireUser();
$club = (new ClubsRepo())->get((int) $group_id);
if (!$club || !$club->canBeModifiedBy($this->getUser())) {
$this->fail(15, "You can't get settings of this group.");
$this->fail(15, "Access denied");
}
$arr = (object) [
"title" => $club->getName(),
"description" => $club->getDescription() != null ? $club->getDescription() : "",
"description" => $club->getDescription(),
"address" => $club->getShortcode(),
"wall" => $club->getWallType(), # отличается от вкшных но да ладно
"wall" => $club->getWallType(), # is different from vk values
"photos" => 1,
"video" => 0,
"audio" => $club->isEveryoneCanUploadAudios() ? 1 : 0,
"docs" => 0,
"docs" => 1,
"topics" => $club->isEveryoneCanCreateTopics() == true ? 1 : 0,
"wiki" => 0,
"messages" => 0,
"obscene_filter" => 0,
"obscene_stopwords" => 0,
"obscene_words" => "",
"access" => 1,
"subject" => 1,
"subject_list" => [
0 => "в",
1 => "опенвк",
2 => "нет",
3 => "категорий",
4 => "групп",
],
"rss" => "/club" . $club->getId() . "/rss",
"website" => $club->getWebsite(),
"age_limits" => 0,
"market" => [],
];
return $arr;
}
public function isMember(string $group_id, int $user_id, string $user_ids = "", bool $extended = false)
public function isMember(string $group_id, int $user_id, int $extended = 0)
{
$this->requireUser();
$id = $user_id != null ? $user_id : explode(",", $user_ids);
if ($group_id < 0) {
$this->fail(228, "Remove the minus from group_id");
$input_club = (new ClubsRepo())->get(abs((int) $group_id));
$input_user = (new UsersRepo())->get(abs((int) $user_id));
if (!$input_club || !$input_club->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access denied");
}
$club = (new ClubsRepo())->get((int) $group_id);
$usver = (new UsersRepo())->get((int) $id);
if (!$club || $group_id == 0) {
$this->fail(203, "Invalid club");
if (!$input_user || $input_user->isDeleted()) {
$this->fail(15, "Not found");
}
if (!$usver || $usver->isDeleted() || $user_id == 0) {
$this->fail(30, "Invalid user");
}
if ($extended == false) {
return $club->getSubscriptionStatus($usver) ? 1 : 0;
if ($extended == 0) {
return $input_club->getSubscriptionStatus($input_user) ? 1 : 0;
} else {
return (object)
[
"member" => $club->getSubscriptionStatus($usver) ? 1 : 0,
"member" => $input_club->getSubscriptionStatus($input_user) ? 1 : 0,
"request" => 0,
"invitation" => 0,
"can_invite" => 0,
@ -665,11 +475,4 @@ final class Groups extends VKAPIRequestHandler
];
}
}
public function remove(int $group_id, int $user_id)
{
$this->requireUser();
$this->fail(501, "Not implemented");
}
}

View file

@ -118,7 +118,14 @@ final class Likes extends VKAPIRequestHandler
}
if (!$user->canBeViewedBy($this->getUser())) {
$this->fail(1984, "Access denied: you can't see this user");
$this->fail(15, "Access denied");
}
if ($user->isPrivateLikes()) {
return (object) [
"liked" => 1,
"copied" => 1,
];
}
$postable = null;

View file

@ -13,38 +13,49 @@ use openvk\Web\Models\Entities\{Note, Comment};
final class Notes extends VKAPIRequestHandler
{
public function add(string $title, string $text, int $privacy = 0, int $comment_privacy = 0, string $privacy_view = "", string $privacy_comment = "")
public function add(string $title, string $text)
{
$this->requireUser();
$this->willExecuteWriteAction();
if (empty($title)) {
$this->fail(100, "Required parameter 'title' missing.");
}
$note = new Note();
$note->setOwner($this->getUser()->getId());
$note->setCreated(time());
$note->setName($title);
$note->setSource($text);
$note->setEdited(time());
$note->save();
return $note->getVirtualId();
}
public function createComment(string $note_id, int $owner_id, string $message, int $reply_to = 0, string $attachments = "")
public function createComment(int $note_id, int $owner_id, string $message, string $attachments = "")
{
$this->requireUser();
$this->willExecuteWriteAction();
$note = (new NotesRepo())->getNoteById((int) $owner_id, (int) $note_id);
if (empty($message)) {
$this->fail(100, "Required parameter 'message' missing.");
}
$note = (new NotesRepo())->getNoteById($owner_id, $note_id);
if (!$note) {
$this->fail(180, "Note not found");
$this->fail(15, "Access denied");
}
if ($note->isDeleted()) {
$this->fail(189, "Note is deleted");
$this->fail(15, "Access denied");
}
if ($note->getOwner()->isDeleted()) {
$this->fail(403, "Owner is deleted");
$this->fail(15, "Access denied");
}
if (!$note->canBeViewedBy($this->getUser())) {
@ -52,11 +63,7 @@ final class Notes extends VKAPIRequestHandler
}
if (!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser())) {
$this->fail(43, "No access");
}
if (empty($message) && empty($attachments)) {
$this->fail(100, "Required parameter 'message' missing.");
$this->fail(15, "Access denied");
}
$comment = new Comment();
@ -67,78 +74,9 @@ final class Notes extends VKAPIRequestHandler
$comment->setCreated(time());
$comment->save();
if (!empty($attachments)) {
$attachmentsArr = explode(",", $attachments);
if (sizeof($attachmentsArr) > 10) {
$this->fail(50, "Error: too many attachments");
}
foreach ($attachmentsArr as $attac) {
$attachmentType = null;
if (str_contains($attac, "photo")) {
$attachmentType = "photo";
} elseif (str_contains($attac, "video")) {
$attachmentType = "video";
} else {
$this->fail(205, "Unknown attachment type");
}
$attachment = str_replace($attachmentType, "", $attac);
$attachmentOwner = (int) explode("_", $attachment)[0];
$attachmentId = (int) end(explode("_", $attachment));
$attacc = null;
if ($attachmentType == "photo") {
$attacc = (new PhotosRepo())->getByOwnerAndVID($attachmentOwner, $attachmentId);
if (!$attacc || $attacc->isDeleted()) {
$this->fail(100, "Photo does not exists");
}
if ($attacc->getOwner()->getId() != $this->getUser()->getId()) {
$this->fail(43, "You do not have access to this photo");
}
$comment->attach($attacc);
} elseif ($attachmentType == "video") {
$attacc = (new VideosRepo())->getByOwnerAndVID($attachmentOwner, $attachmentId);
if (!$attacc || $attacc->isDeleted()) {
$this->fail(100, "Video does not exists");
}
if ($attacc->getOwner()->getId() != $this->getUser()->getId()) {
$this->fail(43, "You do not have access to this video");
}
$comment->attach($attacc);
}
}
}
return $comment->getId();
}
public function delete(string $note_id)
{
$this->requireUser();
$this->willExecuteWriteAction();
$note = (new NotesRepo())->get((int) $note_id);
if (!$note) {
$this->fail(180, "Note not found");
}
if (!$note->canBeModifiedBy($this->getUser())) {
$this->fail(15, "Access to note denied");
}
$note->delete();
return 1;
}
public function edit(string $note_id, string $title = "", string $text = "", int $privacy = 0, int $comment_privacy = 0, string $privacy_view = "", string $privacy_comment = "")
{
$this->requireUser();
@ -147,15 +85,15 @@ final class Notes extends VKAPIRequestHandler
$note = (new NotesRepo())->getNoteById($this->getUser()->getId(), (int) $note_id);
if (!$note) {
$this->fail(180, "Note not found");
$this->fail(15, "Access denied");
}
if ($note->isDeleted()) {
$this->fail(189, "Note is deleted");
$this->fail(15, "Access denied");
}
if (!$note->canBeModifiedBy($this->getUser())) {
$this->fail(403, "No access");
$this->fail(15, "Access denied");
}
!empty($title) ? $note->setName($title) : null;
@ -171,26 +109,28 @@ final class Notes extends VKAPIRequestHandler
public function get(int $user_id, string $note_ids = "", int $offset = 0, int $count = 10, int $sort = 0)
{
$this->requireUser();
$user = (new UsersRepo())->get($user_id);
if (!$user || $user->isDeleted()) {
$this->fail(15, "Invalid user");
$this->fail(15, "Access denied");
}
if (!$user->getPrivacyPermission('notes.read', $this->getUser())) {
$this->fail(15, "Access denied: this user chose to hide his notes");
$this->fail(15, "Access denied");
}
if (!$user->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access denied");
}
$nodez = (object) [
$notes_return_object = (object) [
"count" => 0,
"notes" => [],
"items" => [],
];
if (empty($note_ids)) {
$nodez->count = (new NotesRepo())->getUserNotesCount($user);
$notes_return_object->count = (new NotesRepo())->getUserNotesCount($user);
$notes = array_slice(iterator_to_array((new NotesRepo())->getUserNotes($user, 1, $count + $offset, $sort == 0 ? "ASC" : "DESC")), $offset);
@ -199,25 +139,21 @@ final class Notes extends VKAPIRequestHandler
continue;
}
$nodez->notes[] = $note->toVkApiStruct();
$notes_return_object->items[] = $note->toVkApiStruct();
}
} else {
$notes = explode(',', $note_ids);
$notes_splitted = explode(',', $note_ids);
foreach ($notes as $note) {
$id = explode("_", $note);
foreach ($notes_splitted as $note_id) {
$note = (new NotesRepo())->getNoteById($user_id, $note_id);
$items = [];
$note = (new NotesRepo())->getNoteById((int) $id[0], (int) $id[1]);
if ($note && !$note->isDeleted()) {
$nodez->notes[] = $note->toVkApiStruct();
$nodez->count++;
$notes_return_object->items[] = $note->toVkApiStruct();
}
}
}
return $nodez;
return $notes_return_object;
}
public function getById(int $note_id, int $owner_id, bool $need_wiki = false)
@ -227,23 +163,23 @@ final class Notes extends VKAPIRequestHandler
$note = (new NotesRepo())->getNoteById($owner_id, $note_id);
if (!$note) {
$this->fail(180, "Note not found");
$this->fail(15, "Access denied");
}
if ($note->isDeleted()) {
$this->fail(189, "Note is deleted");
$this->fail(15, "Access denied");
}
if (!$note->getOwner() || $note->getOwner()->isDeleted()) {
$this->fail(177, "Owner does not exists");
$this->fail(15, "Access denied");
}
if (!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser())) {
$this->fail(40, "Access denied: this user chose to hide his notes");
$this->fail(15, "Access denied");
}
if (!$note->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access to note denied");
$this->fail(15, "Access denied");
}
return $note->toVkApiStruct();
@ -256,23 +192,23 @@ final class Notes extends VKAPIRequestHandler
$note = (new NotesRepo())->getNoteById($owner_id, $note_id);
if (!$note) {
$this->fail(180, "Note not found");
$this->fail(15, "Access denied");
}
if ($note->isDeleted()) {
$this->fail(189, "Note is deleted");
$this->fail(15, "Access denied");
}
if (!$note->getOwner()) {
$this->fail(177, "Owner does not exists");
$this->fail(15, "Access denied");
}
if (!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser())) {
$this->fail(14, "No access");
$this->fail(15, "Access denied");
}
if (!$note->canBeViewedBy($this->getUser())) {
$this->fail(15, "Access to note denied");
$this->fail(15, "Access denied");
}
$arr = (object) [
@ -286,14 +222,4 @@ final class Notes extends VKAPIRequestHandler
return $arr;
}
public function getFriendsNotes(int $offset = 0, int $count = 0)
{
$this->fail(501, "Not implemented");
}
public function restoreComment(int $comment_id = 0, int $owner_id = 0)
{
$this->fail(501, "Not implemented");
}
}

View file

@ -120,11 +120,11 @@ final class Polls extends VKAPIRequestHandler
$poll = (new PollsRepo())->get($poll_id);
if (!$poll) {
$this->fail(251, "Invalid poll");
$this->fail(15, "Access denied");
}
if ($poll->isAnonymous()) {
$this->fail(251, "Access denied: poll is anonymous.");
$this->fail(15, "Access denied");
}
$voters = array_slice($poll->getVoters($answer_ids, 1, $offset + $count), $offset);
@ -175,10 +175,4 @@ final class Polls extends VKAPIRequestHandler
return $this->getById($poll->getId());
}
public function edit()
{
#todo
return 1;
}
}

View file

@ -20,12 +20,18 @@ final class Video extends VKAPIRequestHandler
$this->requireUser();
if (!empty($videos)) {
$vids = explode(',', $videos);
$vids = array_unique(explode(',', $videos));
if (sizeof($vids) > 100) {
$this->fail(15, "Too many ids given");
}
$profiles = [];
$groups = [];
$items = [];
foreach ($vids as $vid) {
$id = explode("_", $vid);
$items = [];
$video = (new VideosRepo())->getByOwnerAndVID(intval($id[0]), intval($id[1]));
if ($video && !$video->isDeleted()) {

View file

@ -1104,13 +1104,18 @@ final class Wall extends VKAPIRequestHandler
$post = (new PostsRepo())->getPostById($owner_id, $post_id, true);
if (!$post || $post->isDeleted()) {
$this->fail(583, "Invalid post");
$this->fail(15, "Not found");
}
$wallOwner = $post->getWallOwner();
# trying to solve the condition below.
# $post->getTargetWall() < 0 - if post on wall of club
# !$post->getWallOwner()->canBeModifiedBy($this->getUser()) - group is cannot be modifiet by %user%
# $post->getWallOwner()->getWallType() != 1 - wall is not open
# $post->getSuggestionType() == 0 - post is not suggested
if ($post->getTargetWall() < 0 && !$post->getWallOwner()->canBeModifiedBy($this->getUser()) && $post->getWallOwner()->getWallType() != 1 && $post->getSuggestionType() == 0) {
$this->fail(12, "Access denied: you can't delete your accepted post.");
$this->fail(15, "Access denied");
}
if ($post->getOwnerPost() == $this->getUser()->getId() || $post->getTargetWall() == $this->getUser()->getId() || $owner_id < 0 && $wallOwner->canBeModifiedBy($this->getUser())) {

View file

@ -429,6 +429,11 @@ class Club extends RowModel
$this->save();
}
public function delete(bool $softly = true): void
{
$this->ban("");
}
public function unban(): void
{
$this->setBlock_Reason(null);

View file

@ -60,6 +60,11 @@ abstract class MediaCollection extends RowModel
}
}
public function getOwnerId(): int
{
return (int) $this->getRecord()->owner;
}
public function getPrettyId(): string
{
return $this->getRecord()->owner . "_" . $this->getRecord()->id;

View file

@ -138,18 +138,13 @@ class Note extends Postable
{
$res = (object) [];
$res->type = "note";
$res->id = $this->getVirtualId();
$res->owner_id = $this->getOwner()->getId();
$res->title = $this->getName();
$res->text = $this->getText();
$res->date = $this->getPublicationTime()->timestamp();
$res->comments = $this->getCommentsCount();
$res->read_comments = $this->getCommentsCount();
$res->view_url = "/note" . $this->getOwner()->getId() . "_" . $this->getVirtualId();
$res->privacy_view = 1;
$res->can_comment = 1;
$res->text_wiki = "r";
return $res;
}

View file

@ -336,7 +336,12 @@ class Photo extends Media
public function getAlbum(): ?Album
{
return (new Albums())->getAlbumByPhotoId($this);
$album = (new Albums())->getAlbumByPhotoId($this);
if (!$album || $album->isDeleted()) {
return null;
}
return $album;
}
public function toVkApiStruct(bool $photo_sizes = true, bool $extended = false): object

View file

@ -260,6 +260,7 @@ class Playlist extends MediaCollection
$cover->setDescription("Playlist cover image");
$cover->setFile($file);
$cover->setCreated(time());
$cover->setSystem(true);
$cover->save();
$this->setCover_photo_id($cover->getId());

View file

@ -75,9 +75,9 @@ abstract class Postable extends Attachable
return new DateTime($edited);
}
public function getComments(int $page, ?int $perPage = null): \Traversable
public function getComments(int $page, ?int $perPage = null, string $sort = "ASC"): \Traversable
{
return (new Comments())->getCommentsByTarget($this, $page, $perPage);
return (new Comments())->getCommentsByTarget($this, $page, $perPage, $sort);
}
public function getCommentsCount(): int

View file

@ -1502,7 +1502,7 @@ class User extends RowModel
return $this->getPrivacySetting("likes.read") == User::PRIVACY_NO_ONE;
}
public function toVkApiStruct(?User $user = null, string $fields = ''): object
public function toVkApiStruct(?User $relation_user = null, string $fields = ''): object
{
$res = (object) [];
@ -1512,8 +1512,8 @@ class User extends RowModel
$res->deactivated = $this->isDeactivated();
$res->is_closed = $this->isClosed();
if (!is_null($user)) {
$res->can_access_closed = (bool) $this->canBeViewedBy($user);
if (!is_null($relation_user)) {
$res->can_access_closed = (bool) $this->canBeViewedBy($relation_user);
}
if (!is_array($fields)) {
@ -1569,18 +1569,18 @@ class User extends RowModel
$res->real_id = $this->getRealId();
break;
case "blacklisted_by_me":
if (!$user) {
if (!$relation_user) {
break;
}
$res->blacklisted_by_me = (int) $this->isBlacklistedBy($user);
$res->blacklisted_by_me = (int) $this->isBlacklistedBy($relation_user);
break;
case "blacklisted":
if (!$user) {
if (!$relation_user) {
break;
}
$res->blacklisted = (int) $user->isBlacklistedBy($this);
$res->blacklisted = (int) $relation_user->isBlacklistedBy($this);
break;
case "games":
$res->games = $this->getFavoriteGames();

View file

@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace openvk\Web\Presenters;
use Chandler\Session\Session;
use Parsedown;
final class DevelopersPresenter extends OpenVKPresenter
{
public function renderMain(): void
{
$this->template->_template = "Developers/Main.xml";
$this->template->responseTime = round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2);
}
public function renderStandalone(): void
{
$this->template->_template = "Developers/Standalone.xml";
}
public function noPage(): void
{
$this->template->_template = "Developers/NoPage.xml";
}
public function parseMarkdown(string $path)
{
if (!file_exists("$path")) {
$this->noPage();
return [];
}
$dataArray = array();
$lines = file($path);
if (!preg_match("%^OpenVK-KB-Heading: (.+)$%", $lines[0], $matches)) {
$heading = "Article $name";
} else {
$heading = $matches[1];
array_shift($lines);
}
$content = implode($lines);
$parser = new Parsedown();
$dataArray['heading'] = $heading;
$dataArray['content'] = $parser->text($content);
return $dataArray;
}
public function renderDevelopersBaseArticle(string $name): void
{
$lang = Session::i()->get("lang", "ru");
$base = OPENVK_ROOT . "/data/developers";
if (file_exists("$base/$name.$lang.md")) {
$file = "$base/$name.$lang.md";
} elseif (file_exists("$base/$name.md")) {
$file = "$base/$name.md";
} else {
$this->noPage();
return;
}
$parsedMd = $this->parseMarkdown($file);
$this->template->articlename = $name;
$this->template->heading = $parsedMd['heading'];
$this->template->content = $parsedMd['content'];
}
}

View file

@ -73,10 +73,10 @@ final class DocumentsPresenter extends OpenVKPresenter
$this->template->count = $docs->size();
$this->template->docs = iterator_to_array($docs->page($page, OPENVK_DEFAULT_PER_PAGE));
$this->template->locale_string = "you_have_x_documents";
if ($owner_id < 0) {
$this->template->locale_string = "group_has_x_documents";
} elseif ($current_tab != 0) {
if ($current_tab != 0) {
$this->template->locale_string = "x_documents_in_tab";
} elseif ($owner_id < 0) {
$this->template->locale_string = "group_has_x_documents";
}
$this->template->canUpload = $owner_id == $this->user->id || $this->template->group->canBeModifiedBy($this->user->identity);

View file

@ -135,7 +135,7 @@ final class GroupPresenter extends OpenVKPresenter
$this->template->paginatorConf = (object) [
"count" => $this->template->count,
"page" => $this->queryParam("p") ?? 1,
"page" => (int) ($this->queryParam("p") ?? 1),
"amount" => 10,
"perPage" => OPENVK_DEFAULT_PER_PAGE,
];

View file

@ -149,7 +149,7 @@ final class InternalAPIPresenter extends OpenVKPresenter
{
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
header("HTTP/1.1 405 Method Not Allowed");
exit("ты‍ не по адресу");
$this->redirect("/");
}
$type = $this->queryParam("type", false);
@ -168,7 +168,7 @@ final class InternalAPIPresenter extends OpenVKPresenter
if ($type == 'post') {
$this->template->_template = 'components/post.xml';
$this->template->post = $post;
$this->template->commentSection = true;
$this->template->commentSection = $this->queryParam("from_page") == "another";
} elseif ($type == 'comment') {
$this->template->_template = 'components/comment.xml';
$this->template->comment = $post;

View file

@ -102,7 +102,7 @@ final class NoSpamPresenter extends OpenVKPresenter
$item = new $model($item);
if (key_exists("deleted", $item->unwrap()) && $item->isDeleted()) {
if (property_exists($item->unwrap(), "deleted") && $item->isDeleted()) {
$item->setDeleted(0);
$item->save();
}

View file

@ -272,21 +272,27 @@ final class PhotosPresenter extends OpenVKPresenter
$this->assertUserLoggedIn();
$this->willExecuteWriteAction(true);
$upload_context = $this->queryParam("upload_context");
if (is_null($this->queryParam("album"))) {
$album = $this->albums->getUserWallAlbum($this->user->identity);
if ((int) $upload_context == $this->user->id) {
$album = $this->albums->getUserWallAlbum($this->user->identity);
}
} else {
[$owner, $id] = explode("_", $this->queryParam("album"));
$album = $this->albums->get((int) $id);
}
if (!$album) {
$this->flashFail("err", tr("error"), tr("error_adding_to_deleted"), 500, true);
if ($_SERVER["REQUEST_METHOD"] == "GET" || $this->queryParam("act") == "finish") {
if (!$album || $album->isCreatedBySystem()) {
$this->flashFail("err", tr("error"), tr("error_adding_to_deleted"));
}
}
# Для быстрой загрузки фоток из пикера фотографий нужен альбом, но юзер не может загружать фото
# в системные альбомы, так что так.
if (is_null($this->user) || !is_null($this->queryParam("album")) && !$album->canBeModifiedBy($this->user->identity)) {
$this->flashFail("err", tr("error_access_denied_short"), tr("error_access_denied"), 500, true);
if ($album && !$album->canBeModifiedBy($this->user->identity)) {
if ($album->getOwnerId() != $this->user->id) {
$this->flashFail("err", tr("error_access_denied_short"), tr("error_access_denied"));
}
}
if ($_SERVER["REQUEST_METHOD"] === "POST") {
@ -306,8 +312,6 @@ final class PhotosPresenter extends OpenVKPresenter
$phot->setDescription($description);
$phot->save();
$album = $phot->getAlbum();
}
$this->returnJson(["success" => true,
@ -346,9 +350,11 @@ final class PhotosPresenter extends OpenVKPresenter
$this->flashFail("err", "Неизвестная ошибка", "Не удалось сохранить фотографию в $name.", 500, true);
}
$album->addPhoto($photo);
$album->setEdited(time());
$album->save();
if ($album != null) {
$album->addPhoto($photo);
$album->setEdited(time());
$album->save();
}
}
$this->returnJson(["success" => true,

View file

@ -133,6 +133,7 @@ final class VideosPresenter extends OpenVKPresenter
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$video->setName(empty($this->postParam("name")) ? null : $this->postParam("name"));
$video->setDescription(empty($this->postParam("desc")) ? null : $this->postParam("desc"));
$video->setUnlisted(false);
$video->save();
$this->flash("succ", tr("changes_saved"), tr("changes_saved_video_comment"));

View file

@ -469,7 +469,11 @@ final class WallPresenter extends OpenVKPresenter
}
$this->template->cCount = $post->getCommentsCount();
$this->template->cPage = (int) ($_GET["p"] ?? 1);
$this->template->comments = iterator_to_array($post->getComments($this->template->cPage));
$this->template->sort = $this->queryParam("sort") ?? "asc";
$input_sort = $this->template->sort == "asc" ? "ASC" : "DESC";
$this->template->comments = iterator_to_array($post->getComments($this->template->cPage, null, $input_sort));
}
public function renderLike(int $wall, int $post_id): void

View file

@ -210,7 +210,7 @@
{var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="{_admin} [Alt+Shift+A]" accesskey="a" rel="nofollow">{_admin}</a>
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk" rel="nofollow">{_helpdesk}
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">{_helpdesk}
{if $helpdeskTicketNotAnsweredCount > 0}
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
{/if}
@ -365,7 +365,7 @@
<a href="/terms" class="link">{_footer_rules}</a>
<a href="/blog" class="link">{_footer_blog}</a>
<a href="/support" class="link">{_footer_help}</a>
<a href="/dev" target="_blank" class="link">{_footer_developers}</a>
<a href="/dev" class="link">{_footer_developers}</a>
<a href="/privacy" class="link">{_footer_privacy}</a>
</div>
<p>

View file

@ -16,7 +16,7 @@
{block tabs}
<div n:attr="id => ($act === 'list' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($act === 'list' ? 'act_tab_a' : 'ki')" href="?act=list">{_all_apps}</a>
<a n:attr="id => ($act === 'list' ? 'act_tab_a' : 'ki')" href="/search?q=&section=apps">{_all_apps}</a>
</div>
<div n:attr="id => ($act === 'installed' ? 'activetabs' : 'ki')" class="tab">

View file

@ -0,0 +1,57 @@
{extends "../@layout.xml"}
{block title}
{_developers_title}
{/block}
{block header}
{_developers_title}
{/block}
{block content}
{css "css/dev.css"}
<div class="knowledgeBaseArticle">{$content|noescape}</div>
<div id="dev_sidebar" class="dev_sidebar fl_r">
<div id="dev_mlist_cont">
<div id="dev_page_narrow">
<a
href="/dev/main"
class="dev_section_menu {if $articlename === 'main'} dev_mlist_sel{/if}"
>Документация</a>
<a
href="/dev/native"
class="dev_section_submenu {if $articlename === 'native'} dev_mlist_sel{/if}"
>Приложения и игры</a>
<a
href="/dev/standalone"
class="dev_section_submenu"
>Standalone/Mobile</a>
<a
href="/dev/sites"
class="dev_section_submenu {if $articlename === 'sites'} dev_mlist_sel{/if}"
>Сайты и виджеты</a>
<a
href="/dev/methods"
class="dev_section_menu {if $articlename === 'methods'} dev_mlist_sel{/if}"
>Список методов</a>
<a
href="/dev/datatypes"
class="dev_section_submenu {if $articlename === 'datatypes'} dev_mlist_sel{/if}"
>Типы данных</a>
<a
href="/dev/help"
class="dev_section_menu {if $articlename === 'help'} dev_mlist_sel{/if}"
>Поддержка</a>
<a
href="/dev/rules"
class="dev_section_submenu {if $articlename === 'rules'} dev_mlist_sel{/if}"
>Правила платформы</a>
</div>
</div>
</div>
{/block}

View file

@ -0,0 +1,92 @@
{extends "../@layout.xml"}
{block title}
{_developers_title}
{/block}
{block header}
{_developers_title}
{/block}
{block content}
{css "css/dev.css"}
<div class="dev_head">
<div class="dev_main_header">Разработка приложений</div>
<div class="dev_main_narrow">
<a
class="button"
href="/editapp?act=create"
>&nbsp;&nbsp;Создать приложение&nbsp;&nbsp;</a>
<br>
<br>
<a href="/apps?act=dev">Список моих приложений »</a>
</div>
<div class="dev_main_desc">
<b>оупэн В контакте</b> самый быстрорастущий сайт европейского интернета. Его аудитория удваивается каждые несколько месяцев, и сейчас на оупэн В контакте приходится более половины русскоязычного трафика. Если Вы хотите заниматься разработкой приложений в интернете, Вы можете приобщиться к этому успеху и получить доступ к аудитории свыше
<b>25000 (!!!)</b> пользователей.
</div>
</div>
<div class="dev_cont">
<div class="dev_main_sections">
<a href="/dev/native" class="dev_sect dev_sect_games">
<div class="dev_sect_icon"></div>
Игры и приложения ВКонтакте
</a>
<a href="/dev/standalone" class="dev_sect dev_sect_standalone">
<div class="dev_sect_icon"></div>
Mobile/Standalone приложения
</a>
<a href="/dev/sites" class="dev_sect dev_sect_widgets">
<div class="dev_sect_icon"></div>
Авторизация и виджеты для сайтов
</a>
</div>
<div class="dev_parts_list fl_l">
<a href="/dev/main" class="dev_part">
<div class="dev_part_name">Документация платформы</div>
<div class="dev_part_desc">Описание возможностей платформы ВКонтакте: процедура авторизации приложения, серверные и клиентские методы API, создание приложений и подключение сайтов.</div>
</a>
<a href="/dev/help" class="dev_part">
<div class="dev_part_name">Поддержка</div>
<div class="dev_part_desc">Разрешение вопросов, связанных с платформой: инструменты для связи со службой поддержки, попадание в каталог приложений, статус работы платформы.</div>
</a>
<a href="/dev/rules" class="dev_part">
<div class="dev_part_name">Правила платформы</div>
<div class="dev_part_desc">Правила публикации приложений на площадке ВКонтакте, размещение рекламы в приложениях, прием платежей от пользователей.</div>
</a>
<a href="/bagosi" class="dev_part">
<div class="dev_part_name">Баг-трекер</div>
<div class="dev_part_desc">Инструмент для информирования разработчиков о проблемах в API и документации платформы.</div>
</a>
</div>
<div class="dev_right_col fl_l">
<a class="dev_part dev_platform_info" href="/dev/health">
<div class="dev_info_header">Статус платформы</div>
Время ответа — <span class="dev_api_status_good">{$responseTime} ms</span><br>
Uptime — <span class="dev_api_status_good">целестора сделай%</span><br>
</a>
<div class="dev_last_news">
<div class="dev_info_header">Последние новости</div>
<div class="dev_main_widget_cont">
<ul class="notes_titles">
<li class="written">
<a href="/note1_1">
seks
</a>
<small>
только что
<span class="divide">|</span>
<a href="/note1_1">Комментарии</a>
</small>
</li>
</ul>
</div>
</div>
</div>
</div>
{/block}

View file

@ -0,0 +1,61 @@
{extends "../@layout.xml"}
{block title}
{_developers_nopage}
{/block}
{block header}
{_developers_nopage}
{/block}
{block content}
{css "css/dev.css"}
<div class="knowledgeBaseArticle" style="float: left">
<p>братишка ты что-то попутал</p>
</div>
<!-- я сделал так, чтобы можно было сделать норм 404 для девелоперов, типа рекомендуемые функции -->
<!-- или ВЫ ОШИБЛИСЬ, А МОЖЕТ ВЫ ХОТЕЛИ НАПИСАТЬ ...? ну вы поняли я надеюсь -->
<div id="dev_sidebar" class="dev_sidebar fl_r">
<div id="dev_mlist_cont">
<div id="dev_page_narrow">
<a
href="/dev/main"
class="dev_section_menu"
>Документация</a>
<a
href="/dev/native"
class="dev_section_submenu"
>Приложения и игры</a>
<a
href="/dev/standalone"
class="dev_section_submenu"
>Standalone/Mobile</a>
<a
href="/dev/sites"
class="dev_section_submenu"
>Сайты и виджеты</a>
<a
href="/dev/methods"
class="dev_section_menu"
>Список методов</a>
<a
href="/dev/datatypes"
class="dev_section_submenu"
>Типы данных</a>
<a
href="/dev/help"
class="dev_section_menu"
>Поддержка</a>
<a
href="/dev/rules"
class="dev_section_submenu"
>Правила платформы</a>
</div>
</div>
</div>
{/block}

View file

@ -0,0 +1,144 @@
{extends "../@layout.xml"}
{block title}
{_developers_title}
{/block}
{block header}
{_developers_title}
{/block}
{block content}
{css "css/dev.css"}
{script "js/al_dev.js"}
<div style="margin-left: 0px; width: 141.321px;" id="dev_steps_s">
<div class="borders">
<div class="content" style="margin-left: -2px;">
<div class="dev_step first">
<div>
<b>Developers</b><br>Where to start
</div>
</div>
<div class="dev_step">
<div>
<b>Documentation</b><br>VK API
</div>
</div>
<div class="dev_step last">
<div>
<b>Integration Examples</b><br>Consider the platform advantages
</div>
</div>
</div>
</div>
</div>
<div id="dev_steps">
<div class="dev_step first current" id="dev_step1" onclick="return dev_step(1);">
<div>
<b>Developers</b><br>Where to start
</div>
</div>
<div class="dev_step" id="dev_step2" onclick="return dev_step(2)">
<div>
<b>Documentation</b><br>VK API
</div>
</div>
<div class="dev_step last" id="dev_step3" onclick="return dev_step(3)">
<div>
<b>Integration Examples</b><br>Consider the platform advantages
</div>
</div>
</div>
<div class="dev_steps_c" id="dev_steps_c" style="height: 460px;">
<div class="content" style="margin-left: 0px;">
<div class="step" id="dev_step1_c" style="height: auto; position: static; left: auto;">
<div class="borders">
<div class="introPage">
<a href="/developers.php?id=-1_27971896&amp;s=1" class="info first apps"><span class="header">VK Flash/IFrame Applications</span>
Interactive appliation use <b>VK API</b> to deeply integrate with the site. You can use VK servers as well as any number of your own servers.
<span class="more">More »</span>
</a>
<a href="/developers.php?id=-1_37230422&amp;s=1" class="info mobile"><span class="header">Standalone/Mobile Applications</span>
These are launched in the same way as a regular program on a user's device, be it a desktop computer or a smartphone. All algorithms available to applications on the <b>VK API</b> platform work for desktop applications too.
<span class="more">More »</span>
</a>
<a href="/developers.php?id=-1_27987570&amp;s=1" class="info sites"><span class="header">Widgets and External Sites</span>
VK's lineup of <b>widgets</b> for external sites allows you to add a social aspect to your project. Also a deeper integration via <b>Open API</b> or <b>OAuth 2.0.</b> is available.
<span class="more">More »</span>
</a>
<a href="/developers.php?id=-1_12904887&s=1" class="info shops"><span class="header">Stores</span>
With the help of <b>Merchant API</b> you can connect your internet store or a VK API application to VK&#39;s payment system and gain full access to millions of potential customers.
<span class="more">More »</span>
</a>
</div>
</div>
</div>
<div class="step" id="dev_step2_c" style="position: static; left: auto; height: auto;">
<div class="borders">
<div class="introPage">
<!--4-->
<a name="Connect"></a>
<div class="wk_header">Connect</div>
<ul class="listing">
<li><span><a href="developers.php?oid=-17680044&amp;p=VK_Applications">VK Applications</a> Where to start creating Flash and IFrame applications </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Flash_Applications">Flash Applications</a> Interaction with API from Flash applications </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Using_the_Flash_Wrapper">Flash Applications with Wrapper</a> Interaction with API using the Flash wrapper </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=IFrame_Applications">IFrame Applications</a> Interaction with API from IFrame applications </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Application_Interaction_with_API">Application Interaction with API</a> Calling API from an application or from an external server </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Authorization">Authorization</a> Authorization from Desktop and Mobile applications </span></li>
</ul>
<br>
<a name="VK API"></a>
<div class="wk_header">VK API</div>
<ul class="listing">
<li><span><a href="developers.php?oid=-17680044&amp;p=API_Method_Description">API Method Description</a> Standard API methods </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Advanced_API_Methods">Advanced API Methods</a> Methods for Desktop/Mobile applications </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Storing_Data_on_VK_Servers">Storing Data on VK Servers</a> </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Uploading_Files_to_the_VK_Server_Procedure">Uploading Files to the VK Server Procedure</a> </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Application_Localization">Application Localization</a> </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Ads_API">Ads API</a> <sup><b>beta</b></sup> methods for working with advertising accounts. </span></li>
</ul>
<br>
<a name="JS API"></a>
<div class="wk_header">JS API</div>
<ul class="listing">
<li><span><a href="developers.php?oid=-17680044&amp;p=IFrame_Applications">IFrame Applications</a> Calling JS API methods from IFrame applications </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Flash_Applications">Flash Applications</a> Calling JS API methods from Flash applications </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Using_the_Flash_Wrapper">Using the Flash Wrapper</a> Calling JS API methods from Flash applications using a wrapper </span></li>
</ul>
<br>
<a name="For Websites"></a>
<div class="wk_header">For Websites</div>
<ul class="listing">
<li><span><a href="developers.php?oid=-17680044&amp;p=Comments">Comments</a> Embed a universal comments block to an external website </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Groups">Groups</a> Embed a community block on an external website </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Like">Like</a> Let users "like" items on your site and share links with friends </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Poll">Polls</a> Poll your visitors and and let them pass the poll on to their friends </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Auth">Auth</a> Hassle-free authorization on your site </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Share">Share button</a> Let users quickly share links to your items </span></li>
<li><span><a href="developers.php?oid=-17680044&amp;p=Open_API">Open API</a> Use VK API on external websites </span></li>
</ul>
<br>
<a name="For Online Stores"></a>
<div class="wk_header">For Online Stores</div>
<ul class="listing">
<li><span><a href="developers.php?oid=-17680044&amp;p=Merchant_API">Merchant API</a> connect applications and external internet stores to the VK payment system </span></li>
</ul>
<!--ru:2438534-->
</div>
</div>
</div>
<div class="step" id="dev_step3_c" style="height: auto; position: static; left: auto;">
<div class="borders">
<div class="introPage">
<!--4--><b>VK</b> is the fastest growing site in Europe. Its audience is doubled every few months and now VK controls more than half of the traffic in Russian-speaking countries. If you would like to develop applications on the internet, you can become part of this success and gain access to an audience of more than <b>100 million</b> users. <br><br>
It is not uncommon for an <a class="wk_vk_link" href="/apps">an application</a> created within a month to be visited by millions of people daily. Every month the most popular applications bring their creators millions of dollars. If you want to become one of them, we will give you the tools for distributing and promoting applications and also will fully take on all <b>payment</b> matters, <b>traffic</b> costs and the translation of your application into <b>all languages spoken in the world</b>. <br><br>
<a href="developers.php?oid=-17680044&amp;p=Flash_Applications">VK API</a> is the most advanced platform for Flash and iFrame applications on the worldwide web. We provide a massive field for your applications (up to <b>827x4050</b> pixels), access to the left user menu, counters, on-site and <b>SMS</b> notifications, profile, photos, friends, rating and audio files of users, and much more. <br><br>
<a class="wk_vk_link" href="/apps">Applications Catalog</a> <br>
</div>
</div>
</div>
</div>
</div>
{/block}

View file

@ -20,28 +20,25 @@
{block content}
{var $is_gallery = $current_tab == 3 || $current_tab == 4}
<div id="docs_page_wrapper">
<div class="docs_page_search">
<form action="/search" method="get">
<input type="hidden" name="section" value="docs">
<input type="search" name="q" class="input_with_search_icon" placeholder="{_search_by_documents}">
</form>
<input n:if="$canUpload" id="upload_entry_point" class="button" type="button" value="{_upload_button}" {if isset($group)}data-gid="{$group->getId()}"{/if}>
</div>
<div n:if="sizeof($tabs) > 1" class="docs_page_tabs">
<div class="mb_tabs">
<div class="mb_tab" n:attr="id => $current_tab == 0 ? active">
<a href="?tab=0">{_document_type_0}</a>
</div>
<div n:foreach="$tabs as $tab" class="mb_tab" n:attr="id => $tab['type'] == $current_tab ? active">
<a href="?tab={$tab['type']}">
{$tab["name"]}
<span n:if="$tab['count'] > 1" class="special_counter">{$tab["count"]}</span>
</a>
<div class="docs_page_tabs">
<div class="mb_tabs display_flex_row display_flex_space_between">
<div>
<div class="mb_tab" n:attr="id => $current_tab == 0 ? active">
<a href="?tab=0">{_document_type_0}</a>
</div>
<div n:foreach="$tabs as $tab" class="mb_tab" n:attr="id => $tab['type'] == $current_tab ? active">
<a href="?tab={$tab['type']}">
{$tab["name"]}
<span n:if="$tab['count'] > 1" class="special_counter">{$tab["count"]}</span>
</a>
</div>
</div>
<input n:if="$canUpload" id="upload_entry_point" class="button" type="button" value="{_upload_button}" {if isset($group)}data-gid="{$group->getId()}"{/if}>
</div>
</div>
<div n:class="docs_page_content, $is_gallery ? docs_page_gallery">
<div class="summaryBar display_flex_row display_flex_space_between">
<div n:if="$count > 0" class="summaryBar display_flex_row display_flex_space_between">
<div class="summary">{tr($locale_string, $count)}.</div>
<select n:if="$count > 3" name="docs_sort">

View file

@ -34,6 +34,12 @@
</a>
</td>
</tr>
<tr>
<td><span class="nobold">{_sent}: </span></td>
<td>
{$x->sent}
</td>
</tr>
<tr n:if="!empty($x->caption)">
<td><span class="nobold">{_comment}: </span></td>
<td>{$x->caption}</td>

View file

@ -55,7 +55,7 @@
<tbody>
<tr>
<td width="120" valign="top"><span class="nobold">{_pronouns}: </span></td>
<td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
<td>{$user->isFemale() ? tr("female") : ($user->isNeutral() ? tr("neutral") : tr("male"))}</td>
</tr>
<tr>
<td width="120" valign="top"><span class="nobold">{_registration_date}: </span></td>

View file

@ -269,7 +269,13 @@
search();
}
});
$("#apply").on("click", () => { search(Number($("#noSpam-ban-type").val())); })
$("#apply").on("click", (e) => {
e.preventDefault()
MessageBox(tr("warning"), tr("nospam_prevention"), [tr("no"), tr("yes")], [Function.noop, () => {
search(Number($("#noSpam-ban-type").val()));
}]);
})
async function selectChange(value) {
console.log(value);

View file

@ -13,7 +13,7 @@
<textarea name="html" style="display:none;"></textarea>
<div id="editor" style="width:600px;height:300px;border:1px solid grey"></div>
<p><i><a href="/kb/notes">{_something}</a> {_supports_xhtml}</i></p>
<p><i>{_something_is_supported_from_xhtml|noescape}</i></p>
<input type="hidden" name="hash" value="{$csrfToken}" />
<button class="button">{_save}</button>

View file

@ -18,7 +18,7 @@
<textarea name="html" style="display:none;"></textarea>
<div id="editor" style="width:600px;height:300px;border:1px solid grey"></div>
<p><i><a href="/kb/notes">{_something}</a> {_supports_xhtml}</i></p>
<p><i>{_something_is_supported_from_xhtml|noescape}</i></p>
<input type="hidden" name="hash" value="{$csrfToken}" />
<button class="button">{_save}</button>

View file

@ -5,7 +5,7 @@
{block title}{_albums} {$owner->getCanonicalName()}{/block}
{block header}
{if isset($thisUser) && $thisUser->getId() == $owner->getId()}
{if isset($thisUser) && $thisUser->getId() == $owner->getRealId()}
{_my_photos}
{else}
<a href="{$owner->getURL()}">
@ -18,7 +18,7 @@
{block size}
<div style="padding-bottom: 0px; padding-top: 0;" class="summaryBar">
<div class="summary">
{if !is_null($thisUser) && $owner->getId() === $thisUser->getId()}
{if !is_null($thisUser) && $owner->getRealId() === $thisUser->getId()}
{tr("albums_list", $count)}
{else}
{tr("albums", $count)}

View file

@ -42,6 +42,6 @@
{block description}
{var $author = $x->getUser()}
{ovk_proc_strtr($x->getContext(), 50)}<br/>
{ovk_proc_strtr($x->getContext(), 200)}<br/>
<span class="nobold">{_author}: </span> <a href="{$author->getURL()}">{$author->getCanonicalName()}</a>
{/block}

View file

@ -76,14 +76,4 @@
<input type="hidden" name="hash" value="{$csrfToken}" />
</form>
<script>
$(document).ready(() => {
u("#post-buttons1 .postFileSel").on("change", function() {
handleUpload.bind(this, 1)();
});
setupWallPostInputHandlers(1);
});
</script>
{/block}

View file

@ -33,14 +33,14 @@
</td>
<td>
{if $topic->getClub()->canBeModifiedBy($thisUser)}
<input type="checkbox" name="pin" n:attr="checked => $topic->isPinned()" /> {_pin_topic}<br />
<label><input type="checkbox" name="pin" n:attr="checked => $topic->isPinned()" /> {_pin_topic}</label><br />
{/if}
<input type="checkbox" name="close" n:attr="checked => $topic->isClosed()" /> {_close_topic}
<label><input type="checkbox" name="close" n:attr="checked => $topic->isClosed()" /> {_close_topic}</label>
</td>
</tr>
<tr>
<td>
<a class="button" href="/topic{$topic->getPrettyId()}/delete?hash={urlencode($csrfToken)}">{_delete_topic}</a>
<a id="_anotherDelete" class="button" href="/topic{$topic->getPrettyId()}/delete?hash={urlencode($csrfToken)}">{_delete_topic}</a>
</td>
<td>
<input type="hidden" name="hash" value="{$csrfToken}" />

View file

@ -409,7 +409,7 @@
</td>
<td>
<select name="likes.read", style="width: 164px;">
<option value="2" {if $user->getPrivacySetting('likes.read') == 2}selected{/if}>{_privacy_value_anybody}</option>
<option value="2" {if $user->getPrivacySetting('likes.read') == 2}selected{/if}>{_privacy_value_anybody_dative}</option>
<option value="0" {if $user->getPrivacySetting('likes.read') == 0}selected{/if}>{_privacy_value_only_me_dative}</option>
</select>
</td>

View file

@ -419,7 +419,7 @@
{else}
<div class="page_status" style="display: flex;">
<div n:class="audioStatus, $thatIsThisUser ? page_status_edit_button" id="page_status_text">
{$audioStatus->getName()}
<a {if !$thatIsThisUser}href="/audio0_{$audioStatus->getId()}"{/if}>{$audioStatus->getName()}</a>
</div>
</div>
{/if}
@ -458,8 +458,8 @@
</tr>
<tr n:if="!is_null($user->getBirthday())">
<td class="label"><span class="nobold">{_birth_date}:</span></td>
<td n:if="$user->getBirthdayPrivacy() == 0" class="data">{$user->getBirthday()->format('%e %B %Y')},
{tr("years", $user->getAge())}</td>
<td n:if="$user->getBirthdayPrivacy() == 0" class="data">{$user->getBirthday()->format('%e %B %Y')}{if $user->onlineStatus() != 2},
{tr("years", $user->getAge())}{/if}</td>
<td n:if="$user->getBirthdayPrivacy() == 1" class="data">{$user->getBirthday()->format('%e %B')}</td>
</tr>
</tbody>

View file

@ -36,9 +36,10 @@
count => $cCount,
page => $cPage,
model => "posts",
parent => $post }
parent => $post,
sort => $sort}
</div>
<div style="float: left; min-height: 100px; width: 32%;">
<div style="float: left; min-height: 100px; width: 32%;padding-left: 10px;width: 30%;">
<h4>{_actions}</h4>
{if isset($thisUser)}
{var $canDelete = $post->canBeDeletedBy($thisUser)}
@ -47,7 +48,7 @@
{/if}
{/if}
<a n:if="$canDelete ?? false" class="profile_link" style="display:block;width:96%;" href="/wall{$post->getPrettyId()}/delete">{_delete}</a>
<a n:if="$canDelete ?? false" id="_ajaxDelete" class="profile_link" style="display:block;width:96%;" href="/wall{$post->getPrettyId()}/delete">{_delete}</a>
<a
n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL) AND $post->getEditTime()"
style="display:block;width:96%;"

View file

@ -17,7 +17,9 @@
{/if}
{/if}
<link rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/stylesheet/styles.css" />
{* remove the "n:if" if you having issues with your theme *}
<link n:if="$theme->getId() != 'mobile_ovk'" rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/stylesheet/styles.css" />
{if $isXmas}
<link rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/resource/xmas.css" />

View file

@ -44,7 +44,7 @@
{if !$timeOnly}
{if $comment->canBeDeletedBy($thisUser)}
|
<a href="/comment{$comment->getId()}/delete">{_delete}</a>
<a href="/comment{$comment->getId()}/delete" id="_ajaxDelete">{_delete}</a>
{/if}
{if $comment->canBeEditedBy($thisUser)}
|

View file

@ -1,5 +1,18 @@
<h4 n:if="$showTitle ?? true">{_comments} ({$count})</h4>
<div>
<h4 n:if="$showTitle ?? true">{_comments} ({$count})</h4>
{if !is_null($sort) && $count > 5}
<a class="sort_link" n:attr="href => $sort == 'desc' ? '?sort=asc' : '?sort=desc'">
{if $sort == 'desc'}
{_new_first}
{else}
{_old_first}
{/if}
<div n:class="sort_link_icon, $sort == 'desc' ? sort_link_icon_desc : sort_link_icon_asc"></div>
</a>
{/if}
</div>
<div n:ifset="$thisUser" id="standaloneCommentBox">
{var $commentsURL = "/al_comments/create/$model/" . $parent->getId()}
{var $club = $parent instanceof \openvk\Web\Models\Entities\Post && $parent->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($parent->getTargetWall())) : $club}
@ -11,7 +24,7 @@
{if sizeof($comments) > 0}
<div class='scroll_container'>
<div class='scroll_node' n:foreach="$comments as $comment">
{include "comment.xml", comment => $comment}
{include "comment.xml", comment => $comment, no_reply_button => $readOnly}
</div>
</div>
<div style="margin-top: 11px;">

View file

@ -149,7 +149,7 @@
{/if}
</div>
<div n:if="!($forceNoCommentsLink ?? false) && $commentSection == true && $compact == false" class="post-menu-s">
<a n:if="$commentsCount > 3" href="/wall{$post->getPrettyId()}" class="expand_button">{_view_other_comments}</a>
<a n:if="$commentsCount > 3" href="/wall{$post->getPrettyId()}" class="expand_button">{_view_other_comments} ({$commentsCount - 3})</a>
{foreach $comments as $comment}
{include "../comment.xml", comment => $comment, $compact => true}
{/foreach}

View file

@ -2,7 +2,7 @@
{var $textAreaId = ($post ?? NULL) === NULL ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
{var $textAreaId = ($custom_id ?? NULL) === NULL ? $textAreaId : $custom_id}
<div id="write" class='model_content_textarea' style="padding: 5px 0;">
<div id="write" class='model_content_textarea' style="padding: 5px 0;" data-id="{is_null($owner) || gettype($owner) == 'integer' ? $owner : $owner->getId()}">
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
<textarea id="wall-post-input{$textAreaId}" placeholder="{_write}" name="text" style="width: 100%;resize: none;" class="small-textarea"></textarea>
<div>
@ -33,15 +33,15 @@
</script>
<label>
<input type="checkbox" name="as_group" onchange="onWallAsGroupClick(this)" /> {_post_as_group}
<input type="checkbox" name="as_group" onchange="onWallAsGroupClick(this)" checked /> {_post_as_group}
</label>
<label id="forceSignOpt" style="display: none;">
<label id="forceSignOpt" style="display: block;">
<input type="checkbox" name="force_sign" /> {_add_signature}
</label>
{/if}
{/if}
<label n:if="$anonEnabled" id="octoberAnonOpt">
<label n:if="$anonEnabled" id="octoberAnonOpt" style="display: none;">
<input type="checkbox" name="anon" /> {_as_anonymous}
</label>

View file

@ -1,5 +1,5 @@
<div class="content_divider">
<div class="content_title_expanded" onclick="hidePanel(this);">
<div class="content_title_expanded">
{_wall}
<nobold>
{tr("wall", $count)}

View file

@ -57,3 +57,4 @@ services:
- openvk\Web\Models\Repositories\Faves
- openvk\Web\Presenters\MaintenancePresenter
- openvk\Web\Presenters\NoSpamPresenter
- openvk\Web\Presenters\DevelopersPresenter

View file

@ -408,7 +408,15 @@ routes:
- url: "/humans.txt"
handler: "About->humansTxt"
- url: "/dev"
handler: "About->dev"
handler: "Developers->Main"
- url: "/dev/"
handler: "Developers->Main"
- url: "/dev/standalone"
handler: "Developers->Standalone"
- url: "/developers.php"
handler: "Developers->Standalone"
- url: "/dev/{text}"
handler: "Developers->DevelopersBaseArticle"
- url: "/iapi/getPhotosFromPost/{num}_{num}"
handler: "InternalAPI->getPhotosFromPost"
- url: "/iapi/getPostTemplate/{num}_{num}"

View file

@ -763,8 +763,9 @@
fill-opacity: .7;
}
.audioStatus span {
.audioStatus a {
color: #2B587A;
font-weight: bold;
}
.audioStatus span:hover {

416
Web/static/css/dev.css Normal file
View file

@ -0,0 +1,416 @@
.fl_r {
float: right;
}
.fl_l {
float: left;
}
.dev_parts_list {
width: 378px;
padding: 0;
}
.dev_part {
display: block;
padding: 15px 20px;
}
.dev_part:hover {
text-decoration: none;
background: #F7F7F7;
}
.dev_part_name {
display: block;
padding-bottom: 8px;
color: #4d7199;
font-weight: bold;
font-size: 1.2em;
}
.dev_part_desc {
color: #808080;
}
.dev_platform_info {
margin-top: 20px;
width: 200px;
padding: 15px 16px;
}
.dev_info_header {
display: block;
color: #4d7199;
font-weight: bold;
font-size: 1.2em;
border-bottom: 1px solid #DAE2E8;
margin-bottom: 8px;
}
.dev_api_status_good {
color: #038A07;
font-weight: bold;
}
.dev_api_status_bad {
color: #8A0307;
font-weight: bold;
}
.dev_last_news {
padding: 14px 16px 20px 16px;
width: 200px;
}
.dev_main_widget_cont {
height: 242px;
overflow: hidden;
}
.dev_head {
padding: 20px 10px 80px 40px;
background: #edf1f5;
-webkit-box-shadow: inset 0 -4px 2px -2px rgba(0,0,0,0.03);
-moz-box-shadow: inset 0 -4px 2px -2px rgba(0,0,0,0.03);
box-shadow: inset 0 -4px 2px -2px rgba(0,0,0,0.03);
margin: -10px -7px 0px -10px;
}
.dev_main_header {
color: #5c7b9b;
font-weight: bold;
font-size: 1.3em;
}
.dev_main_desc {
margin-top: 15px;
line-height: 160%;
max-width: 400px
}
.dev_main_narrow {
float: right;
width: 180px;
height: 100px;
padding: 35px 38px 0px 38px;
text-align: center;
}
.dev_sect {
display: block;
width: 168px;
height: 142px;
padding: 10px;
background: #f7f9fb;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
position: absolute;
-webkit-box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2);
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2);
color: #5c7b9b;
text-align: center;
font-weight: bold;
font-size: 1.2em;
line-height: 160%;
-webkit-transition: all 200ms ease-out;
-moz-transition: all 200ms ease-out;
-o-transition: all 200ms ease-out;
transition: all 200ms ease-out;
}
.dev_sect:hover {
text-decoration: none;
background: #fafafc;
margin-top: -8px;
-webkit-box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
-moz-box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
}
.dev_main_sections {
padding-top: 20px;
padding-bottom: 25px;
height: 150px;
}
.dev_sect_games {
}
.dev_sect_standalone {
margin-left: 209px;
}
.dev_sect_widgets {
margin-left: 419px;
}
.dev_sect_icon {
width: 95px;
height: 83px;
margin: 8px 35px 10px;
background: url('/assets/packages/static/openvk/img/dev/dev_icons.png') no-repeat;
}
.dev_sect_standalone .dev_sect_icon {
background-position: 0px -82px;
}
.dev_sect_widgets .dev_sect_icon {
background-position: 0px -163px;
}
#dev_steps_s .content {
padding: 0;
}
.dev_cont {
margin-top: -70px;
}
#dev_steps {
height: 48px;
background-color: #F7F7F7;
border-color: #DAE2E8;
border-style: solid;
border-width: 1px 0;
width: 520px;
}
#dev_steps_s {
border: 1px solid #3B6798;
margin-left: 152px;
margin-top: -1px;
padding-right: 2px;
width: 141px;
position: absolute;
color: #ffffff;
text-shadow: 0 1px 1px #35587E;
}
#dev_steps_s .dev_step,
#dev_steps_s .dev_step.first {
border: none;
}
#dev_steps_s .borders {
background-color: #6D8FB3;
border-color: #7E9CBC #5C82AB #5C82AB;
border-right: 1px solid #5C82AB;
border-style: solid;
border-width: 1px;
height: 48px;
overflow: hidden;
position: relative;
width: 100%;
}
#dev_steps_s .content {
padding: 0;
}
#dev_steps .dev_step {
border-left: 1px solid #FFFFFF;
cursor: pointer;
float: left;
}
#dev_steps .dev_step.first,
#dev_steps .dev_step.first div {
border-color: #F7F7F7;
}
.dev_step div {
float: left;
height: 41px;
padding: 7px 0 0 22px;
width: 120px;
font-size: 10px;
}
#dev_steps .dev_step div {
border-left: 1px solid #EAEAEA;
padding: 7px 0 0 20px;
}
.dev_step div b {
font-size: 11px;
line-height: 18px;
}
.dev_step.last div {
width: 200px;
}
.dev_steps_c {
width: 600px;
margin-top: 10px;
overflow: hidden;
border: 1px solid #FFFFFF;
}
.content {
width: 2000px;
}
.step {
width: 587px;
margin-right: 13px;
height: 500px;
float: left;
}
.introPage .info {
display: block;
border-bottom: 1px solid #d9d9d9;
padding: 15px 0px 20px 70px;
height: 80px;
color: #333333;
}
.introPage .info:focus {
outline: none;
}
.introPage .info.first {
padding: 0px 0px 20px 70px;
}
.introPage .info:hover {
text-decoration: none;
}
.introPage .info .header {
display: block;
font-weight: bold;
margin-bottom: 3px;
color: #2B587A;
}
.introPage .info .more {
display: block;
margin-top: 6px;
color: #2B587A;
}
.introPage .info.apps {
background: url('/assets/packages/static/openvk/img/dev/dev_apps.png') 0px 6px no-repeat;
}
.introPage .info.sites {
background: url('/assets/packages/static/openvk/img/dev/dev_sites.png') 0px 21px no-repeat;
}
.introPage .info.mobile {
background: url('/assets/packages/static/openvk/img/dev/dev_mobile.png') 0px 21px no-repeat;
}
.introPage .info.shops {
background: url('/assets/packages/static/openvk/img/dev/dev_shops.png') 0px 21px no-repeat;
border-bottom: none;
}
.wk_header,
.dev_page_cont .wk_header {
border-bottom: none;
font-size: 1.2em;
}
.introPage .listing {
padding-left: 14px;
}
.listing span {
font-size: 11px;
font-weight: normal;
}
.listing span.bold {
font-weight: bold;
}
h3 {
border-bottom: 1px solid #B9C4DA;
font-size: 12px;
color: #45688E;
margin-bottom: 0px;
font-weight: bold;
padding-bottom: 2px;
}
.dev_sidebar {
margin: 5px 5px 5px 5px;
background: #F0F2F4;
width: 156px;
padding: 0px 10px 10px 10px;
}
.dev_section_menu, .dev_section_submenu {
display: block;
padding: 4px 8px 5px 8px;
overflow: hidden;
text-overflow: ellipsis;
}
.dev_section_menu {
margin-top: 10px;
font-weight: bold;
}
.dev_section_menu:hover, .dev_section_submenu:hover {
text-decoration: none;
background: #E0E5E9;
}
.dev_section_submenu {
padding-left: 20px;
}
.dev_mlist_sel {
background: #5e82a8;
color: #FFFFFF;
}
.dev_mlist_sel:hover {
background: #5e82a8;
}
.knowledgeBaseArticle {
float: left;
width: 424px;
max-width: 424px;
}
.knowledgeBaseArticle img {
max-width: 424px;
}
pre {
padding: 10px;
border-left: 9px solid #C9D8DF;
border-bottom: 2px solid #EBEFF2;
background-color: #F5F7F8;
margin: 10px 0px 0px 0px;
}
h1 {
margin: 0px;
padding: 0px;
font-size: 14px; }
h1 a { color: white; text-decoration: none; }
h1 a:hover { color: white; text-decoration: underline; }
h1 em { font-style: normal; border-bottom: solid 1px #DAE1E8; }
h2 {
font-size: 11px;
margin: 0px;
padding: 0px; }
h6 { border-bottom: 1px solid #DAE1E8;
color: #36638E;
margin:0px; padding:0px;
font-size: 14px;
padding-bottom: 5px; }
h3 {
color: #444;
font-size: 11px;
font-weight: normal;
margin: 0px;
padding: 0px; }
h4 {
color: #36638E;
font-size: 11px;
margin: 0px 0px 6px 8px;}
h4 .edit { display: inline; margin-left: 8px; }
h4 .edit a { color: lightgrey; }
h4 .edit a:hover { color: #36638E; }
h5 {
color: #36638E;
font-size: 11px;
margin: 0px 0px 6px 8px; }
h5 .edit { display: inline; margin-left: 8px; }
h5 .edit a { color: lightgrey; }
h5 .edit a:hover { color: #36638E; }
h3 {
border-bottom:1px solid #B9C4DA;
font-size: 12px;
color:#45688E;
margin-bottom: 0px;
font-weight: bold;
padding-bottom:2px;
}

View file

@ -49,7 +49,7 @@ body.dimmed > .dimmer #absolute_territory {
.ovk-diag-body {
padding: 20px;
overflow-y: auto;
max-height: 80vh
max-height: 83vh
}
.ovk-diag-action {

View file

@ -14,6 +14,10 @@ body {
line-height: 1.19;
}
body.ajax_request_made {
cursor: progress;
}
body, .ovk-fullscreen-dimmer, .ovk-photo-view-dimmer {
scrollbar-gutter: stable both-edges;
}
@ -876,7 +880,7 @@ h4 {
}
.post-geo {
margin: 1px 0px;
margin: 8px 0px 2px -3px;
padding: 0 4px;
}
@ -1566,6 +1570,10 @@ body.scrolled .toTop:hover, .toTop.has_down:hover {
color: #3c3c3c;
}
.post-has-geo.appended-geo {
padding: 6px 0px;
}
.post-source #remove_source_button, #small_remove_button {
display: inline-block;
background-repeat: no-repeat;
@ -1880,6 +1888,7 @@ body.scrolled .toTop:hover, .toTop.has_down:hover {
#ovkDraw {
border: 1px solid #757575;
min-height: 510px;
}
#ovkDraw .lc-drawing.with-gui {
@ -1888,6 +1897,7 @@ body.scrolled .toTop:hover, .toTop.has_down:hover {
#ovkDraw .literally {
border-radius: 0;
height: 510px;
}
#ovkDraw .literally .lc-picker,
@ -2666,7 +2676,8 @@ a.poll-retract-vote {
}
.post-buttons .vertical-attachment .vertical-attachment-content {
max-height: 27px;
/*max-height: 27px;*/
padding: 3px 2px;
}
.vertical-attachment .vertical-attachment-content .overflowedName {
@ -3197,6 +3208,11 @@ a.poll-retract-vote {
display: flex;
align-items: center;
gap: 1px;
padding: 5px 9px;
}
.post-buttons .attachment_note {
padding: 3px 0px;
}
.attachment_note svg {
@ -3212,6 +3228,10 @@ a.poll-retract-vote {
height: 12px;
}
.attachments .attachment_note {
padding: 5px 5px;
}
#notesList
{
overflow-y: scroll;
@ -3248,7 +3268,7 @@ body.article .floating_sidebar, body.article .page_content {
display: none;
position: absolute;
z-index: 128;
width: 100%;
width: 98%;
min-height: 100vh;
padding: 20px;
box-sizing: border-box;
@ -3282,6 +3302,7 @@ body.article .floating_sidebar, body.article .page_content {
.articleView_author > div {
display: flex;
flex-direction: column;
margin-top: 3px;
}
.articleView_author > div > span {
@ -3379,6 +3400,7 @@ body.article .floating_sidebar, body.article .page_content {
display: flex;
flex-direction: column;
gap: 22px;
padding: 5px 10px;
}
.sugglist {
@ -3652,7 +3674,7 @@ hr {
.entity_vertical_list {
display: flex;
flex-direction: column;
gap: 3px;
gap: 10px;
height: 197px;
overflow-y: auto;
}
@ -3660,6 +3682,7 @@ hr {
.entity_vertical_list.scroll_container {
height: unset;
overflow-y: unset;
padding: 5px;
}
.entity_vertical_list .entity_vertical_list_item {
@ -3677,12 +3700,16 @@ hr {
}
.entity_vertical_list.m_mini .entity_vertical_list_item .first_column {
gap: 10px;
gap: 13px;
}
.entity_vertical_list.m_mini .entity_vertical_list_item:hover .first_column a {
text-decoration: underline;
}
.entity_vertical_list.m_mini .entity_vertical_list_item .first_column .avatar img {
width: 30px;
height: 30px;
width: 40px;
height: 40px;
}
.entity_vertical_list .entity_vertical_list_item .avatar {
@ -3813,12 +3840,13 @@ hr {
display: none;
position: fixed;
top: -10%;
background: rgba(26, 26, 26, 0.9);;
background: rgba(0, 0, 0, 0.8);
box-shadow: 0px 0px 2px 0px black;
padding-top: 12px;
width: 91px;
height: 25px;
text-align: center;
border-radius: 1px;
border-radius: 2px;
margin: auto;
left: 0;
right: 0;
@ -3917,6 +3945,11 @@ hr {
height: 25px;
}
.object_fit_ava {
object-fit: cover;
object-position: top;
}
.like_tooltip_wrapper .like_tooltip_body a {
height: 25px;
}
@ -4027,7 +4060,7 @@ hr {
#docs_page_wrapper .container_white {
display: flex;
flex-direction: column;
padding: 5px 10px;
padding: 10px 10px;
}
#docs_page_wrapper .docs_page_content.docs_page_gallery .scroll_container {
@ -4170,11 +4203,12 @@ hr {
justify-content: center;
border-radius: 2px;
height: 17px;
padding: 2px 0px;
padding: 3px 0px;
}
.docListViewItem .doc_icon.no_image span {
color: #6b6b6b;
font-weight: bold;
}
.doc_icon.no_image span::before {
@ -4259,8 +4293,8 @@ hr {
.attachments .docGalleryItem {
display: block;
min-width: 170px;
height: 170px;
width: 50%;
min-height: 170px;
width: 60%;
margin-bottom: 4px;
}
@ -4286,3 +4320,23 @@ hr {
.deleted_mark_average {
padding: 5px 61px;
}
.sort_link {
padding: 5px 2px;
display: inline-block;
}
.sort_link_icon {
background: url(/assets/packages/static/openvk/img/wall.png?v=3) no-repeat;
display: inline-block;
height: 11px;
width: 9px;
}
.sort_link_icon_desc {
background-position: 0px -15px;
}
.sort_link_icon_asc {
background-position: -11px -15px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

147
Web/static/js/al_dev.js Normal file
View file

@ -0,0 +1,147 @@
var nav = null;
function init_dev_steps(step) {
this.step = step;
this.moving = false;
this.steps_glass = document.getElementById('dev_steps_s');
this.steps_glass_c = this.steps_glass.querySelector('.content');
this.steps_wrap = document.getElementById('dev_steps_c');
this.steps_content = this.steps_wrap.querySelector('.content');
this.easeInOut = function(t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
this.move = function(toStep) {
var self = this;
if (toStep === this.step || this.moving) return;
this.moving = true;
var startGlass = (this.step - 1) * 140;
var startContent = (1 - this.step) * 600;
var startHeight = this.steps_wrap.offsetHeight;
var endGlass = (toStep - 1) * 140;
var endContent = (1 - toStep) * 600;
var targetNode = document.getElementById('dev_step' + toStep + '_c');
targetNode.style.position = 'absolute';
targetNode.style.left = '-5000px';
var endHeight = targetNode.querySelector('.borders').offsetHeight + 12;
targetNode.style.position = 'static';
targetNode.style.left = 'auto';
for (var i = 1; i <= 3; i++) {
var stepEl = document.getElementById('dev_step' + i + '_c');
stepEl.style.height = 'auto';
stepEl.style.position = 'static';
stepEl.style.left = 'auto';
}
var duration = 400;
var startTime = Date.now();
var startGlassWidth = (this.step === 3) ? 236 : 141;
var endGlassWidth = (toStep === 3) ? 236 : 141;
function animate() {
var elapsed = Date.now() - startTime;
var progress = Math.min(elapsed / duration, 1);
var easedProgress = self.easeInOut(progress, 0, 1, 1);
var currentGlass = startGlass + (endGlass - startGlass) * easedProgress;
var currentContent = startContent + (endContent - startContent) * easedProgress;
var currentHeight = startHeight + (endHeight - startHeight) * easedProgress;
var currentGlassWidth = startGlassWidth + (endGlassWidth - startGlassWidth) * easedProgress;
self.steps_glass.style.marginLeft = currentGlass + 'px';
self.steps_glass_c.style.marginLeft = (-currentGlass - 2) + 'px';
self.steps_content.style.marginLeft = currentContent + 'px';
self.steps_wrap.style.height = currentHeight + 'px';
self.steps_glass.style.width = currentGlassWidth + 'px';
if (progress < 1) {
requestAnimationFrame(animate);
} else {
self.step = toStep;
self.moving = false;
if (window.history && window.history.replaceState) {
window.history.replaceState(null, null, '#devstep' + toStep);
} else {
location.hash = 'devstep' + toStep;
}
}
}
requestAnimationFrame(animate);
};
this.steps_wrap.style.height = 'auto';
var initialHeight = document.getElementById('dev_step' + this.step + '_c').querySelector('.borders').offsetHeight + 12;
this.steps_wrap.style.height = initialHeight + 'px';
this.steps_glass.style.marginLeft = ((this.step - 1) * 140) + 'px';
this.steps_glass_c.style.marginLeft = (-(this.step - 1) * 140 - 2) + 'px';
this.steps_content.style.marginLeft = ((1 - this.step) * 600) + 'px';
this.steps_glass.style.width = (this.step === 3 ? 236 : 141) + 'px';
this.steps_glass.style.display = 'block';
this.steps_content.style.display = 'block';
for (var i = 1; i <= 3; i++) {
var stepElement = document.getElementById('dev_step' + i + '_c');
stepElement.style.height = 'auto';
stepElement.style.position = 'static';
stepElement.style.left = 'auto';
}
}
function dev_step(toStep) {
if (nav) {
nav.move(toStep);
}
return false;
}
function onDomReady(callback) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', callback);
} else {
callback();
}
}
window.prevSection = false;
function slideSection(obj, directly) {
if (!directly) obj = obj.parentNode.children[1];
if (window.prevSection && window.prevSection !== obj) {
window.prevSection.style.display = 'none';
}
window.prevSection = obj;
obj.style.display = obj.style.display === 'none' ? 'block' : 'none';
}
onDomReady(function() {
var step = 1;
var hash = location.hash;
var match = hash.match(/devstep(\d)/);
if (match) {
var hashStep = parseInt(match[1]);
if (hashStep >= 1 && hashStep <= 3) {
nav = new init_dev_steps(hashStep);
dev_step(hashStep);
}
} else {
nav = new init_dev_steps(1);
}
});

View file

@ -333,7 +333,7 @@ async function __docAttachment(form, ctx = "wall", source = "user", source_arg =
<text id="photo_com_title_photos">
${tr("select_doc")}
</text>
<span style="display: inline-flex;gap: 7px;">
<span style="display: inline-flex;gap: 7px;margin-left: 5px;">
${source != "user" ? `<a id="_doc_picker_go_to_my">${tr("go_to_my_documents")}</a>`: ""}
<a id="_doc_picker_upload">${tr("upload_button")}</a>
</span>

View file

@ -23,6 +23,7 @@ tippy.delegate("body", {
target: '.mention',
theme: "light vk",
content: "⌛",
delay: 300,
allowHTML: true,
interactive: true,
interactiveDebounce: 500,

View file

@ -176,7 +176,7 @@ window.player = new class {
}
}
if(window.player.listen_coef > 10) {
if(window.player.listen_coef > 5) {
this.__countListen()
window.player.listen_coef = -10
}
@ -845,22 +845,14 @@ u(document).on('click', '.audioEntry .playerButton > .playIcon', async (e) => {
if(!window.player.hasTrackWithId(id) && !window.player.isAtAudiosPage()) {
let _nodes = null
if(u(e.target).closest('.attachments').length > 0) {
window.player.connectionType = '.attachments'
_nodes = u(e.target).closest('.attachments').find('.audioEmbed').nodes
} else if(u(e.target).closest('.content_list').length > 0) {
window.player.connectionType = '.content_list'
_nodes = u(e.target).closest('.content_list').find('.audioEmbed').nodes
} else if(u(e.target).closest('.generic_audio_list').length > 0) {
window.player.connectionType = '.generic_audio_list'
_nodes = u(e.target).closest('.generic_audio_list').find('.audioEmbed').nodes
} else if(u(e.target).closest('.audiosInsert').length > 0) {
window.player.connectionType = '.audiosInsert'
_nodes = u(e.target).closest('.audiosInsert').find('.audioEmbed').nodes
} else if(u(e.target).closest('.scroll_container').length > 0) {
window.player.connectionType = '.scroll_container'
_nodes = u(e.target).closest('.scroll_container').find('.audioEmbed').nodes
}
try_these_containers = [".attachments", ".content_list", ".generic_audio_list", ".audiosInsert", ".scroll_container", ".container_gray"]
try_these_containers.forEach(__container => {
if(u(e.target).closest(__container).length > 0) {
window.player.connectionType = __container
_nodes = u(e.target).closest(__container).find('.audioEmbed').nodes
}
})
window.player.tracks = []
_nodes.forEach(el => {
@ -1859,7 +1851,7 @@ function showAudioAttachment(type = 'form', form = null)
}
let is_attached = false
if(type == 'form') {
is_attached = (u(form).find(`.post-vertical .vertical-attachment[data-id='${id}']`)).length > 0
is_attached = (u(form).find(`.post-vertical .vertical-attachment[data-type='audio'][data-id='${id}']`)).length > 0
} else {
is_attached = (u(form).find(`.PE_audios .vertical-attachment[data-id='${id}']`)).length > 0
}

View file

@ -12,7 +12,7 @@ $(document).on("change", ".photo_ajax_upload_button", (e) => {
return;
}
if(file.size > 5 * 1024 * 1024) {
if(file.size > window.openvk.max_filesize_mb * 1024 * 1024) {
MessageBox(tr("error"), tr("max_filesize", 5), [tr("ok")], [() => {Function.noop}])
return;
}
@ -88,7 +88,6 @@ $(document).on("click", ".photo_upload_container #endUploading", (e) => {
data.append("hash", u("meta[name=csrf]").attr("value"))
let xhr = new XMLHttpRequest()
// в самом вк на каждое изменение описания отправляется свой запрос, но тут мы экономим запросы
xhr.open("POST", "/photos/upload?act=finish&album="+document.getElementById("album").value)
xhr.onloadstart = () => {
@ -108,10 +107,10 @@ $(document).on("click", ".photo_upload_container #endUploading", (e) => {
document.querySelector(".page_content .insertPhotos").innerHTML = ""
document.getElementById("endUploading").style.display = "none"
NewNotification(tr("photos_successfully_uploaded"), tr("click_to_go_to_album"), null, () => {window.router.route({url:`/album${result.owner}_${result.album}`})})
window.router.route({url:`/album${result.owner}_${result.album}`})
document.querySelector(".whiteBox").style.display = "block"
document.querySelector(".insertAgain").append(document.getElementById("fakeButton"))
/*document.querySelector(".whiteBox").style.display = "block"
document.querySelector(".insertAgain").append(document.getElementById("fakeButton"))*/
}
e.currentTarget.removeAttribute("disabled")

View file

@ -606,7 +606,22 @@ function reportClub(club_id) {
]);
}
$(document).on("click", "#_photoDelete, #_videoDelete", function(e) {
$(document).on("click", "#_ajaxDelete", function(e) {
MessageBox(tr('warning'), tr('question_confirm'), [
tr('yes'),
tr('no')
], [
() => {
window.router.route(e.target.href)
},
Function.noop
]);
e.stopPropagation()
return e.preventDefault();
});
$(document).on("click", "#_photoDelete, #_videoDelete, #_anotherDelete", function(e) {
var formHtml = "<form id='tmpPhDelF' action='" + u(this).attr("href") + "' >";
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
formHtml += "</form>";
@ -825,6 +840,7 @@ tippy.delegate("body", {
target: '.client_app',
theme: "light vk",
content: "⌛",
delay: 400,
allowHTML: true,
interactive: true,
interactiveDebounce: 500,
@ -864,6 +880,7 @@ tippy.delegate('body', {
target: `.post-like-button[data-type]:not([data-likes="0"])`,
theme: "special vk",
content: "⌛",
delay: 400,
allowHTML: true,
interactive: true,
interactiveDebounce: 500,
@ -900,7 +917,7 @@ tippy.delegate('body', {
that._likesList.items.forEach(item => {
final_template.find('.like_tooltip_body .like_tooltip_body_grid').append(`
<a title="${escapeHtml(item.first_name + " " + item.last_name)}" href='/id${item.id}'><img src='${item.photo_50}' alt='.'></a>
<a title="${escapeHtml(item.first_name + " " + item.last_name)}" href='/id${item.id}'><img class="object_fit_ava" src='${item.photo_50}' alt='.'></a>
`)
})
that.setContent(final_template.nodes[0].outerHTML)
@ -1123,7 +1140,14 @@ u(document).on("click", "#editPost", async (e) => {
return
}
const new_post_html = await (await fetch(`/iapi/getPostTemplate/${id[0]}_${id[1]}?type=${type}`, {
let is_at_post_page = false
try {
if(location.pathname.indexOf("wall") != -1 && location.pathname.split("_").length == 2) {
is_at_post_page = true
}
} catch(e) {}
const new_post_html = await (await fetch(`/iapi/getPostTemplate/${id[0]}_${id[1]}?type=${type}&from_page=${is_at_post_page ? "post" : "another"}`, {
'method': 'POST'
})).text()
u(ev.target).removeClass('lagged')
@ -1174,7 +1198,7 @@ async function __uploadToTextarea(file, textareaNode) {
const rand = random_int(0, 1000)
textareaNode.find('.post-horizontal').append(`<a id='temp_filler${rand}' class="upload-item lagged"><img src='${temp_url}'></a>`)
const res = await fetch(`/photos/upload`, {
const res = await fetch(`/photos/upload?upload_context=${textareaNode.nodes[0].dataset.id}`, {
method: 'POST',
body: form_data
})
@ -1342,7 +1366,7 @@ u(document).on("click", "#__photoAttachment", async (e) => {
if(album == 0) {
photos = await window.OVKAPI.call('photos.getAll', {'owner_id': window.openvk.current_id, 'photo_sizes': 1, 'count': photos_per_page, 'offset': page * photos_per_page})
} else {
photos = await window.OVKAPI.call('photos.get', {'owner_id': window.openvk.current_id, 'album_id': album, 'photo_sizes': 1, 'count': photos_per_page, 'offset': page * photos_per_page})
photos = await window.OVKAPI.call('photos.get', {'owner_id': club != 0 ? Math.abs(club) * -1 : window.openvk.current_id, 'album_id': album, 'photo_sizes': 1, 'count': photos_per_page, 'offset': page * photos_per_page})
}
} catch(e) {
u("#attachment_insert_count h4").html(tr("is_x_photos", -1))
@ -1432,7 +1456,7 @@ u(document).on("click", "#__photoAttachment", async (e) => {
window.openvk.photoalbums = await window.OVKAPI.call('photos.getAlbums', {'owner_id': club != 0 ? Math.abs(club) * -1 : window.openvk.current_id})
}
window.openvk.photoalbums.items.forEach(item => {
u('.ovk-diag-body #albumSelect').append(`<option value="${item.vid}">${ovk_proc_strtr(escapeHtml(item.title), 20)}</option>`)
u('.ovk-diag-body #albumSelect').append(`<option value="${item.id}">${ovk_proc_strtr(escapeHtml(item.title), 20)}</option>`)
})
})
@ -1645,7 +1669,7 @@ u(document).on('click', '#__notesAttachment', async (e) => {
insert_place.append(tr('no_notes'))
}
notes.notes.forEach(note => {
notes.items.forEach(note => {
is_attached = (form.find(`.upload-item[data-type='note'][data-id='${note.owner_id}_${note.id}']`)).length > 0
insert_place.append(`
<div class='display_flex_row _content' data-attachmentdata="${note.owner_id}_${note.id}" data-name='${escapeHtml(note.title)}'>
@ -1943,10 +1967,10 @@ async function repost(id, repost_type = 'post') {
title: tr('share'),
unique_name: 'repost_modal',
body: `
<div class='display_flex_column' style='gap: 1px;'>
<div class='display_flex_column' style='gap: 5px;'>
<b>${tr('auditory')}</b>
<div class='display_flex_column'>
<div class='display_flex_column' style="gap: 2px;padding-left: 1px;">
<label>
<input type="radio" name="repost_type" value="wall" checked>
${tr("in_wall")}
@ -1962,12 +1986,14 @@ async function repost(id, repost_type = 'post') {
<b>${tr('your_comment')}</b>
<input type='hidden' id='repost_attachments'>
<textarea id='repostMsgInput' placeholder='...'></textarea>
<div style="padding-left: 1px;">
<input type='hidden' id='repost_attachments'>
<textarea id='repostMsgInput' placeholder='...'></textarea>
<div id="repost_signs" class='display_flex_column' style='display:none;'>
<label><input type='checkbox' name="asGroup">${tr('post_as_group')}</label>
<label><input type='checkbox' name="signed">${tr('add_signature')}</label>
<div id="repost_signs" class='display_flex_column' style='display:none;'>
<label><input type='checkbox' name="asGroup">${tr('post_as_group')}</label>
<label><input type='checkbox' name="signed">${tr('add_signature')}</label>
</div>
</div>
</div>
`,
@ -2036,7 +2062,7 @@ async function repost(id, repost_type = 'post') {
]
});
u('.ovk-diag-body').attr('style', 'padding: 14px;')
u('.ovk-diag-body').attr('style', 'padding: 18px;')
u('.ovk-diag-body').on('change', `input[name='repost_type']`, (e) => {
const value = e.target.value
@ -2062,6 +2088,7 @@ async function repost(id, repost_type = 'post') {
if(window.openvk.writeableClubs.items.length < 1) {
u(`input[name='repost_type'][value='group']`).attr('disabled', 'disabled')
u(`input[name='repost_type'][value='group']`).closest("label").addClass("lagged")
}
}
@ -2371,7 +2398,10 @@ async function __processPaginatorNextPage(page)
const new_url = new URL(location.href)
new_url.hash = page
history.replaceState(null, null, new_url)
//history.replaceState(null, null, new_url)
showMoreObserver.disconnect()
showMoreObserver.observe(u('.paginator:not(.paginator-at-top)').nodes[0])
if(typeof __scrollHook != 'undefined') {
__scrollHook(page)
@ -2397,6 +2427,9 @@ const showMoreObserver = new IntersectionObserver(entries => {
if(target.length < 1 || target.hasClass('paginator-at-top')) {
return
}
if(target.hasClass('lagged')) {
return
}
const current_url = new URL(location.href)
if(current_url.searchParams && !isNaN(parseInt(current_url.searchParams.get('p')))) {
@ -2437,8 +2470,7 @@ u(document).on('click', '#__sourceAttacher', (e) => {
MessageBox(tr('add_source'), `
<div id='source_flex_kunteynir'>
<span>${tr('set_source_tip')}</span>
<!-- давай, копируй ссылку и переходи по ней -->
<input type='text' maxlength='400' placeholder='https://www.youtube.com/watch?v=lkWuk_nzzVA'>
<input type='text' maxlength='400' placeholder='...'>
</div>
`, [tr('cancel')], [
() => {Function.noop}
@ -2546,7 +2578,12 @@ u(document).on('mouseover mousemove mouseout', `div[data-tip='simple']`, (e) =>
})
function setStatusEditorShown(shown) {
document.getElementById("status_editor").style.display = shown ? "block" : "none";
if(shown) {
document.getElementById("status_editor").style.display = "block"
document.querySelector("#status_editor input").focus()
} else {
document.getElementById("status_editor").style.display = "none"
}
}
u(document).on('click', (event) => {
@ -2648,7 +2685,7 @@ u(document).on('click', "#__geoAttacher", async (e) => {
${tplMapIcon}
<span>${escapeHtml(geo_name)}</span>
<div id="small_remove_button"></div>
`)
`).addClass("appended-geo")
}, () => {}]
})
@ -2951,3 +2988,28 @@ u(document).on("submit", "#additional_fields_form", (e) => {
}
})
})
if(Number(localStorage.getItem('ux.gif_autoplay') ?? 0) == 1) {
const showMoreObserver = new IntersectionObserver(entries => {
entries.forEach(async x => {
doc_item = x.target.closest(".docGalleryItem")
if(doc_item.querySelector(".play-button") != null) {
if(x.isIntersecting) {
doc_item.classList.add("playing")
} else {
doc_item.classList.remove("playing")
}
}
})
}, {
root: null,
rootMargin: '0px',
threshold: 0,
})
if(u('.docGalleryItem').length > 0) {
u('.docGalleryItem').nodes.forEach(item => {
showMoreObserver.observe(item)
})
}
}

View file

@ -202,7 +202,7 @@ window.router = new class {
if(this.prev_page_html && this.prev_page_html.pathname != location.pathname) {
this.prev_page_html = null
}
const push_url = params.push_state ?? true
const next_page_url = new URL(url)
if(push_url) {
@ -210,6 +210,8 @@ window.router = new class {
} else {
history.replaceState({'from_router': 1}, '', url)
}
u('body').addClass('ajax_request_made')
const parser = new DOMParser
const next_page_request = await fetch(next_page_url, {
@ -227,6 +229,8 @@ window.router = new class {
this.__closeMsgs()
this.__unlinkObservers()
u('body').removeClass('ajax_request_made')
try {
this.__appendPage(parsed_content)
@ -397,8 +401,10 @@ window.addEventListener('popstate', (e) => {
return
}*/
window.router.route({
url: location.href,
push_state: false,
})
if(e.state != null) {
window.router.route({
url: location.href,
push_state: false,
})
}
})

View file

@ -6429,6 +6429,21 @@ tools.ToolWithStroke = ToolWithStroke = (function(superClass) {
module.exports = tools;
},{}]},{},[22])(22)
});
});
document.addEventListener('keydown', function (e) {
const redoBtn = document.querySelector(".lc-redo")
const undoBtn = document.querySelector(".lc-undo")
if (e.ctrlKey && undoBtn && redoBtn) {
if ((e.code === "KeyY") || (e.code === "KeyZ" && e.shiftKey)) {
e.preventDefault()
redoBtn.click()
}
else if (e.code === "KeyZ") {
e.preventDefault()
undoBtn.click()
}
}
})

View file

@ -0,0 +1 @@
datatypes fallback

1
data/developers/help.md Normal file
View file

@ -0,0 +1 @@
help fallback

68
data/developers/main.md Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
methods fallback

View file

@ -0,0 +1 @@
native fallback

1
data/developers/rules.md Normal file
View file

@ -0,0 +1 @@
rules fallback

1
data/developers/sites.md Normal file
View file

@ -0,0 +1 @@
sites fallback

View file

@ -505,7 +505,7 @@
"edit_photo" = "Edit photo";
"creating_album" = "Creating album";
"delete_photo" = "Delete photo";
"sure_deleting_photo" = "Do you really want to delete this picture?";
"sure_deleting_photo" = "Do you sure you want to delete this photo from album?";
"upload_photo" = "Upload photo";
"photo" = "Photo";
"upload_button" = "Upload";
@ -619,6 +619,7 @@
"notes_closed" = "You can't attach a note to the post because only you can see them.<br> You can change this in <a href=\"/settings?act=privacy\">settings</a>.";
"do_not_attach_note" = "Do not attach a note";
"something_is_supported_from_xhtml" = "<a href='/kb/notes'>Something</a> from (X)HTML supported.";
"something" = "Something";
"supports_xhtml" = "from (X)HTML supported.";
@ -867,6 +868,9 @@
"sort_up" = "Sort by ID up";
"sort_down" = "Sort by ID down";
"new_first" = "New frist";
"old_first" = "Old first";
/* Videos */
"videos" = "Videos";
@ -1196,6 +1200,7 @@
"coins_other" = "$1 votes";
"users_gifts" = "Gifts";
"sent" = "Sent";
/* Apps */
"app" = "Application";
@ -2322,6 +2327,8 @@
"roll_back" = "rollback";
"roll_backed" = "rollbacked";
"nospam_prevention" = "This action will affect a lot of data. Are you sure you want to apply?";
/* RSS */
"post_deact_in_general" = "Page deletion";

View file

@ -489,7 +489,7 @@
"edit_photo" = "Изменить фотографию";
"creating_album" = "Создание альбома";
"delete_photo" = "Удалить фотографию";
"sure_deleting_photo" = "Вы уверены, что хотите удалить эту фотографию?";
"sure_deleting_photo" = "Вы уверены, что хотите удалить эту фотографию из альбома?";
"upload_photo" = "Загрузить фотографию";
"photo" = "Фотография";
"upload_button" = "Загрузить";
@ -603,6 +603,7 @@
"notes_closed" = "Вы не можете прикрепить заметку к записи, так как ваши заметки видны только вам.<br><br> Вы можете поменять это в <a href=\"/settings?act=privacy\">настройках</a>.";
"do_not_attach_note" = "Не прикреплять заметку";
"something_is_supported_from_xhtml" = "<a href='/kb/notes'>Кое-что</a> из (X)HTML поддерживается.";
"something" = "Кое-что";
"supports_xhtml" = "из (X)HTML поддерживается.";
@ -825,6 +826,9 @@
"sort_up" = "Сортировать по дате создания вверх";
"sort_down" = "Сортировать по дате создания вниз";
"new_first" = "Сначала новые";
"old_first" = "Сначала старые";
/* Videos */
"videos" = "Видеозаписи";
@ -1138,6 +1142,7 @@
"coins_many" = "$1 голосов";
"coins_other" = "$1 голосов";
"users_gifts" = "Подарки";
"sent" = "Отправлено";
/* Apps */
"app" = "Приложение";
@ -2217,6 +2222,8 @@
"roll_back" = "откатить";
"roll_backed" = "откачено";
"nospam_prevention" = "Данное действие затронет множество данных. Вы действительно хотите применить?";
/* RSS */
"post_deact_in_general" = "Удаление страницы";

View file

@ -448,6 +448,7 @@
"notes_closed" = "Vy ne možete prikrepití zametku k zapisi, tak kak vaši zametki vidny tolíko vam.<br><br> Vy možete pomenjatí eto v <a href=\"/settings?act=privacy\">nastrojkah</a>.";
"do_not_attach_note" = "Ne prikrepljatí zametku";
"something_is_supported_from_xhtml" = "<a href='/kb/notes'>Koe-čto</a> iz (X)HTML podderživaetsja.";
"something" = "Koe-čto";
"supports_xhtml" = "iz (X)HTML podderživaetsja.";

View file

@ -579,6 +579,7 @@
"notes_closed" = "Ви не можете прикріпити нотатку до запису, оскільки Ваші нотатки видно тільки Вам.<br><br> Ви можете змінити це в <a href=\"/settings?act=privacy\">налаштуваннях</a>.";
"do_not_attach_note" = "Не прикріплювати нотатку";
"something_is_supported_from_xhtml" = "<a href='/kb/notes'>Певні</a> теги з (X)HTML підтримується.";
"something" = "Певні";
"supports_xhtml" = "теги з (X)HTML підтримується.";