Skip to content
Next Next commit
feat(NavigationManager): Add default entries handling
Signed-off-by: provokateurin <[email protected]>
  • Loading branch information
provokateurin committed Sep 9, 2024
commit b0baaaed9dfdce8c2630255d0d1921679579761d
4 changes: 3 additions & 1 deletion apps/files/lib/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Server;
use Psr\Log\LoggerInterface;

class App {
private static ?INavigationManager $navigationManager = null;
Expand All @@ -32,7 +33,8 @@ public static function getNavigationManager(): INavigationManager {
Server::get(IFactory::class),
Server::get(IUserSession::class),
Server::get(IGroupManager::class),
Server::get(IConfig::class)
Server::get(IConfig::class),
Server::get(LoggerInterface::class),
);
self::$navigationManager->clear(false);
}
Expand Down
97 changes: 87 additions & 10 deletions lib/private/NavigationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
*/
namespace OC;

use InvalidArgumentException;
use OC\App\AppManager;
use OC\Group\Manager;
use OCP\App\IAppManager;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use Psr\Log\LoggerInterface;

/**
* Manages the ownCloud navigation
Expand All @@ -41,25 +44,30 @@ class NavigationManager implements INavigationManager {
private $groupManager;
/** @var IConfig */
private $config;
/** The default app for the current user (cached for the `add` function) */
private ?string $defaultApp;
/** The default entry for the current user (cached for the `add` function) */
private ?string $defaultEntry;
/** User defined app order (cached for the `add` function) */
private array $customAppOrder;
private LoggerInterface $logger;

public function __construct(IAppManager $appManager,
public function __construct(
IAppManager $appManager,
IURLGenerator $urlGenerator,
IFactory $l10nFac,
IUserSession $userSession,
IGroupManager $groupManager,
IConfig $config) {
IConfig $config,
LoggerInterface $logger,
) {
$this->appManager = $appManager;
$this->urlGenerator = $urlGenerator;
$this->l10nFac = $l10nFac;
$this->userSession = $userSession;
$this->groupManager = $groupManager;
$this->config = $config;
$this->logger = $logger;

$this->defaultApp = null;
$this->defaultEntry = null;
}

/**
Expand Down Expand Up @@ -93,7 +101,7 @@ public function add($entry) {
}

// This is the default app that will always be shown first
$entry['default'] = ($entry['app'] ?? false) === $this->defaultApp;
$entry['default'] = ($entry['id'] ?? false) === $this->defaultEntry;
// Set order from user defined app order
$entry['order'] = (int)($this->customAppOrder[$id]['order'] ?? $entry['order'] ?? 100);
}
Expand Down Expand Up @@ -156,10 +164,10 @@ private function proceedNavigation(array $list, string $type): array {
unset($navEntry);
}

$activeApp = $this->getActiveEntry();
if ($activeApp !== null) {
$activeEntry = $this->getActiveEntry();
if ($activeEntry !== null) {
foreach ($list as $index => &$navEntry) {
if ($navEntry['id'] == $activeApp) {
if ($navEntry['id'] == $activeEntry) {
$navEntry['active'] = true;
} else {
$navEntry['active'] = false;
Expand Down Expand Up @@ -213,7 +221,7 @@ private function init() {
]);
}

$this->defaultApp = $this->appManager->getDefaultAppForUser($this->userSession->getUser(), false);
$this->defaultEntry = $this->getDefaultEntryIdForUser($this->userSession->getUser(), false);

if ($this->userSession->isLoggedIn()) {
// Profile
Expand Down Expand Up @@ -401,4 +409,73 @@ private function isSubadmin() {
public function setUnreadCounter(string $id, int $unreadCounter): void {
$this->unreadCounters[$id] = $unreadCounter;
}

public function get(string $id): array|null {
$this->init();
foreach ($this->closureEntries as $c) {
$this->add($c());
}
$this->closureEntries = [];

return $this->entries[$id];
}

public function getDefaultEntryIdForUser(?IUser $user = null, bool $withFallbacks = true): string {
$this->init();
$defaultEntryIds = explode(',', $this->config->getSystemValueString('defaultapp', ''));
$defaultEntryIds = array_filter($defaultEntryIds);

$user ??= $this->userSession->getUser();

if ($user !== null) {
$userDefaultEntryIds = explode(',', $this->config->getUserValue($user->getUID(), 'core', 'defaultapp'));
$defaultEntryIds = array_filter(array_merge($userDefaultEntryIds, $defaultEntryIds));
if (empty($defaultEntryIds) && $withFallbacks) {
/* Fallback on user defined apporder */
$customOrders = json_decode($this->config->getUserValue($user->getUID(), 'core', 'apporder', '[]'), true, flags: JSON_THROW_ON_ERROR);
if (!empty($customOrders)) {
// filter only entries with app key (when added using closures or NavigationManager::add the app is not guaranteed to be set)
$customOrders = array_filter($customOrders, static fn ($entry) => isset($entry['app']));
// sort apps by order
usort($customOrders, static fn ($a, $b) => $a['order'] - $b['order']);
// set default apps to sorted apps
$defaultEntryIds = array_map(static fn ($entry) => $entry['app'], $customOrders);
}
}
}

if (empty($defaultEntryIds) && $withFallbacks) {
$defaultEntryIds = ['dashboard','files'];
}

$entryIds = array_keys($this->entries);

// Find the first app that is enabled for the current user
foreach ($defaultEntryIds as $defaultEntryId) {
if (in_array($defaultEntryId, $entryIds, true)) {
return $defaultEntryId;
}
}

// Set fallback to always-enabled files app
return $withFallbacks ? 'files' : '';
}

public function getDefaultEntryIds(): array {
return explode(',', $this->config->getSystemValueString('defaultapp', 'dashboard,files'));
}

public function setDefaultEntryIds(array $ids): void {
$this->init();
$entryIds = array_keys($this->entries);

foreach ($ids as $id) {
if (!in_array($id, $entryIds, true)) {
$this->logger->debug('Cannot set unavailable entry as default entry', ['missing_entry' => $id]);
throw new InvalidArgumentException('Entry not available');
}
}

$this->config->setSystemValue('defaultapp', join(',', $ids));
}
}
38 changes: 38 additions & 0 deletions lib/public/INavigationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,42 @@ public function getAll(string $type = self::TYPE_APPS): array;
* @since 22.0.0
*/
public function setUnreadCounter(string $id, int $unreadCounter): void;

/**
* Get a navigation entry by id.
*
* @param string $id ID of the navigation entry
* @since 31.0.0
*/
public function get(string $id): array|null;

/**
* Returns the id of the user's default entry
*
* If `user` is not passed, the currently logged in user will be used
*
* @param ?IUser $user User to query default entry for
* @param bool $withFallbacks Include fallback values if no default entry was configured manually
* Before falling back to predefined default entries,
* the user defined entry order is considered and the first entry would be used as the fallback.
* @since 31.0.0
*/
public function getDefaultEntryIdForUser(?IUser $user = null, bool $withFallbacks = true): string;

/**
* Get the global default entries with fallbacks
*
* @return string[] The default entries
* @since 31.0.0
*/
public function getDefaultEntryIds(): array;

/**
* Set the global default entries with fallbacks
*
* @param string[] $ids
* @throws \InvalidArgumentException If any of the entries is not available
* @since 31.0.0
*/
public function setDefaultEntryIds(array $ids): void;
}
Loading