Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/user_status/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
['name' => 'UserStatus#setPredefinedMessage', 'url' => '/api/v1/user_status/message/predefined', 'verb' => 'PUT'],
['name' => 'UserStatus#setCustomMessage', 'url' => '/api/v1/user_status/message/custom', 'verb' => 'PUT'],
['name' => 'UserStatus#clearMessage', 'url' => '/api/v1/user_status/message', 'verb' => 'DELETE'],
// Routes for getting your backup status (if it exists)
['name' => 'UserStatus#getBackupStatus', 'url' => '/api/v1/user_status_backup', 'verb' => 'GET'],
Comment thread
CarlSchwan marked this conversation as resolved.
Outdated
['name' => 'UserStatus#revert', 'url' => '/api/v1/user_status/revert', 'verb' => 'POST'],
// Routes for listing default routes
['name' => 'PredefinedStatus#findAll', 'url' => '/api/v1/predefined_statuses/', 'verb' => 'GET']
],
Expand Down
24 changes: 12 additions & 12 deletions apps/user_status/js/dashboard.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/user_status/js/dashboard.js.map

Large diffs are not rendered by default.

65 changes: 44 additions & 21 deletions apps/user_status/js/user-status-menu.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/user_status/js/user-status-menu.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions apps/user_status/js/user-status-modal.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/user_status/js/user-status-modal.js.map

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions apps/user_status/js/vendors-user-status-modal.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/user_status/js/vendors-user-status-modal.js.map

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion apps/user_status/lib/Connector/UserStatusProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,24 @@
use OCA\UserStatus\Service\StatusService;
use OCP\UserStatus\IProvider;
use OC\UserStatus\ISettableProvider;
use OCP\IConfig;

