diff --git a/ServiceAPI/Wall.php b/ServiceAPI/Wall.php
index 628ceb22..16358e93 100644
--- a/ServiceAPI/Wall.php
+++ b/ServiceAPI/Wall.php
@@ -2,17 +2,19 @@
namespace openvk\ServiceAPI;
use openvk\Web\Models\Entities\Post;
use openvk\Web\Models\Entities\User;
-use openvk\Web\Models\Repositories\Posts;
+use openvk\Web\Models\Repositories\{Posts, Notes};
class Wall implements Handler
{
protected $user;
protected $posts;
+ protected $notes;
function __construct(?User $user)
{
$this->user = $user;
$this->posts = new Posts;
+ $this->notes = new Notes;
}
function getPost(int $id, callable $resolve, callable $reject): void
@@ -71,4 +73,25 @@ class Wall implements Handler
$resolve($post->getId());
}
+
+ function getMyNotes(callable $resolve, callable $reject)
+ {
+ $myNotes = $this->notes->getUserNotes($this->user, 1, $this->notes->getUserNotesCount($this->user));
+
+ $arr = [
+ "count" => sizeof($myNotes),
+ "closed" => $this->user->getPrivacySetting("notes.read"),
+ "items" => [],
+ ];
+
+ foreach($myNotes as $note) {
+ $arr["items"][] = [
+ "id" => $note->getId(),
+ "name" => ovk_proc_strtr($note->getName(), 30),
+ #"preview" => $note->getPreview()
+ ];
+ }
+
+ $resolve($arr);
+ }
}
diff --git a/VKAPI/Handlers/Notes.php b/VKAPI/Handlers/Notes.php
index d3dc3468..ce26baae 100644
--- a/VKAPI/Handlers/Notes.php
+++ b/VKAPI/Handlers/Notes.php
@@ -40,6 +40,9 @@ final class Notes extends VKAPIRequestHandler
if($note->getOwner()->isDeleted())
$this->fail(403, "Owner is deleted");
+ 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.");
@@ -183,6 +186,9 @@ final class Notes extends VKAPIRequestHandler
if(!$user || $user->isDeleted())
$this->fail(15, "Invalid user");
+ if(!$user->getPrivacyPermission('notes.read', $this->getUser()))
+ $this->fail(43, "Access denied: this user chose to hide his notes");
+
if(empty($note_ids)) {
$notes = array_slice(iterator_to_array((new NotesRepo)->getUserNotes($user, 1, $count + $offset, $sort == 0 ? "ASC" : "DESC")), $offset);
$nodez = (object) [
@@ -225,10 +231,13 @@ final class Notes extends VKAPIRequestHandler
if($note->isDeleted())
$this->fail(189, "Note is deleted");
-
+
if(!$note->getOwner() || $note->getOwner()->isDeleted())
$this->fail(177, "Owner does not exists");
+ if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser()))
+ $this->fail(40, "Access denied: this user chose to hide his notes");
+
return $note->toVkApiStruct();
}
@@ -246,6 +255,9 @@ final class Notes extends VKAPIRequestHandler
if(!$note->getOwner())
$this->fail(177, "Owner does not exists");
+
+ if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser()))
+ $this->fail(14, "No access");
$arr = (object) [
"count" => $note->getCommentsCount(),
diff --git a/VKAPI/Handlers/Wall.php b/VKAPI/Handlers/Wall.php
index 927d74ae..cc1204ae 100644
--- a/VKAPI/Handlers/Wall.php
+++ b/VKAPI/Handlers/Wall.php
@@ -13,6 +13,8 @@ use openvk\Web\Models\Entities\Photo;
use openvk\Web\Models\Repositories\Photos as PhotosRepo;
use openvk\Web\Models\Entities\Video;
use openvk\Web\Models\Repositories\Videos as VideosRepo;
+use openvk\Web\Models\Entities\Note;
+use openvk\Web\Models\Repositories\Notes as NotesRepo;
final class Wall extends VKAPIRequestHandler
{
@@ -54,6 +56,8 @@ final class Wall extends VKAPIRequestHandler
$attachments[] = $this->getApiPoll($attachment, $this->getUser());
} else if ($attachment instanceof \openvk\Web\Models\Entities\Video) {
$attachments[] = $attachment->getApiStructure();
+ } else if ($attachment instanceof \openvk\Web\Models\Entities\Note) {
+ $attachments[] = $attachment->toVkApiStruct();
} else if ($attachment instanceof \openvk\Web\Models\Entities\Post) {
$repostAttachments = [];
@@ -226,6 +230,8 @@ final class Wall extends VKAPIRequestHandler
$attachments[] = $this->getApiPoll($attachment, $user);
} else if ($attachment instanceof \openvk\Web\Models\Entities\Video) {
$attachments[] = $attachment->getApiStructure();
+ } else if ($attachment instanceof \openvk\Web\Models\Entities\Note) {
+ $attachments[] = $attachment->toVkApiStruct();
} else if ($attachment instanceof \openvk\Web\Models\Entities\Post) {
$repostAttachments = [];
@@ -440,6 +446,8 @@ final class Wall extends VKAPIRequestHandler
$attachmentType = "photo";
elseif(str_contains($attac, "video"))
$attachmentType = "video";
+ elseif(str_contains($attac, "note"))
+ $attachmentType = "note";
else
$this->fail(205, "Unknown attachment type");
@@ -465,6 +473,17 @@ final class Wall extends VKAPIRequestHandler
if($attacc->getOwner()->getId() != $this->getUser()->getId())
$this->fail(43, "You do not have access to this video");
+ $post->attach($attacc);
+ } elseif($attachmentType == "note") {
+ $attacc = (new NotesRepo)->getNoteById($attachmentOwner, $attachmentId);
+ if(!$attacc || $attacc->isDeleted())
+ $this->fail(100, "Note does not exist");
+ if($attacc->getOwner()->getId() != $this->getUser()->getId())
+ $this->fail(43, "You do not have access to this note");
+
+ if($attacc->getOwner()->getPrivacySetting("notes.read") < 1)
+ $this->fail(11, "You can't attach note to post, because your notes list is closed. Change it in privacy settings in web-version.");
+
$post->attach($attacc);
}
}
@@ -542,6 +561,8 @@ final class Wall extends VKAPIRequestHandler
foreach($comment->getChildren() as $attachment) {
if($attachment instanceof \openvk\Web\Models\Entities\Photo) {
$attachments[] = $this->getApiPhoto($attachment);
+ } elseif($attachment instanceof \openvk\Web\Models\Entities\Note) {
+ $attachments[] = $attachment->toVkApiStruct();
}
}
@@ -599,8 +620,8 @@ final class Wall extends VKAPIRequestHandler
function getComment(int $owner_id, int $comment_id, bool $extended = false, string $fields = "sex,screen_name,photo_50,photo_100,online_info,online") {
$this->requireUser();
- $comment = (new CommentsRepo)->get($comment_id); // один хуй айди всех комментов общий
-
+ $comment = (new CommentsRepo)->get($comment_id); # один хуй айди всех комментов общий
+
$profiles = [];
$attachments = [];
diff --git a/Web/Models/Entities/Note.php b/Web/Models/Entities/Note.php
index d259c2a5..37d9ac29 100644
--- a/Web/Models/Entities/Note.php
+++ b/Web/Models/Entities/Note.php
@@ -123,6 +123,7 @@ class Note extends Postable
{
$res = (object) [];
+ $res->type = "note";
$res->id = $this->getId();
$res->owner_id = $this->getOwner()->getId();
$res->title = $this->getName();
diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php
index 6b9ec183..727101ff 100644
--- a/Web/Presenters/WallPresenter.php
+++ b/Web/Presenters/WallPresenter.php
@@ -3,7 +3,7 @@ namespace openvk\Web\Presenters;
use openvk\Web\Models\Exceptions\TooMuchOptionsException;
use openvk\Web\Models\Entities\{Poll, Post, Photo, Video, Club, User};
use openvk\Web\Models\Entities\Notifications\{MentionNotification, RepostNotification, WallPostNotification};
-use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums};
+use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums, Notes};
use Chandler\Database\DatabaseConnection;
use Nette\InvalidStateException as ISE;
use Bhaktaraz\RSSGenerator\Item;
@@ -278,8 +278,22 @@ final class WallPresenter extends OpenVKPresenter
} catch(\UnexpectedValueException $e) {
$this->flashFail("err", tr("failed_to_publish_post"), "Poll format invalid");
}
+
+ $note = NULL;
+
+ if(!is_null($this->postParam("note")) && $this->postParam("note") != "none") {
+ $note = (new Notes)->get((int)$this->postParam("note"));
+
+ if(!$note || $note->isDeleted() || $note->getOwner()->getId() != $this->user->id) {
+ $this->flashFail("err", tr("error"), tr("error_attaching_note"));
+ }
+
+ if($note->getOwner()->getPrivacySetting("notes.read") < 1) {
+ $this->flashFail("err", " ");
+ }
+ }
- if(empty($this->postParam("text")) && !$photo && !$video && !$poll)
+ if(empty($this->postParam("text")) && !$photo && !$video && !$poll && !$note)
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big"));
try {
@@ -304,6 +318,9 @@ final class WallPresenter extends OpenVKPresenter
if(!is_null($poll))
$post->attach($poll);
+
+ if(!is_null($note))
+ $post->attach($note);
if($wall > 0 && $wall !== $this->user->identity->getId())
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
diff --git a/Web/Presenters/templates/Wall/Feed.xml b/Web/Presenters/templates/Wall/Feed.xml
index b7f405a4..5ed1e2fb 100644
--- a/Web/Presenters/templates/Wall/Feed.xml
+++ b/Web/Presenters/templates/Wall/Feed.xml
@@ -16,7 +16,7 @@
- {include "../components/textArea.xml", route => "/wall" . $thisUser->getId() . "/makePost", graffiti => true, polls => true}
+ {include "../components/textArea.xml", route => "/wall" . $thisUser->getId() . "/makePost", graffiti => true, polls => true, notes => true}
{foreach $posts as $post}
diff --git a/Web/Presenters/templates/components/attachment.xml b/Web/Presenters/templates/components/attachment.xml
index 2b70b768..667c4f52 100644
--- a/Web/Presenters/templates/components/attachment.xml
+++ b/Web/Presenters/templates/components/attachment.xml
@@ -28,6 +28,20 @@
{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll}
{presenter "openvk!Poll->view", $attachment->getId()}
+{elseif $attachment instanceof \openvk\Web\Models\Entities\Note}
+ {if !$attachment->isDeleted()}
+
+ {else}
+
+
+
{_note}
+
{_deleted}
+
+ {/if}
{elseif $attachment instanceof \openvk\Web\Models\Entities\Post}
{php $GLOBALS["_nesAttGloCou"] = (isset($GLOBALS["_nesAttGloCou"]) ? $GLOBALS["_nesAttGloCou"] : 0) + 1}
{if $GLOBALS["_nesAttGloCou"] > 2}
diff --git a/Web/Presenters/templates/components/textArea.xml b/Web/Presenters/templates/components/textArea.xml
index 5e51ff76..f76649d6 100644
--- a/Web/Presenters/templates/components/textArea.xml
+++ b/Web/Presenters/templates/components/textArea.xml
@@ -13,6 +13,9 @@
{_poll}
+
+
+
- {include "../components/textArea.xml", route => "/wall$owner/makePost", graffiti => true, polls => true}
+ {include "../components/textArea.xml", route => "/wall$owner/makePost", graffiti => true, polls => true, notes => true}
diff --git a/Web/static/css/main.css b/Web/static/css/main.css
index 485aaf57..989156e2 100644
--- a/Web/static/css/main.css
+++ b/Web/static/css/main.css
@@ -1453,14 +1453,14 @@ body.scrolled .toTop:hover {
font-weight: bold;
}
-.post-upload, .post-has-poll {
+.post-upload, .post-has-poll, .post-has-note {
margin-top: 11px;
margin-left: 3px;
color: #3c3c3c;
display: none;
}
-.post-upload::before, .post-has-poll::before {
+.post-upload::before, .post-has-poll::before, .post-has-note::before {
content: " ";
width: 8px;
height: 8px;
@@ -2533,3 +2533,35 @@ a.poll-retract-vote {
{
background: rgb(236, 235, 235);
}
+
+.attachment_note_icon {
+ max-width: 9px;
+}
+
+.attachment_note_text {
+ color: #605F63;
+ margin-left: 2px;
+}
+
+.attachment_note {
+ user-select: none;
+}
+
+#notesList
+{
+ overflow-y: scroll;
+ max-height: 130px;
+ margin-top: 5px;
+}
+
+.ntSelect
+{
+ cursor: pointer;
+ padding: 6px;
+
+}
+
+.ntSelect:hover
+{
+ background-color: rgb(233, 232, 232);
+}
diff --git a/Web/static/img/note.svg b/Web/static/img/note.svg
new file mode 100644
index 00000000..9583bb3b
--- /dev/null
+++ b/Web/static/img/note.svg
@@ -0,0 +1 @@
+
note
\ No newline at end of file
diff --git a/Web/static/js/al_wall.js b/Web/static/js/al_wall.js
index 238cc104..867beb73 100644
--- a/Web/static/js/al_wall.js
+++ b/Web/static/js/al_wall.js
@@ -189,3 +189,64 @@ tippy(".client_app", {
}
});
+function addNote(textareaId, nid)
+{
+ if(nid > 0) {
+ note.value = nid
+ let noteObj = document.querySelector("#nd"+nid)
+
+ let nortd = document.querySelector("#post-buttons"+textareaId+" .post-has-note");
+ nortd.style.display = "block"
+
+ nortd.innerHTML = `${tr("note")} ${escapeHtml(noteObj.dataset.name)}`
+ } else {
+ note.value = "none"
+
+ let nortd = document.querySelector("#post-buttons"+textareaId+" .post-has-note");
+ nortd.style.display = "none"
+
+ nortd.innerHTML = ""
+ }
+
+ u("body").removeClass("dimmed");
+ u(".ovk-diag-cont").remove();
+}
+
+async function attachNote(id)
+{
+ let notes = await API.Wall.getMyNotes()
+ let body = ``
+
+ if(notes.closed < 1) {
+ body = `${tr("notes_closed")}`
+ } else {
+ if(notes.items.length < 1) {
+ body = `${tr("no_notes")}`
+ } else {
+ body = `
+ ${tr("select_or_create_new")}
+
`
+
+ if(note.value != "none") {
+ body += `
+
+ ${tr("do_not_attach_note")}
+
`
+ }
+
+ for(const note of notes.items) {
+ body += `
+
+ ${escapeHtml(note.name)}
+
+ `
+ }
+
+ body += `
`
+ }
+ }
+
+ let frame = MessageBox(tr("select_note"), body, [tr("cancel")], [Function.noop]);
+
+ document.querySelector(".ovk-diag-body").style.padding = "10px"
+}
\ No newline at end of file
diff --git a/locales/en.strings b/locales/en.strings
index 72bf67f8..0a5c02c6 100644
--- a/locales/en.strings
+++ b/locales/en.strings
@@ -404,6 +404,16 @@
"notes_list_one" = "$1 note found";
"notes_list_other" = "$1 notes found";
+"select_note" = "Selecting note";
+"no_notes" = "You don't have any notes";
+
+"error_attaching_note" = "Error when attaching note";
+
+"select_or_create_new" = "Select existing note or
create new one ";
+
+"notes_closed" = "You can't attach note to post, because only you can see them.
You can change it in
settings .";
+"do_not_attach_note" = "Do not attach note";
+
/* Menus */
/* Note that is string need to fit into the "My Page" link */
diff --git a/locales/ru.strings b/locales/ru.strings
index ce943e33..060819db 100644
--- a/locales/ru.strings
+++ b/locales/ru.strings
@@ -389,6 +389,16 @@
"notes_list_many" = "Найдено $1 заметок";
"notes_list_other" = "Найдено $1 заметок";
+"select_note" = "Выбор заметки";
+"no_notes" = "У вас нет ни одной заметки";
+
+"error_attaching_note" = "Не удалось прикрепить заметку";
+
+"select_or_create_new" = "Выберите существующую заметку или
создайте новую ";
+
+"notes_closed" = "Вы не можете прикрепить заметку к записи, так как ваши заметки видны только вам.
Вы можете поменять это в
настройках .";
+"do_not_attach_note" = "Не прикреплять заметку";
+
/* Menus */
"edit_button" = "ред.";