Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ node_modules/
!/apps/updatenotification
!/apps/theming
!/apps/twofactor_backupcodes
!/apps/user_picker
!/apps/user_status
!/apps/weather_status
!/apps/webhook_listeners
Expand Down
6 changes: 0 additions & 6 deletions .tx/config
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,6 @@ source_file = translationfiles/templates/user_ldap.pot
source_lang = en
type = PO

[o:nextcloud:p:nextcloud:r:user_picker]
file_filter = translationfiles/<lang>/user_picker.po
source_file = translationfiles/templates/user_picker.pot
source_lang = en
type = PO

[o:nextcloud:p:nextcloud:r:user_status]
file_filter = translationfiles/<lang>/user_status.po
source_file = translationfiles/templates/user_status.pot
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions apps/profile/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@

return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'OCA\\Profile\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
'OCA\\Profile\\Controller\\ProfilePageController' => $baseDir . '/../lib/Controller/ProfilePageController.php',
'OCA\\Profile\\Listener\\ProfilePickerReferenceListener' => $baseDir . '/../lib/Listener/ProfilePickerReferenceListener.php',
'OCA\\Profile\\Reference\\ProfilePickerReferenceProvider' => $baseDir . '/../lib/Reference/ProfilePickerReferenceProvider.php',
);
3 changes: 3 additions & 0 deletions apps/profile/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ class ComposerStaticInitProfile

public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'OCA\\Profile\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
'OCA\\Profile\\Controller\\ProfilePageController' => __DIR__ . '/..' . '/../lib/Controller/ProfilePageController.php',
'OCA\\Profile\\Listener\\ProfilePickerReferenceListener' => __DIR__ . '/..' . '/../lib/Listener/ProfilePickerReferenceListener.php',
'OCA\\Profile\\Reference\\ProfilePickerReferenceProvider' => __DIR__ . '/..' . '/../lib/Reference/ProfilePickerReferenceProvider.php',
);

public static function getInitializer(ClassLoader $loader)
Expand Down
3 changes: 3 additions & 0 deletions apps/profile/img/app-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions apps/profile/img/app.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\UserPicker\AppInfo;
namespace OCA\Profile\AppInfo;

use OCA\UserPicker\Listener\UserPickerReferenceListener;
use OCA\UserPicker\Reference\ProfilePickerReferenceProvider;
use OCA\Profile\Listener\ProfilePickerReferenceListener;
use OCA\Profile\Reference\ProfilePickerReferenceProvider;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
Expand All @@ -18,15 +18,15 @@
use OCP\Collaboration\Reference\RenderReferenceEvent;

