Skip to content

Commit

Permalink
New features: Unread & Pinned (#377)
Browse files Browse the repository at this point in the history
* New features: Unread & Pinned

* New feature: Pinned

* Fix tests

* Update pin icon

* Fix select of next read message for redirect after mark as unread
  • Loading branch information
yurabakhtin authored Jan 29, 2024
1 parent 011407a commit d39daa5
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 52 deletions.
81 changes: 72 additions & 9 deletions controllers/MailController.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public function actionAddUser($id)
*/
public function actionNotificationList()
{
$query = UserMessage::findByUser(null, 'message.updated_at DESC')->limit(5);
$query = UserMessage::findByUser()->limit(5);
return $this->renderAjax('notificationList', ['userMessages' => $query->all()]);
}

Expand Down Expand Up @@ -341,6 +341,58 @@ public function actionCreate($userGuid = null, ?string $title = null, ?string $m
]);
}

/**
* Mark a Conversation as unread
*
* @param int $id
*/
public function actionMarkUnread($id)
{
$this->forcePostRequest();
$this->getMessage($id, true)->markUnread();

$nextReadMessage = $this->getNextReadMessage($id);

return $this->asJson([
'success' => true,
'redirect' => $nextReadMessage ? Url::toMessenger($nextReadMessage) : Url::to(['/dashboard'])
]);
}

/**
* Pin a Conversation
*
* @param int $id
*/
public function actionPin($id)
{
$this->forcePostRequest();
$message = $this->getMessage($id, true);
$message->pin();

return $this->asJson([
'success' => true,
'redirect' => Url::toMessenger($message)
]);
}

/**
* Unpin a Conversation
*
* @param int $id
*/
public function actionUnpin($id)
{
$this->forcePostRequest();
$message = $this->getMessage($id, true);
$message->unpin();

return $this->asJson([
'success' => true,
'redirect' => Url::toMessenger($message)
]);
}

/**
* Leave Message / Conversation
*
Expand All @@ -355,7 +407,7 @@ public function actionCreate($userGuid = null, ?string $title = null, ?string $m
public function actionLeave($id)
{
$this->forcePostRequest();
$this->getMessage($id, true)->leave(Yii::$app->user->id);
$this->getMessage($id, true)->leave();

return $this->asJson([
'success' => true,
Expand Down Expand Up @@ -441,18 +493,15 @@ public function actionGetNewMessageCountJson()
*
* @param int $id
* @param bool $throw
* @return Message
* @return Message|null
* @throws HttpException
*/
private function getMessage($id, $throw = false)
private function getMessage($id, $throw = false): ?Message
{
$message = Message::findOne(['id' => $id]);

if ($message) {
$userMessage = $message->getUserMessage();
if ($userMessage != null) {
return $message;
}
if ($message && $message->getUserMessage() !== null) {
return $message;
}

if ($throw) {
Expand All @@ -461,4 +510,18 @@ private function getMessage($id, $throw = false)

return null;
}

private function getNextReadMessage($id): ?Message
{
return Message::find()
->leftJoin('user_message', 'user_message.message_id = message.id')
->where(['user_id' => Yii::$app->user->id])
->andWhere(['!=', 'message_id', $id])
->andWhere('user_message.last_viewed >= message.updated_at')
->orderBy([
'user_message.pinned' => SORT_DESC,
'message.updated_at' => SORT_DESC
])
->one();
}
}
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
Unreleased
------------------------
- Fix #369: Misplaced Online dot
- Enh #377: New features: Unread & Pinned

3.1.2 (January 22, 2024)
------------------------
Expand Down
19 changes: 17 additions & 2 deletions helpers/Url.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,24 @@ public static function toConversationUserList(Message $message)
return static::to(['/mail/mail/user-list', 'id' => $message->id]);
}

public static function toMarkUnreadConversation(Message $message)
{
return static::to(['/mail/mail/mark-unread', 'id' => $message->id]);
}

public static function toPinConversation(Message $message)
{
return static::to(['/mail/mail/pin', 'id' => $message->id]);
}

public static function toUnpinConversation(Message $message)
{
return static::to(['/mail/mail/unpin', 'id' => $message->id]);
}

public static function toLeaveConversation(Message $message)
{
return static::to(["/mail/mail/leave", 'id' => $message->id]);
return static::to(['/mail/mail/leave', 'id' => $message->id]);
}