class UserStatusProvider implements IProvider, ISettableProvider {

/** @var StatusService */
private $service;

/** @var IConfig */
private $config;

/**
* UserStatusProvider constructor.
*
* @param StatusService $service
*/
public function __construct(StatusService $service) {
public function __construct(StatusService $service, IConfig $config) {
$this->service = $service;
$this->config = $config;
}

/**
Expand All @@ -58,6 +63,9 @@ public function getUserStatuses(array $userIds): array {
}

public function setUserStatus(string $userId, string $messageId, string $status, bool $createBackup = false): void {
if (!(bool)$this->config->getUserValue($userId, 'user_status', 'automatic_status_enabled', (string)true)) {
return;
}
if ($createBackup) {
if ($this->service->backupCurrentStatus($userId) === false) {
return; // Already a status set automatically => abort.
Expand Down
4 changes: 1 addition & 3 deletions apps/user_status/lib/Controller/StatusesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,8 @@ public function find(string $userId): DataResponse {
}

/**
* @NoAdminRequired
*
* @param UserStatus $status
* @return array
* @return array{userId: string, message: string, icon: string, clearAt: int, status: string}
*/
private function formatStatus(UserStatus $status): array {
$visibleStatus = $status->getStatus();
Expand Down
28 changes: 28 additions & 0 deletions apps/user_status/lib/Controller/UserStatusController.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ public function getStatus(): DataResponse {
return new DataResponse($this->formatStatus($userStatus));
}

/**
* @NoAdminRequired
*
* @return DataResponse
*/
public function getBackupStatus(): DataResponse {
try {
$userStatus = $this->service->findByUserId($this->userId, true);
} catch (DoesNotExistException $ex) {
return new DataResponse(['hasBackup' => false]);
}

return new DataResponse($this->formatStatus($userStatus));
}

/**
* @NoAdminRequired
*
Expand All @@ -99,6 +114,7 @@ public function getStatus(): DataResponse {
public function setStatus(string $statusType): DataResponse {
try {
$status = $this->service->setStatus($this->userId, $statusType, null, true);
$this->service->removeUserStatus($this->userId, true);
return new DataResponse($this->formatStatus($status));
} catch (InvalidStatusTypeException $ex) {
$this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid status type "' . $statusType . '"');
Expand All @@ -118,6 +134,7 @@ public function setPredefinedMessage(string $messageId,
?int $clearAt): DataResponse {
try {
$status = $this->service->setPredefinedMessage($this->userId, $messageId, $clearAt);
$this->service->removeUserStatus($this->userId, true);
return new DataResponse($this->formatStatus($status));
} catch (InvalidClearAtException $ex) {
$this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid clearAt value "' . $clearAt . '"');
Expand Down Expand Up @@ -147,6 +164,7 @@ public function setCustomMessage(?string $statusIcon,
$this->service->clearMessage($this->userId);
$status = $this->service->findByUserId($this->userId);
}
$this->service->removeUserStatus($this->userId, true);
return new DataResponse($this->formatStatus($status));
} catch (InvalidClearAtException $ex) {
$this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid clearAt value "' . $clearAt . '"');
Expand Down Expand Up @@ -180,6 +198,16 @@ public function clearMessage(): DataResponse {
return new DataResponse([]);
}

/**
* @NoAdminRequired
* @param array $status The current status.
* @return DataResponse
*/
public function revert(array $status): DataResponse {
$this->service->revertUserStatus($this->userId, null, $status['status']);
return new DataResponse([]);
}

/**
* @param UserStatus $status
* @return array
Expand Down
20 changes: 7 additions & 13 deletions apps/user_status/lib/Service/StatusService.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,12 @@ public function findAllRecentStatusChanges(?int $limit = null, ?int $offset = nu

/**
* @param string $userId
* @param bool $isBackup
* @return UserStatus
* @throws DoesNotExistException
*/
public function findByUserId(string $userId):UserStatus {
return $this->processStatus($this->mapper->findByUserId($userId));
public function findByUserId(string $userId, bool $isBackup = false):UserStatus {
return $this->processStatus($this->mapper->findByUserId($userId, $isBackup));
}

/**
Expand Down Expand Up @@ -448,25 +449,18 @@ public function backupCurrentStatus(string $userId): bool {
return true;
}

public function revertUserStatus(string $userId, string $messageId, string $status): void {
public function revertUserStatus(string $userId, ?string $messageId, string $status): void {
try {
/** @var UserStatus $userStatus */
$backupUserStatus = $this->mapper->findByUserId($userId, true);
} catch (DoesNotExistException $ex) {
// No backup, just move back to available
try {
$userStatus = $this->mapper->findByUserId($userId);
} catch (DoesNotExistException $ex) {
// No backup nor current status => ignore
return;
}
$this->cleanStatus($userStatus);
$this->cleanStatusMessage($userStatus);
// No user status to revert, do nothing
return;
}
try {
$userStatus = $this->mapper->findByUserId($userId);
if ($userStatus->getMessageId() !== $messageId || $userStatus->getStatus() !== $status) {
if (($messageId !== null && $userStatus->getMessageId() !== $messageId)
|| $userStatus->getStatus() !== $status) {
// Another status is set automatically, do nothing
return;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/user_status/src/UserStatus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ import { getCurrentUser } from '@nextcloud/auth'
import { loadState } from '@nextcloud/initial-state'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import debounce from 'debounce'
import OnlineStatusMixin from './mixins/OnlineStatusMixin'

import { sendHeartbeat } from './services/heartbeatService'
import OnlineStatusMixin from './mixins/OnlineStatusMixin'

const { profileEnabled } = loadState('user_status', 'profileEnabled', false)

Expand Down
126 changes: 126 additions & 0 deletions apps/user_status/src/components/ResetStatus.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!--
- @copyright Copyright (c) 2021 Carl Schwan <carl@carlschwan.eu>
- @author Carl Schwan <carl@carlschwan.eu>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->

<template>
<div v-if="hasLoaded && backupStatus.status">
{{ $t('user_status', 'Automatically set during calls and events.') }}<br />
{{ $t('user_status', 'Reset to') }}
<a
href="#"
role="button"
@click.prevent.stop="revertCurrentStatus">
{{ message }}
</a>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/l10n.html#improving-your-translations please make the message a parameter in the translation, or use another line break and make the translated string "complete" e.g. Reset status: and use a real button?

</div>
</template>

<script>
import { mapState } from 'vuex'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { getCurrentUser } from '@nextcloud/auth'

export default {
name: 'ResetStatus',
computed: {
...mapState({
backupStatus: state => state.backupStatus,
userStatus: state => state.userStatus,
}),
/**
* Indicator whether the backup status has already been loaded
*
* @returns {boolean}
*/
hasLoaded() {
return this.backupStatus.status !== null
},
message() {
if (this.backupStatus.icon && this.backupStatus.message) {
return `${this.backupStatus.icon} ${this.backupStatus.message}`
}

if (this.backupStatus.message) {
return this.backupStatus.message
}

switch (this.backupStatus.status) {
case 'online':
return this.$t('user_status', 'Online')

case 'away':
return this.$t('user_status', 'Away')

case 'dnd':
return this.$t('user_status', 'Do not disturb')

case 'invisible':
return this.$t('user_status', 'Invisible')

case 'offline':
return this.$t('user_status', 'Offline')
}
return ''
},
},
/**
* Loads all predefined statuses from the server
* when this component is mounted
*/
mounted() {
this.$store.dispatch('loadBackupStatus')
subscribe('user_status:status.updated', this.handleUserStatusUpdated)
},
beforeDestroy() {
unsubscribe('user_status:status.updated', this.handleUserStatusUpdated)
},
methods: {
/**
* Revert the current status.
*/
revertCurrentStatus() {
this.$store.dispatch('revertStatus', {
status: this.userStatus,
backupStatus: this.backupStatus,
})
},
/**
* Handle change of status, and check if we still need to display the
* option to revert the current status.
* @param {Object} status The current status
*/
handleUserStatusUpdated(status) {
if (getCurrentUser().uid === status.userId) {
// Update backup information
this.$store.dispatch('loadBackupStatus')
}
},
},
}
</script>

<style lang="scss" scoped>
a {
font-weight: bold;
&:focus, &:hover {
text-decoration: underline;
}
}
</style>
18 changes: 17 additions & 1 deletion apps/user_status/src/components/SetStatusModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
@select="changeStatus" />
</div>

<ResetStatus />

<!-- Status message -->
<div class="set-status-modal__header">
<h3>{{ $t('user_status', 'Status message') }}</h3>
Expand Down Expand Up @@ -72,6 +74,7 @@
</template>

<script>
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { showError } from '@nextcloud/dialogs'
import EmojiPicker from '@nextcloud/vue/dist/Components/EmojiPicker'
import Modal from '@nextcloud/vue/dist/Components/Modal'
Expand All @@ -82,6 +85,7 @@ import PredefinedStatusesList from './PredefinedStatusesList'
import CustomMessageInput from './CustomMessageInput'
import ClearAtSelect from './ClearAtSelect'
import OnlineStatusSelect from './OnlineStatusSelect'
import ResetStatus from './ResetStatus'

export default {
name: 'SetStatusModal',
Expand All @@ -93,6 +97,7 @@ export default {
Modal,
OnlineStatusSelect,
PredefinedStatusesList,
ResetStatus,
},
mixins: [OnlineStatusMixin],

Expand Down Expand Up @@ -130,6 +135,10 @@ export default {
time: this.$store.state.userStatus.clearAt,
}
}
subscribe('user_status:status.updated', this.handleUserStatusUpdated)
},
beforeDestroy() {
unsubscribe('user_status:status.updated', this.handleUserStatusUpdated)
},
methods: {
/**
Expand Down Expand Up @@ -178,6 +187,13 @@ export default {
this.icon = status.icon
this.message = status.message
},
handleUserStatusUpdated(state) {
if (OC.getCurrentUser().uid === state.userId) {
this.messageId = this.$store.state.userStatus.messageId
this.icon = this.$store.state.userStatus.icon
this.message = this.$store.state.userStatus.message || ''
}
},
/**
* Saves the status and closes the
*
Expand Down Expand Up @@ -241,7 +257,7 @@ export default {
min-height: 200px;
padding: 8px 20px 20px 20px;
// Enable scrollbar for too long content, same way as in Dashboard customize
max-height: 70vh;
max-height: 80vh;
overflow: auto;

&__header {
Expand Down
1 change: 1 addition & 0 deletions apps/user_status/src/main-user-status-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const avatarDiv = document.getElementById('avatardiv-menu')
const propsData = {
preloadedUserStatus: {
message: avatarDiv.dataset.userstatus_message,
messageId: avatarDiv.dataset.userstatus_message_id,
icon: avatarDiv.dataset.userstatus_icon,
status: avatarDiv.dataset.userstatus,
},
Expand Down
Loading