class Application extends App implements IBootstrap {
public const APP_ID = 'user_picker';
public const APP_ID = 'profile';

public function __construct(array $urlParams = []) {
parent::__construct(self::APP_ID, $urlParams);
}

public function register(IRegistrationContext $context): void {
$context->registerReferenceProvider(ProfilePickerReferenceProvider::class);
$context->registerEventListener(RenderReferenceEvent::class, UserPickerReferenceListener::class);
$context->registerEventListener(RenderReferenceEvent::class, ProfilePickerReferenceListener::class);
}

public function boot(IBootContext $context): void {
Expand Down
47 changes: 47 additions & 0 deletions apps/profile/lib/Listener/ProfilePickerReferenceListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Profile\Listener;

use OCA\Profile\AppInfo\Application;
use OCP\Collaboration\Reference\RenderReferenceEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IAppConfig;
use OCP\Profile\IProfileManager;
use OCP\Util;

/**
* @template-implements IEventListener<RenderReferenceEvent>
*/
class ProfilePickerReferenceListener implements IEventListener {

public function __construct(
private IAppConfig $appConfig,
private IProfileManager $profileManager,
) {
}

public function handle(Event $event): void {
if (!$event instanceof RenderReferenceEvent) {
return;
}

$profileEnabledGlobally = $this->profileManager->isProfileEnabled();

$profilePickerEnabled = filter_var(
$this->appConfig->getValueString('settings', 'profile_picker_enabled', '1'),
FILTER_VALIDATE_BOOLEAN,
FILTER_NULL_ON_FAILURE,
);

if ($profileEnabledGlobally && $profilePickerEnabled) {
Util::addScript(Application::APP_ID, 'reference');
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,41 @@
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\UserPicker\Reference;
namespace OCA\Profile\Reference;

use OCA\UserPicker\AppInfo\Application;
use OCA\Profile\AppInfo\Application;
use OCP\Accounts\IAccountManager;

use OCP\Collaboration\Reference\ADiscoverableReferenceProvider;
use OCP\Collaboration\Reference\IReference;
use OCP\Collaboration\Reference\Reference;

use OCP\IAppConfig;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Profile\IProfileManager;

class ProfilePickerReferenceProvider extends ADiscoverableReferenceProvider {
public const RICH_OBJECT_TYPE = 'user_picker_profile';
public const RICH_OBJECT_TYPE = 'profile_widget';
private bool $enabled;

public function __construct(
private IL10N $l10n,
private IURLGenerator $urlGenerator,
private IUserManager $userManager,
private IAccountManager $accountManager,
private IProfileManager $profileManager,
private IAppConfig $appConfig,
private ?string $userId,
) {
$profileEnabledGlobally = $this->profileManager->isProfileEnabled();
$profilePickerEnabled = filter_var(
$this->appConfig->getValueString('settings', 'profile_picker_enabled', '1'),
FILTER_VALIDATE_BOOLEAN,
FILTER_NULL_ON_FAILURE,
);
$this->enabled = $profileEnabledGlobally && $profilePickerEnabled;
}

/**
Expand Down Expand Up @@ -65,6 +75,9 @@ public function getIconUrl(): string {
* @inheritDoc
*/
public function matchReference(string $referenceText): bool {
if (!$this->enabled) {
return false;
}
return $this->getObjectId($referenceText) !== null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div class="profile-picker">
<div class="profile-picker__heading">
<h2>
{{ t('user_picker', 'Profile picker') }}
{{ t('profile', 'Profile picker') }}
</h2>
<div class="input-wrapper">
<NcSelect
Expand All @@ -16,15 +16,15 @@
inputId="profiles-search"
:loading="loading"
:filterable="false"
:placeholder="t('user_picker', 'Search for a user profile')"
:placeholder="t('profile', 'Search for a user profile')"
:clearSearchOnBlur="() => false"
:multiple="false"
:options="options"
label="displayName"
@search="searchForProfile"
@option:selecting="resolveResult">
<template #no-options="{ search }">
{{ search ? noResultText : t('user_picker', 'Search for a user profile. Start typing') }}
{{ search ? noResultText : t('profile', 'Search for a user profile. Start typing') }}
</template>
</NcSelect>
</div>
Expand All @@ -38,10 +38,10 @@
<NcButton
v-if="selectedProfile !== null"
variant="primary"
:aria-label="t('user_picker', 'Insert selected user profile link')"
:aria-label="t('profile', 'Insert selected user profile link')"
:disabled="loading || selectedProfile === null"
@click="submit">
{{ t('user_picker', 'Insert') }}
{{ t('profile', 'Insert') }}
<template #icon>
<ArrowRightIcon />
</template>
Expand All @@ -59,7 +59,7 @@ import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
import NcSelect from '@nextcloud/vue/components/NcSelect'
import AccountOutline from 'vue-material-design-icons/AccountOutline.vue'
import ArrowRightIcon from 'vue-material-design-icons/ArrowRight.vue'
import { logger } from '../utils/logger.ts'
import { logger } from '../services/logger.ts'

export default {
name: 'ProfilesCustomPicker',
Expand Down Expand Up @@ -107,7 +107,7 @@ export default {
},

noResultText() {
return this.loading ? t('user_picker', 'Searching …') : t('user_picker', 'Not found')
return this.loading ? t('profile', 'Searching …') : t('profile', 'Not found')
},
},

Expand Down Expand Up @@ -149,7 +149,7 @@ export default {
}
})
} catch (error) {
logger.error('user_picker: error while searching for users', { error })
logger.error('profile_picker: error while searching for users', { error })
} finally {
this.loading = false
}
Expand All @@ -172,7 +172,7 @@ export default {
})
this.reference = res.data.ocs.data.references[this.resultUrl]
} catch (error) {
logger.error('user_picker: error resolving the user profile link', { error })
logger.error('profile_picker: error resolving the user profile link', { error })
} finally {
this.loading = false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { NcCustomPickerRenderResult, registerCustomPickerElement, registerWidget } from '@nextcloud/vue/components/NcRichText'

registerWidget('user_picker_profile', async (el, { richObjectType, richObject, accessible }) => {
registerWidget('profile_widget', async (el, { richObjectType, richObject, accessible }) => {
const { createApp } = await import('vue')
const { default: ProfilePickerReferenceWidget } = await import('./views/ProfilePickerReferenceWidget.vue')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import HandshakeOutline from 'vue-material-design-icons/HandshakeOutline.vue'
import MapMarkerOutline from 'vue-material-design-icons/MapMarkerOutline.vue'
import TextAccount from 'vue-material-design-icons/TextAccount.vue'
import Web from 'vue-material-design-icons/Web.vue'
import { logger } from '../utils/logger.ts'
import { logger } from '../services/logger.ts'

export default {
name: 'ProfilePickerReferenceWidget',
Expand Down Expand Up @@ -116,13 +116,18 @@ export default {
&__header {
width: 100%;
min-height: 70px;
padding: 0 12px;
background-color: var(--color-primary);
background-image: var(--gradient-primary-background);
position: relative;
display: flex;
align-items: center;
gap: 10px;
> *:first-child {
margin-left: 12px;
}
> *:last-child {
margin-right: 12px;
}
}

.profile-card__title a {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\UserPicker\Reference;

namespace OCA\Profile\Reference;

use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
use OCP\Collaboration\Reference\IReference;
use OCP\Collaboration\Reference\Reference;
use OCP\IAppConfig;
use OCP\IL10N;

use OCP\IURLGenerator;
Expand All @@ -28,6 +32,7 @@ class ProfilePickerReferenceProviderTest extends \Test\TestCase {
private IUserManager|MockObject $userManager;
private IAccountManager|MockObject $accountManager;
private IProfileManager|MockObject $profileManager;
private IAppConfig|MockObject $appConfig;
private ProfilePickerReferenceProvider $referenceProvider;

private array $testUsersData = [
Expand Down Expand Up @@ -138,15 +143,7 @@ public function setUp(): void {
$this->userManager = $this->createMock(IUserManager::class);
$this->accountManager = $this->createMock(IAccountManager::class);
$this->profileManager = $this->createMock(IProfileManager::class);

$this->referenceProvider = new ProfilePickerReferenceProvider(
$this->l10n,
$this->urlGenerator,
$this->userManager,
$this->accountManager,
$this->profileManager,
$this->userId
);
$this->appConfig = $this->createMock(IAppConfig::class);

$this->urlGenerator->expects($this->any())
->method('getBaseUrl')
Expand All @@ -156,6 +153,10 @@ public function setUp(): void {
->method('isProfileEnabled')
->willReturn(true);

$this->appConfig->expects($this->any())
->method('getValueString')
->willReturn('1');

$this->profileManager->expects($this->any())
->method('isProfileFieldVisible')
->willReturnCallback(function (string $profileField, IUser $targetUser, ?IUser $visitingUser) {
Expand All @@ -170,6 +171,16 @@ public function setUp(): void {
$this->adminUser->expects($this->any())
->method('getDisplayName')
->willReturn('admin');

$this->referenceProvider = new ProfilePickerReferenceProvider(
$this->l10n,
$this->urlGenerator,
$this->userManager,
$this->accountManager,
$this->profileManager,
$this->appConfig,
$this->userId
);
}

private function getTestAccountPropertyValue(string $testUserId, string $property): mixed {
Expand Down
1 change: 1 addition & 0 deletions apps/settings/lib/Settings/Admin/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public function getForm() {
// Profile page
$this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled());
$this->initialStateService->provideInitialState('profileEnabledByDefault', $this->isProfileEnabledByDefault($this->config));
$this->initialStateService->provideInitialState('profilePickerEnabled', $this->isProfilePickerEnabled($this->config));

// Basic settings
$this->initialStateService->provideInitialState('restrictSystemTagsCreationToAdmin', $this->appConfig->getValueBool('systemtags', 'restrict_creation_to_admin', false));
Expand Down
Loading
Loading