public static function toMessenger(Message $message = null, $scheme = false)
Expand Down Expand Up @@ -131,4 +146,4 @@ public static function toLoadMoreMessages()
{
return static::to(['/mail/mail/load-more']);
}
}
}
26 changes: 26 additions & 0 deletions migrations/m240125_080730_pinned.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

use humhub\components\Migration;
use humhub\modules\mail\models\UserMessage;

/**
* Class m240125_080730_pinned
*/
class m240125_080730_pinned extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->safeAddColumn(UserMessage::tableName(), 'pinned', $this->boolean()->defaultValue(false)->notNull());
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->safeDropColumn(UserMessage::tableName(), 'pinned');
}
}
74 changes: 65 additions & 9 deletions models/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use humhub\components\ActiveRecord;
use humhub\modules\mail\Module;
use humhub\modules\ui\icon\widgets\Icon;
use humhub\modules\user\models\User;
use Yii;
use yii\helpers\Html;
Expand Down Expand Up @@ -105,12 +106,15 @@ public function getAuthor()
}

/**
* @param null $userId
* @param int|null $userId
* @return UserMessage|null
*/
public function getUserMessage($userId = null)
{
if (!$userId) {
if (Yii::$app->user->isGuest) {
return null;
}
$userId = Yii::$app->user->id;
}

Expand Down Expand Up @@ -233,23 +237,58 @@ public function deleteEntry($entry)
}
}

/**
* Mark this message as unread
*
* @param int|null $userId
*/
public function markUnread($userId = null)
{
$userMessage = $this->getUserMessage($userId);
if ($userMessage) {
$userMessage->last_viewed = null;
$userMessage->save();
}
}

/**
* Pin this message
*
* @param int|null $userId
* @param bool $pin
*/
public function pin($userId = null, bool $pin = true)
{
$userMessage = $this->getUserMessage($userId);
if ($userMessage) {
$userMessage->pinned = $pin;
$userMessage->save();
}
}

/**
* Unpin this message
*
* @param int|null $userId
*/
public function unpin($userId = null)
{
$this->pin($userId, false);
}

/**
* User leaves a message
*
* If it's the last user, the whole message will be deleted.
*
* @param int $userId
* @param int|null $userId
* @throws \Throwable
* @throws \yii\db\StaleObjectException
*/
public function leave($userId)
public function leave($userId = null)
{
$userMessage = UserMessage::findOne([
'message_id' => $this->id,
'user_id' => $userId
]);

if(!$userMessage) {
$userMessage = $this->getUserMessage($userId);
if (!$userMessage) {
return;
}

Expand Down Expand Up @@ -371,4 +410,21 @@ public function isBlocked(): bool

return false;
}

public function isPinned($userId = null): bool
{
$userMessage = $this->getUserMessage($userId);
return $userMessage && $userMessage->pinned;
}

public function getPinIcon($userId = null): ?Icon
{
if ($this->isPinned($userId)) {
return Icon::get('map-pin')
->tooltip(Yii::t('MailModule.base', 'Pinned'))
->color(Yii::$app->view->theme->variable('danger', 'red'));
}

return null;
}
}
16 changes: 6 additions & 10 deletions models/UserMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @property integer $created_by
* @property string $updated_at
* @property integer $updated_by
* @property integer $pinned
*
* @property-read Message $message
* @property-read User $user
Expand Down Expand Up @@ -113,19 +114,14 @@ public static function findByUser($userId = null)

return static::find()->joinWith('message')
->where(['user_message.user_id' => $userId])
->orderBy('message.updated_at DESC');
->orderBy([
'user_message.pinned' => SORT_DESC,
'message.updated_at' => SORT_DESC
]);
}

public function isUnread($userId = null)
public function isUnread(): bool
{
if ($userId === null) {
$userId = Yii::$app->user->id;
}

if($this->message->lastEntry && ($this->message->lastEntry->user_id === $userId)) {
return false;
}

return $this->message->updated_at > $this->last_viewed;
}

Expand Down
2 changes: 1 addition & 1 deletion resources/css/humhub.mail.css
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
.mail-conversation-entry.hideUserInfo .author-label {
display: none;
}
.mail-conversation-entry.hideUserInfo .author-image img {
.mail-conversation-entry.hideUserInfo .author-image a {
visibility: hidden;
margin-top: 0;
}
Expand Down
Loading

0 comments on commit d39daa5

Please sign in to comment.