diff --git a/lib/ConfigLexicon.php b/lib/ConfigLexicon.php
index 27031c654..5c52a549f 100644
--- a/lib/ConfigLexicon.php
+++ b/lib/ConfigLexicon.php
@@ -33,6 +33,7 @@ class ConfigLexicon implements ILexicon {
public const FEDERATIONS_CACHE = 'federations_cache';
public const FEDERATIONS_CACHE_EXPIRES = 'expires';
public const FEDERATIONS_CACHE_DELTA_EXPIRES = 'delta_expires';
+ public const HIDE_TEAM_SHARED_FOLDER_CREATION = 'hide_team_shared_folder_creation';
#[\Override]
public function getStrictness(): Strictness {
@@ -107,6 +108,13 @@ public function getAppConfigs(): array {
definition: 'Federations cache update (delta) expiration time.',
lazy: true,
),
+ new Entry(
+ self::HIDE_TEAM_SHARED_FOLDER_CREATION,
+ ValueType::BOOL,
+ defaultRaw: false,
+ definition: 'Hide the team-page button that creates a personal folder and shares it with the team.',
+ lazy: true,
+ ),
];
}
diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php
index a68d8d8ff..370e706a0 100644
--- a/lib/Controller/PageController.php
+++ b/lib/Controller/PageController.php
@@ -9,6 +9,7 @@
use OC\App\CompareVersion;
use OCA\Contacts\AppInfo\Application;
+use OCA\Contacts\ConfigLexicon;
use OCA\Contacts\Service\FederatedInvitesService;
use OCA\Contacts\Service\GroupSharingService;
use OCA\Contacts\Service\SocialApiService;
@@ -16,6 +17,7 @@
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
+use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IRequest;
use OCP\IUserSession;
@@ -29,6 +31,7 @@ public function __construct(
IRequest $request,
private FederatedInvitesService $federatedInvitesService,
private IConfig $config,
+ private IAppConfig $appConfig,
private IInitialState $initialState,
private IFactory $languageFactory,
private IUserSession $userSession,
@@ -83,6 +86,10 @@ public function index(string $token = '', string $providerDomain = ''): Template
$isTalkVersionCompatible = $this->compareVersion->isCompatible($talkVersion ? $talkVersion : '0.0.0', 2);
$isOcmInvitesEnabled = $this->federatedInvitesService->isOcmInvitesEnabled();
$ocmInvitesConfig = $this->federatedInvitesService->getOcmInvitesConfig();
+ $hideTeamSharedFolderCreation = $this->appConfig->getValueBool(
+ Application::APP_ID,
+ ConfigLexicon::HIDE_TEAM_SHARED_FOLDER_CREATION,
+ );
$this->initialState->provideInitialState('isGroupSharingEnabled', $isGroupSharingEnabled);
$this->initialState->provideInitialState('locales', $locales);
@@ -95,6 +102,7 @@ public function index(string $token = '', string $providerDomain = ''): Template
$this->initialState->provideInitialState('isTalkEnabled', $isTalkEnabled && $isTalkVersionCompatible);
$this->initialState->provideInitialState('isOcmInvitesEnabled', $isOcmInvitesEnabled);
$this->initialState->provideInitialState('ocmInvitesConfig', $ocmInvitesConfig);
+ $this->initialState->provideInitialState('hideTeamSharedFolderCreation', $hideTeamSharedFolderCreation);
Util::addStyle(Application::APP_ID, 'contacts-main');
Util::addScript(Application::APP_ID, 'contacts-main');
diff --git a/src/components/CircleDetails.vue b/src/components/CircleDetails.vue
index fb478bcdd..3d219dddf 100644
--- a/src/components/CircleDetails.vue
+++ b/src/components/CircleDetails.vue
@@ -151,7 +151,7 @@
-
+
{{ t('contacts', 'Create') }}
@@ -327,6 +327,7 @@ import TeamResourceButton from './CircleDetails/TeamResourceButton.vue'
import MemberList from './MemberList/MemberList.vue'
import CircleActionsMixin from '../mixins/CircleActionsMixin.js'
import { CircleEdit, editCircle } from '../services/circles.ts'
+import hideTeamSharedFolderCreation from '../services/hideTeamSharedFolderCreation.js'
import logger from '../services/logger.js'
import 'cropperjs/dist/cropper.css'
@@ -541,7 +542,7 @@ export default {
helperText: t('contacts', 'This will create a regular folder shared with the team. To create a Team Folder, please contact your {productName} administrator', { productName: OC.theme.name }),
icon: 'FolderOutlineIcon',
apiPath: 'files',
- enabled: enabledApps.files !== undefined,
+ enabled: enabledApps.files !== undefined && !hideTeamSharedFolderCreation,
},
{
id: 'talk',
diff --git a/src/services/hideTeamSharedFolderCreation.js b/src/services/hideTeamSharedFolderCreation.js
new file mode 100644
index 000000000..d139be073
--- /dev/null
+++ b/src/services/hideTeamSharedFolderCreation.js
@@ -0,0 +1,9 @@
+/**
+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { loadState } from '@nextcloud/initial-state'
+
+const hideTeamSharedFolderCreation = loadState('contacts', 'hideTeamSharedFolderCreation', false)
+export default hideTeamSharedFolderCreation
diff --git a/tests/unit/Controller/PageControllerTest.php b/tests/unit/Controller/PageControllerTest.php
index 1cd8ba637..1200bd40c 100644
--- a/tests/unit/Controller/PageControllerTest.php
+++ b/tests/unit/Controller/PageControllerTest.php
@@ -10,12 +10,14 @@
use ChristophWurst\Nextcloud\Testing\TestCase;
use OC\App\CompareVersion;
use OCA\Contacts\AppInfo\Application;
+use OCA\Contacts\ConfigLexicon;
use OCA\Contacts\Service\FederatedInvitesService;
use OCA\Contacts\Service\GroupSharingService;
use OCA\Contacts\Service\SocialApiService;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
+use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IRequest;
use OCP\IUser;
@@ -33,6 +35,9 @@ class PageControllerTest extends TestCase {
/** @var IConfig|MockObject */
private $config;
+ /** @var IAppConfig|MockObject */
+ private $appConfig;
+
/** @var IInitialState|MockObject */
private $initialStateService;
@@ -59,6 +64,7 @@ protected function setUp(): void {
$this->request = $this->createMock(IRequest::class);
$this->config = $this->createMock(IConfig::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
$this->initialStateService = $this->createMock(IInitialState::class);
$this->languageFactory = $this->createMock(IFactory::class);
$this->userSession = $this->createMock(IUserSession::class);
@@ -76,6 +82,7 @@ private function buildController(ServerVersion $serverVersion): PageController {
$this->request,
$this->federatedInvitesService,
$this->config,
+ $this->appConfig,
$this->initialStateService,
$this->languageFactory,
$this->userSession,
@@ -99,6 +106,47 @@ public function testIndex() {
$this->assertTrue($result instanceof TemplateResponse);
}
+ public function testIndexProvidesHideTeamSharedFolderCreation() {
+ $user = $this->createMock(IUser::class);
+ $user->method('getUid')->willReturn('mrstest');
+ $this->userSession->method('getUser')->willReturn($user);
+
+ $this->appConfig->method('getValueBool')
+ ->willReturnCallback(function (string $app, string $key, bool $default = false) {
+ $this->assertSame(Application::APP_ID, $app);
+ if ($key === ConfigLexicon::HIDE_TEAM_SHARED_FOLDER_CREATION) {
+ return true;
+ }
+ return $default;
+ });
+
+ $states = [];
+ $this->initialStateService->method('provideInitialState')
+ ->willReturnCallback(function (string $key, mixed $value) use (&$states): void {
+ $states[$key] = $value;
+ });
+
+ $this->controller->index();
+
+ $this->assertTrue($states['hideTeamSharedFolderCreation']);
+ }
+
+ public function testIndexHideTeamSharedFolderCreationDefaultsToFalse() {
+ $user = $this->createMock(IUser::class);
+ $user->method('getUid')->willReturn('mrstest');
+ $this->userSession->method('getUser')->willReturn($user);
+
+ $states = [];
+ $this->initialStateService->method('provideInitialState')
+ ->willReturnCallback(function (string $key, mixed $value) use (&$states): void {
+ $states[$key] = $value;
+ });
+
+ $this->controller->index();
+
+ $this->assertFalse($states['hideTeamSharedFolderCreation']);
+ }
+
public static function teamManagementDataProvider(): array {
return [
// [server major version, circles enabled, circles version compatible, expected]