mirror of https://github.com/nextcloud/server
feat(contactsmenu): Show user status
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
parent
b4e707059d
commit
ac168cf9ff
|
@ -25,4 +25,7 @@
|
|||
<background-jobs>
|
||||
<job>OCA\UserStatus\BackgroundJob\ClearOldStatusesBackgroundJob</job>
|
||||
</background-jobs>
|
||||
<contactsmenu>
|
||||
<provider>OCA\UserStatus\ContactsMenu\StatusProvider</provider>
|
||||
</contactsmenu>
|
||||
</info>
|
||||
|
|
|
@ -12,6 +12,7 @@ return array(
|
|||
'OCA\\UserStatus\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
|
||||
'OCA\\UserStatus\\Connector\\UserStatus' => $baseDir . '/../lib/Connector/UserStatus.php',
|
||||
'OCA\\UserStatus\\Connector\\UserStatusProvider' => $baseDir . '/../lib/Connector/UserStatusProvider.php',
|
||||
'OCA\\UserStatus\\ContactsMenu\\StatusProvider' => $baseDir . '/../lib/ContactsMenu/StatusProvider.php',
|
||||
'OCA\\UserStatus\\Controller\\HeartbeatController' => $baseDir . '/../lib/Controller/HeartbeatController.php',
|
||||
'OCA\\UserStatus\\Controller\\PredefinedStatusController' => $baseDir . '/../lib/Controller/PredefinedStatusController.php',
|
||||
'OCA\\UserStatus\\Controller\\StatusesController' => $baseDir . '/../lib/Controller/StatusesController.php',
|
||||
|
|
|
@ -27,6 +27,7 @@ class ComposerStaticInitUserStatus
|
|||
'OCA\\UserStatus\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php',
|
||||
'OCA\\UserStatus\\Connector\\UserStatus' => __DIR__ . '/..' . '/../lib/Connector/UserStatus.php',
|
||||
'OCA\\UserStatus\\Connector\\UserStatusProvider' => __DIR__ . '/..' . '/../lib/Connector/UserStatusProvider.php',
|
||||
'OCA\\UserStatus\\ContactsMenu\\StatusProvider' => __DIR__ . '/..' . '/../lib/ContactsMenu/StatusProvider.php',
|
||||
'OCA\\UserStatus\\Controller\\HeartbeatController' => __DIR__ . '/..' . '/../lib/Controller/HeartbeatController.php',
|
||||
'OCA\\UserStatus\\Controller\\PredefinedStatusController' => __DIR__ . '/..' . '/../lib/Controller/PredefinedStatusController.php',
|
||||
'OCA\\UserStatus\\Controller\\StatusesController' => __DIR__ . '/..' . '/../lib/Controller/StatusesController.php',
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
*
|
||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
*
|
||||
* @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/>.
|
||||
*/
|
||||
|
||||
namespace OCA\UserStatus\ContactsMenu;
|
||||
|
||||
use OCA\UserStatus\Db\UserStatus;
|
||||
use OCA\UserStatus\Service\StatusService;
|
||||
use OCP\Contacts\ContactsMenu\IBulkProvider;
|
||||
use OCP\Contacts\ContactsMenu\IEntry;
|
||||
use function array_combine;
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
|
||||
class StatusProvider implements IBulkProvider {
|
||||
|
||||
public function __construct(private StatusService $statusService) {
|
||||
}
|
||||
|
||||
public function process(array $entries): void {
|
||||
$uids = array_filter(
|
||||
array_map(fn (IEntry $entry): ?string => $entry->getProperty('UID'), $entries)
|
||||
);
|
||||
|
||||
$statuses = $this->statusService->findByUserIds($uids);
|
||||
$indexed = array_combine(
|
||||
array_map(fn(UserStatus $status) => $status->getUserId(), $statuses),
|
||||
$statuses
|
||||
);
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$uid = $entry->getProperty('UID');
|
||||
if ($uid !== null && isset($indexed[$uid])) {
|
||||
$status = $indexed[$uid];
|
||||
$entry->setStatus(
|
||||
$status->getStatus(),
|
||||
$status->getCustomMessage(),
|
||||
$status->getCustomIcon(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -25,27 +25,37 @@
|
|||
:href="contact.profileUrl"
|
||||
class="contact__avatar-wrapper">
|
||||
<NcAvatar class="contact__avatar"
|
||||
:is-no-user="true"
|
||||
:size="44"
|
||||
:user="contact.isUser ? contact.uid : undefined"
|
||||
:is-no-user="!contact.isUser"
|
||||
:display-name="contact.avatarLabel"
|
||||
:url="contact.avatar" />
|
||||
:url="contact.avatar"
|
||||
:preloaded-user-status="preloadedUserStatus" />
|
||||
</a>
|
||||
<a v-else-if="contact.profileUrl"
|
||||
:href="contact.profileUrl">
|
||||
<NcAvatar class="contact__avatar"
|
||||
:is-no-user="true"
|
||||
:display-name="contact.avatarLabel" />
|
||||
:size="44"
|
||||
:user="contact.isUser ? contact.uid : undefined"
|
||||
:is-no-user="!contact.isUser"
|
||||
:display-name="contact.avatarLabel"
|
||||
:preloaded-user-status="preloadedUserStatus" />
|
||||
</a>
|
||||
<NcAvatar v-else
|
||||
:size="44"
|
||||
class="contact__avatar"
|
||||
:is-no-user="true"
|
||||
:user="contact.isUser ? contact.uid : undefined"
|
||||
:is-no-user="!contact.isUser"
|
||||
:display-name="contact.avatarLabel"
|
||||
:url="contact.avatar" />
|
||||
:url="contact.avatar"
|
||||
:preloaded-user-status="preloadedUserStatus" />
|
||||
|
||||
<a class="contact__body"
|
||||
:href="contact.profileUrl || contact.topAction?.hyperlink">
|
||||
<div class="contact__body__full-name">{{ contact.fullName }}</div>
|
||||
<div v-if="contact.lastMessage" class="contact__body__last-message">{{ contact.lastMessage }}</div>
|
||||
<div class="contact__body__email-address">{{ contact.emailAddresses[0] }}</div>
|
||||
<div v-if="contact.statusMessage" class="contact__body__status-message">{{ contact.statusMessage }}</div>
|
||||
<div v-else class="contact__body__email-address">{{ contact.emailAddresses[0] }}</div>
|
||||
</a>
|
||||
<NcActions v-if="actions.length"
|
||||
:inline="contact.topAction ? 1 : 0">
|
||||
|
@ -97,6 +107,16 @@ export default {
|
|||
}
|
||||
return this.contact.actions
|
||||
},
|
||||
preloadedUserStatus() {
|
||||
if (this.contact.status) {
|
||||
return {
|
||||
status: this.contact.status,
|
||||
message: this.contact.statusMessage,
|
||||
icon: this.contact.statusIcon,
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -118,18 +138,15 @@ export default {
|
|||
}
|
||||
|
||||
&__avatar-wrapper {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
&__body {
|
||||
flex-grow: 1;
|
||||
padding-left: 8px;
|
||||
padding-left: 10px;
|
||||
min-width: 0;
|
||||
|
||||
div {
|
||||
|
@ -137,9 +154,16 @@ export default {
|
|||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: -1px 0;
|
||||
}
|
||||
div:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
div:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.last-message, .email-address {
|
||||
&__last-message, &__status-message, &__email-address {
|
||||
color: var(--color-text-maxcontrast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ describe('ContactsMenu', function() {
|
|||
emailAddresses: [],
|
||||
}
|
||||
],
|
||||
contactsAppEnabled: false,
|
||||
contactsAppEnabled: true,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -149,26 +149,6 @@ describe('ContactsMenu', function() {
|
|||
expect(view.vm.contacts.length).toBe(2)
|
||||
expect(view.text()).toContain('Acosta Lancaster')
|
||||
expect(view.text()).toContain('Adeline Snider')
|
||||
})
|
||||
|
||||
it('shows link ot Contacts', async () => {
|
||||
const view = shallowMount(ContactsMenu)
|
||||
axios.post.mockResolvedValue({
|
||||
data: {
|
||||
contacts: [
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
},
|
||||
],
|
||||
contactsAppEnabled: true,
|
||||
},
|
||||
})
|
||||
|
||||
await view.vm.handleOpen()
|
||||
|
||||
expect(view.text()).toContain('Show all contacts …')
|
||||
expect(view.text()).toContain('Show all contacts')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -58,10 +58,10 @@
|
|||
</ul>
|
||||
</div>
|
||||
<div v-if="contactsAppEnabled" class="contactsmenu__menu__content__footer">
|
||||
<a :href="contactsAppURL">{{ t('core', 'Show all contacts …') }}</a>
|
||||
<NcButton type="tertiary" :href="contactsAppURL">{{ t('core', 'Show all contacts') }}</NcButton>
|
||||
</div>
|
||||
<div v-else-if="canInstallApp" class="contactsmenu__menu__content__footer">
|
||||
<a :href="contactsAppMgmtURL">{{ t('core', 'Install the Contacts app') }}</a>
|
||||
<NcButton type="tertiary" :href="contactsAppMgmtURL">{{ t('core', 'Install the Contacts app') }}</NcButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -75,6 +75,7 @@ import debounce from 'debounce'
|
|||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import Magnify from 'vue-material-design-icons/Magnify.vue'
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
|
||||
import NcHeaderMenu from '@nextcloud/vue/dist/Components/NcHeaderMenu.js'
|
||||
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
|
||||
|
@ -91,6 +92,7 @@ export default {
|
|||
Contact,
|
||||
Contacts,
|
||||
Magnify,
|
||||
NcButton,
|
||||
NcEmptyContent,
|
||||
NcHeaderMenu,
|
||||
NcLoadingIcon,
|
||||
|
@ -178,14 +180,9 @@ export default {
|
|||
overflow-y: auto;
|
||||
|
||||
&__footer {
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 12px 0;
|
||||
opacity: .5;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -210,6 +210,7 @@ return array(
|
|||
'OCP\\Constants' => $baseDir . '/lib/public/Constants.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IAction' => $baseDir . '/lib/public/Contacts/ContactsMenu/IAction.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IActionFactory' => $baseDir . '/lib/public/Contacts/ContactsMenu/IActionFactory.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IBulkProvider' => $baseDir . '/lib/public/Contacts/ContactsMenu/IBulkProvider.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IContactsStore' => $baseDir . '/lib/public/Contacts/ContactsMenu/IContactsStore.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IEntry' => $baseDir . '/lib/public/Contacts/ContactsMenu/IEntry.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\ILinkAction' => $baseDir . '/lib/public/Contacts/ContactsMenu/ILinkAction.php',
|
||||
|
|
|
@ -243,6 +243,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\Constants' => __DIR__ . '/../../..' . '/lib/public/Constants.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IAction' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IAction.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IActionFactory' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IActionFactory.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IBulkProvider' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IBulkProvider.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IContactsStore' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IContactsStore.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\IEntry' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IEntry.php',
|
||||
'OCP\\Contacts\\ContactsMenu\\ILinkAction' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/ILinkAction.php',
|
||||
|
|
|
@ -33,6 +33,7 @@ use OC\Contacts\ContactsMenu\Providers\EMailProvider;
|
|||
use OC\Contacts\ContactsMenu\Providers\LocalTimeProvider;
|
||||
use OC\Contacts\ContactsMenu\Providers\ProfileProvider;
|
||||
use OCP\AppFramework\QueryException;
|
||||
use OCP\Contacts\ContactsMenu\IBulkProvider;
|
||||
use OCP\Contacts\ContactsMenu\IProvider;
|
||||
use OCP\IServerContainer;
|
||||
use OCP\IUser;
|
||||
|
@ -47,18 +48,26 @@ class ActionProviderStore {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return IProvider[]
|
||||
* @return list<IProvider|IBulkProvider>
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getProviders(IUser $user): array {
|
||||
$appClasses = $this->getAppProviderClasses($user);
|
||||
$providerClasses = $this->getServerProviderClasses();
|
||||
$allClasses = array_merge($providerClasses, $appClasses);
|
||||
/** @var list<IProvider|IBulkProvider> $providers */
|
||||
$providers = [];
|
||||
|
||||
foreach ($allClasses as $class) {
|
||||
try {
|
||||
$providers[] = $this->serverContainer->get($class);
|
||||
$provider = $this->serverContainer->get($class);
|
||||
if ($provider instanceof IProvider || $provider instanceof IBulkProvider) {
|
||||
$providers[] = $provider;
|
||||
} else {
|
||||
$this->logger->warning('Ignoring invalid contacts menu provider', [
|
||||
'class' => $class,
|
||||
]);
|
||||
}
|
||||
} catch (QueryException $ex) {
|
||||
$this->logger->error(
|
||||
'Could not load contacts menu action provider ' . $class,
|
||||
|
|
|
@ -268,8 +268,10 @@ class ContactsStore implements IContactsStore {
|
|||
if (isset($contact['UID'])) {
|
||||
$uid = $contact['UID'];
|
||||
$entry->setId($uid);
|
||||
$entry->setProperty('isUser', false);
|
||||
if (isset($contact['isLocalSystemBook'])) {
|
||||
$avatar = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $uid, 'size' => 64]);
|
||||
$entry->setProperty('isUser', true);
|
||||
} elseif (isset($contact['FN'])) {
|
||||
$avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => $contact['FN'], 'size' => 64]);
|
||||
} else {
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace OC\Contacts\ContactsMenu;
|
|||
|
||||
use OCP\Contacts\ContactsMenu\IAction;
|
||||
use OCP\Contacts\ContactsMenu\IEntry;
|
||||
use function array_merge;
|
||||
|
||||
class Entry implements IEntry {
|
||||
/** @var string|int|null */
|
||||
|
@ -50,6 +51,10 @@ class Entry implements IEntry {
|
|||
|
||||
private array $properties = [];
|
||||
|
||||
private ?string $status = null;
|
||||
private ?string $statusMessage = null;
|
||||
private ?string $statusIcon = null;
|
||||
|
||||
public function setId(string $id): void {
|
||||
$this->id = $id;
|
||||
}
|
||||
|
@ -102,6 +107,14 @@ class Entry implements IEntry {
|
|||
$this->sortActions();
|
||||
}
|
||||
|
||||
public function setStatus(string $status,
|
||||
string $statusMessage = null,
|
||||
string $icon = null): void {
|
||||
$this->status = $status;
|
||||
$this->statusMessage = $statusMessage;
|
||||
$this->statusIcon = $icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IAction[]
|
||||
*/
|
||||
|
@ -127,11 +140,15 @@ class Entry implements IEntry {
|
|||
});
|
||||
}
|
||||
|
||||
public function setProperty(string $propertyName, mixed $value) {
|
||||
$this->properties[$propertyName] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $contact key-value array containing additional properties
|
||||
* @param array $properties key-value array containing additional properties
|
||||
*/
|
||||
public function setProperties(array $contact): void {
|
||||
$this->properties = $contact;
|
||||
public function setProperties(array $properties): void {
|
||||
$this->properties = array_merge($this->properties, $properties);
|
||||
}
|
||||
|
||||
public function getProperty(string $key): mixed {
|
||||
|
@ -142,7 +159,7 @@ class Entry implements IEntry {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array{id: int|string|null, fullName: string, avatar: string|null, topAction: mixed, actions: array, lastMessage: '', emailAddresses: string[], profileTitle: string|null, profileUrl: string|null}
|
||||
* @return array{id: int|string|null, fullName: string, avatar: string|null, topAction: mixed, actions: array, lastMessage: '', emailAddresses: string[], profileTitle: string|null, profileUrl: string|null, status: string|null, statusMessage: null|string, statusIcon: null|string, isUser: bool, uid: mixed}
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
$topAction = !empty($this->actions) ? $this->actions[0]->jsonSerialize() : null;
|
||||
|
@ -160,6 +177,11 @@ class Entry implements IEntry {
|
|||
'emailAddresses' => $this->getEMailAddresses(),
|
||||
'profileTitle' => $this->profileTitle,
|
||||
'profileUrl' => $this->profileUrl,
|
||||
'status' => $this->status,
|
||||
'statusMessage' => $this->statusMessage,
|
||||
'statusIcon' => $this->statusIcon,
|
||||
'isUser' => $this->getProperty('isUser') === true,
|
||||
'uid' => $this->getProperty('UID'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,9 @@ namespace OC\Contacts\ContactsMenu;
|
|||
use Exception;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Constants;
|
||||
use OCP\Contacts\ContactsMenu\IBulkProvider;
|
||||
use OCP\Contacts\ContactsMenu\IEntry;
|
||||
use OCP\Contacts\ContactsMenu\IProvider;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
|
||||
|
@ -92,9 +94,14 @@ class Manager {
|
|||
*/
|
||||
private function processEntries(array $entries, IUser $user): void {
|
||||
$providers = $this->actionProviderStore->getProviders($user);
|
||||
foreach ($entries as $entry) {
|
||||
foreach ($providers as $provider) {
|
||||
$provider->process($entry);
|
||||
|
||||
foreach ($providers as $provider) {
|
||||
if ($provider instanceof IBulkProvider && !($provider instanceof IProvider)) {
|
||||
$provider->process($entries);
|
||||
} elseif ($provider instanceof IProvider && !($provider instanceof IBulkProvider)) {
|
||||
foreach ($entries as $entry) {
|
||||
$provider->process($entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
*
|
||||
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
namespace OCP\Contacts\ContactsMenu;
|
||||
|
||||
/**
|
||||
* Process contacts menu entries in bulk
|
||||
*
|
||||
* @since 28.0
|
||||
*/
|
||||
interface IBulkProvider {
|
||||
/**
|
||||
* @since 28.0
|
||||
* @param list<IEntry> $entries
|
||||
* @return void
|
||||
*/
|
||||
public function process(array $entries): void;
|
||||
}
|
|
@ -53,6 +53,19 @@ interface IEntry extends JsonSerializable {
|
|||
*/
|
||||
public function addAction(IAction $action): void;
|
||||
|
||||
/**
|
||||
* Set the (system) contact's user status
|
||||
*
|
||||
* @since 28.0
|
||||
* @param string $status
|
||||
* @param string $statusMessage
|
||||
* @param string|null $icon
|
||||
* @return void
|
||||
*/
|
||||
public function setStatus(string $status,
|
||||
string $statusMessage = null,
|
||||
string $icon = null): void;
|
||||
|
||||
/**
|
||||
* Get an arbitrary property from the contact
|
||||
*
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
*
|
||||
|
@ -23,6 +26,10 @@
|
|||
namespace OCP\Contacts\ContactsMenu;
|
||||
|
||||
/**
|
||||
* Process contacts menu entries
|
||||
*
|
||||
* @see IBulkProvider for providers that work with the full dataset at once
|
||||
*
|
||||
* @since 12.0
|
||||
*/
|
||||
interface IProvider {
|
||||
|
|
|
@ -103,6 +103,11 @@ class EntryTest extends TestCase {
|
|||
'emailAddresses' => ['user@example.com'],
|
||||
'profileTitle' => null,
|
||||
'profileUrl' => null,
|
||||
'status' => null,
|
||||
'statusMessage' => null,
|
||||
'statusIcon' => null,
|
||||
'isUser' => false,
|
||||
'uid' => null,
|
||||
];
|
||||
|
||||
$this->entry->setId(123);
|
||||
|
|
Loading…
Reference in New Issue