Skip to content

Commit

Permalink
Port Files navigation to vue
Browse files Browse the repository at this point in the history
Signed-off-by: John Molakvoæ <[email protected]>
  • Loading branch information
skjnldsv committed Jan 4, 2023
1 parent 36b6a7c commit 887c9e0
Show file tree
Hide file tree
Showing 21 changed files with 1,075 additions and 423 deletions.
33 changes: 22 additions & 11 deletions apps/files/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,34 @@
$this,
[
'routes' => [
[
'name' => 'view#index',
'url' => '/',
'verb' => 'GET',
],
[
'name' => 'view#index',
'url' => '/{view}',
'verb' => 'GET',
'postfix' => 'view',
],
[
'name' => 'view#index',
'url' => '/{view}/{fileid}',
'verb' => 'GET',
'postfix' => 'fileid',
],
[
'name' => 'View#showFile',
'url' => '/f/{fileid}',
'verb' => 'GET',
'root' => '',
],

[
'name' => 'ajax#getStorageStats',
'url' => '/ajax/getstoragestats',
'verb' => 'GET',
],
[
'name' => 'API#getThumbnail',
'url' => '/api/v1/thumbnail/{x}/{y}/{file}',
Expand Down Expand Up @@ -94,16 +115,6 @@
'url' => '/api/v1/showgridview',
'verb' => 'GET'
],
[
'name' => 'view#index',
'url' => '/',
'verb' => 'GET',
],
[
'name' => 'ajax#getStorageStats',
'url' => '/ajax/getstoragestats',
'verb' => 'GET',
],
[
'name' => 'API#toggleShowFolder',
'url' => '/api/v1/toggleShowFolder/{key}',
Expand Down
54 changes: 32 additions & 22 deletions apps/files/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
*/
OCA.Files.App = {
/**
* Navigation control
* Navigation instance
*
* @member {OCA.Files.Navigation}
* @member {OCP.Files.Navigation}
*/
navigation: null,

Expand All @@ -51,7 +51,7 @@
* Initializes the files app
*/
initialize: function() {
this.navigation = new OCA.Files.Navigation($('#app-navigation'));
this.navigation = OCP.Files.Navigation;
this.$showHiddenFiles = $('input#showhiddenfilesToggle');
var showHidden = $('#showHiddenFiles').val() === "1";
this.$showHiddenFiles.prop('checked', showHidden);
Expand Down Expand Up @@ -159,7 +159,6 @@
* Destroy the app
*/
destroy: function() {
this.navigation = null;
this.fileList.destroy();
this.fileList = null;
this.files = null;
Expand Down Expand Up @@ -216,23 +215,25 @@
* @return app container
*/
getCurrentAppContainer: function() {
return this.navigation.getActiveContainer();
var viewId = this.getActiveView();
return $('#app-content-' + viewId);
},

/**
* Sets the currently active view
* @param viewId view id
*/
setActiveView: function(viewId, options) {
this.navigation.setActiveItem(viewId, options);
window._nc_event_bus.emit('files:view:changed', { id: viewId })
},

/**
* Returns the view id of the currently active view
* @return view id
*/
getActiveView: function() {
return this.navigation.getActiveItem();
return this.navigation.active
&& this.navigation.active.id;
},

/**
Expand All @@ -254,6 +255,7 @@
$('#app-content').delegate('>div', 'afterChangeDirectory', _.bind(this._onAfterDirectoryChanged, this));
$('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, this));

window._nc_event_bus.subscribe('files:view:changed', _.bind(this._onNavigationChanged, this))
$('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this));
this.$showHiddenFiles.on('change', _.bind(this._onShowHiddenFilesChange, this));
this.$cropImagePreviews.on('change', _.bind(this._onCropImagePreviewsChange, this));
Expand Down Expand Up @@ -308,16 +310,24 @@
/**
* Event handler for when the current navigation item has changed
*/
_onNavigationChanged: function(e) {
_onNavigationChanged: function(view) {
var params;
if (e && e.itemId) {
params = {
view: typeof e.view === 'string' && e.view !== '' ? e.view : e.itemId,
dir: e.dir ? e.dir : '/'
};
if (view && (view.itemId || view.id)) {
if (view.id) {
params = {
view: view.id,
dir: '/',
}
} else {
// Legacy handling
params = {
view: typeof view.view === 'string' && view.view !== '' ? view.view : view.itemId,
dir: view.dir ? view.dir : '/'
}
}
this._changeUrl(params.view, params.dir);
OCA.Files.Sidebar.close();
this.navigation.getActiveContainer().trigger(new $.Event('urlChanged', params));
this.getCurrentAppContainer().trigger(new $.Event('urlChanged', params));
window._nc_event_bus.emit('files:navigation:changed')
}
},
Expand All @@ -327,7 +337,7 @@
*/
_onDirectoryChanged: function(e) {
if (e.dir && !e.changedThroughUrl) {
this._changeUrl(this.navigation.getActiveItem(), e.dir, e.fileId);
this._changeUrl(this.getActiveView(), e.dir, e.fileId);
}
},

Expand All @@ -336,7 +346,7 @@
*/
_onAfterDirectoryChanged: function(e) {
if (e.dir && e.fileId) {
this._changeUrl(this.navigation.getActiveItem(), e.dir, e.fileId);
this._changeUrl(this.getActiveView(), e.dir, e.fileId);
}
},

Expand All @@ -361,15 +371,15 @@
dir: '/',
view: 'files'
}, params);
var lastId = this.navigation.getActiveItem();
if (!this.navigation.itemExists(params.view)) {
var lastId = this.navigation.active;
if (!this.navigation.views.find(view => view.id === params.view)) {
params.view = 'files';
}
this.navigation.setActiveItem(params.view, {silent: true});
if (lastId !== this.navigation.getActiveItem()) {
this.navigation.getActiveContainer().trigger(new $.Event('show'));
this.setActiveView(params.view, {silent: true});
if (lastId !== this.getActiveView()) {
this.getCurrentAppContainer().trigger(new $.Event('show'));
}
this.navigation.getActiveContainer().trigger(new $.Event('urlChanged', params));
this.getCurrentAppContainer().trigger(new $.Event('urlChanged', params));
window._nc_event_bus.emit('files:navigation:changed')
},

Expand Down
1 change: 0 additions & 1 deletion apps/files/js/merged-index.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"jquery.fileupload.js",
"keyboardshortcuts.js",
"mainfileinfodetailview.js",
"navigation.js",
"newfilemenu.js",
"operationprogressbar.js",
"recentfilelist.js",
Expand Down
1 change: 0 additions & 1 deletion apps/files/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ private function registerNavigation(IL10N $l10n): void {
'script' => 'simplelist.php',
'order' => 5,
'name' => $l10n->t('Favorites'),
'expandedState' => 'show_Quick_Access'
];
});
}
Expand Down
22 changes: 11 additions & 11 deletions apps/files/lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,18 +346,18 @@ public function getGridView() {
* @throws \OCP\PreConditionNotMetException
*/
public function toggleShowFolder(int $show, string $key): Response {
// ensure the edited key exists
$navItems = \OCA\Files\App::getNavigationManager()->getAll();
foreach ($navItems as $item) {
// check if data is valid
if (($show === 0 || $show === 1) && isset($item['expandedState']) && $key === $item['expandedState']) {
$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', $key, (string)$show);
return new Response();
}
if ($show !== 0 && $show !== 1) {
return new DataResponse([
'message' => 'Invalid show value. Only 0 and 1 are allowed.'
], Http::STATUS_BAD_REQUEST);
}
$response = new Response();
$response->setStatus(Http::STATUS_FORBIDDEN);
return $response;

$userId = $this->userSession->getUser()->getUID();

// Set the new value and return it
// Using a prefix prevents the user from setting arbitrary keys
$this->config->setUserValue($userId, 'files', 'show_' . $key, (string)$show);
return new JSONResponse([$key => $show]);
}

/**
Expand Down
41 changes: 21 additions & 20 deletions apps/files/lib/Controller/ViewController.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,14 @@ public function showFile(string $fileid = null, int $openfile = 1): Response {
* @throws NotFoundException
*/
public function index($dir = '', $view = '', $fileid = null, $fileNotFound = false, $openfile = null) {
if ($fileid !== null && $dir === '') {
try {
return $this->redirectToFile($fileid);
} catch (NotFoundException $e) {
return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', ['fileNotFound' => true]));
}
}

// if ($fileid !== null && $dir === '') {
// try {
// return $this->redirectToFile($fileid);
// } catch (NotFoundException $e) {
// return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', ['fileNotFound' => true]));
// }
// }

$nav = new \OCP\Template('files', 'appnavigation', '');

Expand All @@ -205,11 +206,11 @@ public function index($dir = '', $view = '', $fileid = null, $fileNotFound = fal
// FIXME: Make non static
$storageInfo = $this->getStorageInfo();

$user = $this->userSession->getUser()->getUID();
$userId = $this->userSession->getUser()->getUID();

// Get all the user favorites to create a submenu
try {
$favElements = $this->activityHelper->getFavoriteFilePaths($this->userSession->getUser()->getUID());
$favElements = $this->activityHelper->getFavoriteFilePaths($userId);
} catch (\RuntimeException $e) {
$favElements['folders'] = [];
}
Expand All @@ -234,7 +235,7 @@ public function index($dir = '', $view = '', $fileid = null, $fileNotFound = fal
'order' => $navBarPositionPosition,
'folderPosition' => $sortingValue,
'name' => basename($favElement),
'icon' => 'files',
'icon' => 'folder',
'quickaccesselement' => 'true'
];

Expand All @@ -248,11 +249,9 @@ public function index($dir = '', $view = '', $fileid = null, $fileNotFound = fal
$navItems['favorites']['sublist'] = $favoritesSublistArray;
$navItems['favorites']['classes'] = $collapseClasses;

// parse every menu and add the expandedState user value
// parse every menu and add the expanded user value
foreach ($navItems as $key => $item) {
if (isset($item['expandedState'])) {
$navItems[$key]['defaultExpandedState'] = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', $item['expandedState'], '0') === '1';
}
$navItems[$key]['expanded'] = $this->config->getUserValue($userId, 'files', 'show_' . $item['id'], '0') === '1';
}

$nav->assign('navigationItems', $navItems);
Expand All @@ -267,10 +266,12 @@ public function index($dir = '', $view = '', $fileid = null, $fileNotFound = fal
$nav->assign('quota', $storageInfo['quota']);
$nav->assign('usage_relative', $storageInfo['relative']);

$nav->assign('webdav_url', \OCP\Util::linkToRemote('dav/files/' . rawurlencode($user)));
$nav->assign('webdav_url', \OCP\Util::linkToRemote('dav/files/' . rawurlencode($userId)));

$contentItems = [];

$this->initialState->provideInitialState('navigation', $navItems);

// render the container content for every navigation item
foreach ($navItems as $item) {
$content = '';
Expand Down Expand Up @@ -314,12 +315,12 @@ public function index($dir = '', $view = '', $fileid = null, $fileNotFound = fal
$params['ownerDisplayName'] = $storageInfo['ownerDisplayName'] ?? '';
$params['isPublic'] = false;
$params['allowShareWithLink'] = $this->shareManager->shareApiAllowLinks() ? 'yes' : 'no';
$params['defaultFileSorting'] = $this->config->getUserValue($user, 'files', 'file_sorting', 'name');
$params['defaultFileSortingDirection'] = $this->config->getUserValue($user, 'files', 'file_sorting_direction', 'asc');
$params['showgridview'] = $this->config->getUserValue($user, 'files', 'show_grid', false);
$showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
$params['defaultFileSorting'] = $this->config->getUserValue($userId, 'files', 'file_sorting', 'name');
$params['defaultFileSortingDirection'] = $this->config->getUserValue($userId, 'files', 'file_sorting_direction', 'asc');
$params['showgridview'] = $this->config->getUserValue($userId, 'files', 'show_grid', false);
$showHidden = (bool) $this->config->getUserValue($userId, 'files', 'show_hidden', false);
$params['showHiddenFiles'] = $showHidden ? 1 : 0;
$cropImagePreviews = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', true);
$cropImagePreviews = (bool) $this->config->getUserValue($userId, 'files', 'crop_image_previews', true);
$params['cropImagePreviews'] = $cropImagePreviews ? 1 : 0;
$params['fileNotFound'] = $fileNotFound ? 1 : 0;
$params['appNavigation'] = $nav;
Expand Down
54 changes: 54 additions & 0 deletions apps/files/src/legacy/navigationMapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @copyright Copyright (c) 2022 John Molakvoæ <[email protected]>
*
* @author John Molakvoæ <[email protected]>
*
* @license AGPL-3.0-or-later
*
* 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/>.
*
*/

import { loadState } from '@nextcloud/initial-state'
import logger from '../logger.js'

/**
* Fetch and register the legacy files views
*/
export default function() {
const legacyViews = Object.values(loadState('files', 'navigation', {}))

if (legacyViews.length > 0) {
logger.debug('Legacy files views detected. Processing...', legacyViews)
legacyViews.forEach(view => {
registerLegacyView(view)
if (view.sublist) {
view.sublist.forEach(subview => registerLegacyView({ ...subview, parent: view.id }))
}
})
}
}

const registerLegacyView = function({ id, name, order, icon, parent, classes = '', expanded }) {
OCP.Files.Navigation.register({
id,
name,
iconClass: icon ? `icon-${icon}` : 'nav-icon-' + id,
order,
parent,
legacy: true,
sticky: classes.includes('pinned'),
expanded: expanded === true,
})
}
Loading

0 comments on commit 887c9e0

Please sign in to comment.