From fc4baed6e5e862492ac1e2f12a408971d8ee6a26 Mon Sep 17 00:00:00 2001 From: fnuesse Date: Sat, 16 Jun 2018 22:44:18 +0200 Subject: [PATCH] Added toggleable QuickAccess Signed-off-by: fnuesse Deleted wrongly commited File Signed-off-by: fnuesse Added quickaccess-state persistence Signed-off-by: fnuesse Started implementing sorting-algorithm for proper alphabetical display Signed-off-by: fnuesse Finished Sorting of Quickaccess elements Signed-off-by: fnuesse Implemented persistence for reverse-list and sorting-strategy Signed-off-by: fnuesse Implemented initial sorting for reverse-list and sorting-strategy Signed-off-by: fnuesse Refactored Code Signed-off-by: fnuesse Refactored Code Signed-off-by: fnuesse Refactored Code Signed-off-by: fnuesse --- apps/files/appinfo/routes.php | 20 ++ apps/files/js/app.js | 40 +--- apps/files/js/navigation.js | 195 ++++++++++++++++++- apps/files/lib/Controller/ApiController.php | 56 +++++- apps/files/lib/Controller/ViewController.php | 83 ++++---- apps/files/templates/appnavigation.php | 56 +++++- core/css/apps.scss | 17 -- 7 files changed, 357 insertions(+), 110 deletions(-) diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php index 3273d6d97d..ed2373149f 100644 --- a/apps/files/appinfo/routes.php +++ b/apps/files/appinfo/routes.php @@ -86,6 +86,26 @@ $application->registerRoutes( 'url' => '/api/v1/hidequickaccess', 'verb' => 'GET', ], + [ + 'name' => 'API#setSortingStrategy', + 'url' => '/api/v1/setsortingstrategy', + 'verb' => 'GET', + ], + [ + 'name' => 'API#setReverseQuickaccess', + 'url' => '/api/v1/setreversequickaccess', + 'verb' => 'GET', + ], + [ + 'name' => 'API#getSortingStrategy', + 'url' => '/api/v1/getsortingstrategy', + 'verb' => 'GET', + ], + [ + 'name' => 'API#getReverseQuickaccess', + 'url' => '/api/v1/getreversequickaccess', + 'verb' => 'GET', + ] ] ] ); diff --git a/apps/files/js/app.js b/apps/files/js/app.js index 97b8b630f7..ec223e418b 100644 --- a/apps/files/js/app.js +++ b/apps/files/js/app.js @@ -54,18 +54,13 @@ var showHidden = $('#showHiddenFiles').val() === "1"; this.$showHiddenFiles.prop('checked', showHidden); - this.$showQuickAccess = $('input#showfavoritequickaccessToggle'); - var showQuickAccess = $('#showFavoriteQuickAccess').val() === "1"; - this.$showQuickAccess.prop('checked', showQuickAccess); - if ($('#fileNotFound').val() === "1") { OC.Notification.show(t('files', 'File could not be found'), {type: 'error'}); } this._filesConfig = new OC.Backbone.Model({ - showhidden: showHidden, - showQuickAccess: showQuickAccess + showhidden: showHidden }); var urlParams = OC.Util.History.parseUrlQuery(); @@ -138,7 +133,6 @@ }); this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200); - this._debouncedPersistShowQuickAccessState = _.debounce(this._persistShowQuickAccessState, 1200); }, /** @@ -213,7 +207,6 @@ $('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this)); this.$showHiddenFiles.on('change', _.bind(this._onShowHiddenFilesChange, this)); - this.$showQuickAccess.on('change', _.bind(this._onShowQuickAccessChange, this)); }, /** @@ -228,7 +221,7 @@ }, /** - * Persist show hidden preference on ther server + * Persist show hidden preference on the server * * @returns {undefined} */ @@ -239,35 +232,6 @@ }); }, - - /** - * Toggle showing hidden files according to the settings checkbox - * - * @returns {undefined} - */ - _onShowQuickAccessChange: function() { - var qa = this.$showQuickAccess.is(':checked'); - this._filesConfig.set('show_quick_access', qa); - this._debouncedPersistShowQuickAccessState(); - }, - - /** - * Persist show hidden preference on ther server - * - * @returns {undefined} - */ - _persistShowQuickAccessState: function() { - var qa = this._filesConfig.get('show_quick_access'); - var url="/apps/files/api/v1/hidequickaccess"; - if(qa){ - url="/apps/files/api/v1/showquickaccess"; - } - - $.get(OC.generateUrl(url),function(data, status){ - }); - }, - - /** * Event handler for when the current navigation item has changed */ diff --git a/apps/files/js/navigation.js b/apps/files/js/navigation.js index d213d0467b..cf4de7d61e 100644 --- a/apps/files/js/navigation.js +++ b/apps/files/js/navigation.js @@ -4,6 +4,8 @@ * @author Vincent Petry * @copyright 2014 Vincent Petry * + * Edited by: Felix NĂ¼sse 2018 + * * This file is licensed under the Affero General Public License version 3 * or later. * @@ -38,6 +40,10 @@ */ $currentContent: null, + /** + * Strategy by which the quickaccesslist is sorted + */ + $sortingStrategy: 'alphabet', /** * Initializes the navigation from the given container * @@ -49,13 +55,16 @@ this._activeItem = null; this.$currentContent = null; this._setupEvents(); + this.initialSort(); }, /** * Setup UI events */ _setupEvents: function() { - this.$el.on('click', 'li a', _.bind(this._onClickItem, this)); + this.$el.on('click', 'li a', _.bind(this._onClickItem, this)) + this.$el.on('click', 'li button', _.bind(this._onClickMenuButton, this)); + this.$el.on('click', 'li input', _.bind(this._onClickMenuItem, this)); }, /** @@ -127,9 +136,193 @@ this.setActiveItem(itemId); } ev.preventDefault(); + }, + /** + * Event handler for when clicking on an three-dot-menu. + */ + _onClickMenuButton: function(ev) { + var $target = $(ev.target); + var itemId = $target.closest('button').attr('id'); + if(itemId==='button-favorites'){ + document.getElementById('menu-favorites').classList.toggle('open'); + } + ev.preventDefault(); + }, + + /** + * Event handler for when clicking on a menuitem. + */ + _onClickMenuItem: function(ev) { + + var qaSelector= '#quickaccess-list'; + var qaKey= 'quickaccess-list'; + + var itemId = $(ev.target).closest('input').attr('id'); + var list = document.getElementById(qaKey).getElementsByTagName('li'); + + if(itemId==='enableQuickAccess'){ + $.get(OC.generateUrl("/apps/files/api/v1/showquickaccess"), {show: document.getElementById('enableQuickAccess').checked}, function(data, status){ + }); + $(qaSelector ).toggle(); + document.getElementById('menu-favorites').classList.toggle('open'); + } + + if(itemId==='sortByAlphabet'){ + //Prevents deselecting Group-Item + if(!document.getElementById('sortByAlphabet').checked){ + ev.preventDefault(); + return; + } + this.sortingStrategy='alphabet'; + document.getElementById('sortByDate').checked=false; + $.get(OC.generateUrl("/apps/files/api/v1/setsortingstrategy"), {strategy: this.sortingStrategy}, function(data, status){}); + this.QuickSort(list, 0, list.length - 1); + document.getElementById('menu-favorites').classList.toggle('open'); + } + + if(itemId==='sortByDate'){ + //Prevents deselecting Group-Item + if(!document.getElementById('sortByDate').checked){ + ev.preventDefault(); + return; + } + this.sortingStrategy='date'; + document.getElementById('sortByAlphabet').checked=false; + $.get(OC.generateUrl("/apps/files/api/v1/setsortingstrategy"), {strategy: this.sortingStrategy}, function(data, status){}); + this.QuickSort(list, 0, list.length - 1); + document.getElementById('menu-favorites').classList.toggle('open'); + } + + if(itemId==='enableReverse'){ + this.reverse(list); + var state = document.getElementById('enableReverse').checked; + $.get(OC.generateUrl("/apps/files/api/v1/setreversequickaccess"), {reverse: state}, function(data, status){}); + document.getElementById('menu-favorites').classList.toggle('open'); + } + //ev.preventDefault(); + }, + + /** + * Sort initially as setup of sidebar for QuickAccess + */ + initialSort: function() { + + var domRevState=document.getElementById('enableReverse').checked; + var domSortAlphabetState=document.getElementById('sortByAlphabet').checked; + var domSortDateState=document.getElementById('sortByDate').checked; + + var qaKey= 'quickaccess-list'; + var list = document.getElementById(qaKey).getElementsByTagName('li'); + + if(domSortAlphabetState){ + this.sortingStrategy='alphabet'; + } + if(domSortDateState){ + this.sortingStrategy='date'; + } + + this.QuickSort(list, 0, list.length - 1); + + if(domRevState){ + this.reverse(list); + } + + /*This creates flashes the UI, which is bad userexperience. It is the cleaner way to do it, that is why i haven't deleted it yet. + var scope=this; + $.get(OC.generateUrl("/apps/files/api/v1/getsortingstrategy"), function(data, status){ + scope.sortingStrategy=data; + scope.QuickSort(list, 0, list.length - 1); + + }); + + $.get(OC.generateUrl("/apps/files/api/v1/getreversequickaccess"), function(data, status){ + if(data){ + scope.reverse(list); + } + }); + */ + }, + + /** + * Sorting-Algorithm for QuickAccess + */ + QuickSort: function(list, start, end) { + var lastmatch; + if(list.length > 1){ + lastmatch = this.quicksort_helper(list, start, end); + if(start < lastmatch - 1){ + this.QuickSort(list, start, lastmatch - 1); + } + if(lastmatch < end){ + this.QuickSort(list, lastmatch, end); + } + } + }, + + /** + * Sorting-Algorithm-Helper for QuickAccess + */ + quicksort_helper: function(list, start, end) { + var pivot = Math.floor((end + start) / 2); + var pivotelem = this.getCompareValue(list,pivot); + var i = start; + var j = end; + + while(i <= j){ + while(this.getCompareValue(list,i) < pivotelem){ + i++; + } + while(this.getCompareValue(list,j) > pivotelem){ + j--; + } + if(i <= j){ + this.swap(list, i, j); + i++; + j--; + } + } + return i; + }, + + /** + * Sorting-Algorithm-Helper for QuickAccess + * This method allows easy access to the element which is sorted by. + */ + getCompareValue: function(nodes, int){ + if(this.sortingStrategy==='alphabet'){ + ; return nodes[int].getElementsByTagName('a')[0].innerHTML.toLowerCase() + }else if(this.sortingStrategy==='date'){ + return nodes[int].getAttribute('folderPos').toLowerCase(); + } + return nodes[int].getElementsByTagName('a')[0].innerHTML.toLowerCase(); + }, + + /** + * Sorting-Algorithm-Helper for QuickAccess + * This method allows easy swapping of elements. + */ + swap: function(list, j, i){ + list[i].before(list[j]); + list[j].before(list[i]); + }, + + /** + * Reverse QuickAccess-List + */ + reverse: function(list){ + var len=list.length-1; + for(var i = 0; i < len/2; i++) { + this.swap(list, i, len-i); + } } + }; OCA.Files.Navigation = Navigation; })(); + + + + + diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index b1af121ed6..53a8e1b55e 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -45,6 +45,7 @@ use OCP\IPreview; use OCP\Share\IManager; use OC\Files\Node\Node; use OCP\IUserSession; +use Sabre\VObject\Property\Boolean; /** * Class ApiController @@ -270,27 +271,64 @@ class ApiController extends Controller { * * @NoAdminRequired * - * @param int $value + * @param bool $show + * * @return Response */ - public function showQuickAccess() { - $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_Quick_Access', 1); + public function showQuickAccess($show) { + $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_Quick_Access', (int) $show); return new Response(); } /** - * Toggle default for showing/hiding QuickAccess folder + * quickaccess-sorting-strategy * * @NoAdminRequired * - * @param int $value + * @param string $strategy * @return Response */ - public function hideQuickAccess() { - $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_Quick_Access', 0); + public function setSortingStrategy($strategy) { + $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_sorting_strategy', (String) $strategy); return new Response(); + } + + /** + * Get reverse-state for quickaccess-list + * + * @NoAdminRequired + * + * @return String + */ + public function getSortingStrategy() { + return $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_sorting_strategy', 'date'); + } + + /** + * Toggle for reverse quickaccess-list + * + * @NoAdminRequired + * + * @param bool $reverse + * @return Response + */ + public function setReverseQuickaccess($reverse) { + $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_reverse_list', (int) $reverse); + return new Response(); + } + + /** + * Get reverse-state for quickaccess-list + * + * @NoAdminRequired + * + * @return bool + */ + public function getReverseQuickaccess() { + if($this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_reverse_list', false)){ + return true; } - - + return false; + } } diff --git a/apps/files/lib/Controller/ViewController.php b/apps/files/lib/Controller/ViewController.php index 54602839eb..11a42fb529 100644 --- a/apps/files/lib/Controller/ViewController.php +++ b/apps/files/lib/Controller/ViewController.php @@ -159,58 +159,73 @@ class ViewController extends Controller { // FIXME: Make non static $storageInfo = $this->getStorageInfo(); + $user = $this->userSession->getUser()->getUID(); + + $sorting=$this->config->getUserValue($user,$this->appName,'quickaccess_sorting_strategy','date'); + $reverseListSetting=$this->config->getUserValue($user,$this->appName,'quickaccess_reverse_list','false'); + if($this->config->getUserValue($user,$this->appName,'show_Quick_Access',true)){ + $expanded='true'; + }else{ + $expanded='false'; + } \OCA\Files\App::getNavigationManager()->add( [ 'id' => 'favorites', 'appname' => 'files', 'script' => 'simplelist.php', + 'enableQuickaccess' => $expanded, + 'quickaccessSortingStrategy' => $sorting, + 'quickaccessSortingReverse' => $reverseListSetting, 'order' => 5, 'name' => $this->l10n->t('Favorites') ] ); - - - $user = $this->userSession->getUser()->getUID(); - $tagger=\OC::$server->getTagManager(); - $helper= new \OCA\Files\Activity\Helper($tagger); $favElements = $helper->getFavoriteFilePaths($this->userSession->getUser()->getUID()); - $favItems = $favElements['items']; - $key='show_Quick_Access'; + $FavoritesFolderCount=sizeof($favElements['folders']); + if($FavoritesFolderCount>0){ - if($this->config->getUserValue($user,$this->appName,$key,true) && sizeof($favElements['folders'])>0){ - /*$nav->assign('showQuickAccess', 1); - \OCA\Files\App::getNavigationManager()->add( - [ - 'id' => 'Spacer', - 'classes' => 'app-navigation-caption', - 'order' => 6, - 'name' => $this->l10n->t('Quick-Access') - ] - );*/ + $NavBarPositionPosition=6; + $currentCount=0; + foreach($favElements['folders'] as $elem){ - $i=0; - foreach($favElements['folders'] as $elem){ + $id=substr( $elem, strrpos($elem,'/')+1, strlen($elem)); + $link=\OC::$WEBROOT.'/index.php/apps/files/?dir='.$elem; - \OCA\Files\App::getNavigationManager()->add( - [ - 'id' => substr( $elem, strrpos($elem,'/')+1, strlen($elem)), - 'href' => \OC::$WEBROOT.'/index.php/apps/files/?dir='.$elem, - 'order' => 7+$i, - 'classes' => 'app-navigation-subelement', - 'name' => substr( $elem, strrpos($elem,'/')+1, strlen($elem)), - 'icon' => 'files' - ] - ); - $i++; + $SortingValue=++$currentCount; + if($currentCount!=$FavoritesFolderCount){ + \OCA\Files\App::getNavigationManager()->add( + [ + 'id' => $id, + 'href' => $link, + 'order' => $NavBarPositionPosition, + 'folderPosition' => $SortingValue, + 'name' => $id, + 'icon' => 'files', + 'quickaccesselement' => 'true' + ] + ); + }else{ + \OCA\Files\App::getNavigationManager()->add( + [ + 'id' => $id, + 'href' => $link, + 'order' => $NavBarPositionPosition, + 'folderPosition' => $SortingValue, + 'name' => $id, + 'icon' => 'files', + 'quickaccesselement' => 'last' + ] + ); + } + $NavBarPositionPosition++; + } } - } - $navItems = \OCA\Files\App::getNavigationManager()->getAll(); @@ -218,10 +233,6 @@ class ViewController extends Controller { return $item1['order'] - $item2['order']; }); - - - - $nav->assign('navigationItems', $navItems); $nav->assign('usage', \OC_Helper::humanFileSize($storageInfo['used'])); diff --git a/apps/files/templates/appnavigation.php b/apps/files/templates/appnavigation.php index 749f36a44e..c2f15fde80 100644 --- a/apps/files/templates/appnavigation.php +++ b/apps/files/templates/appnavigation.php @@ -5,12 +5,55 @@ - +
  • - - t('Use this address to access your Files via WebDAV', array(link_to_docs('user-webdav'))));?> diff --git a/core/css/apps.scss b/core/css/apps.scss index 2e3ab7b1a2..ab4e338a69 100644 --- a/core/css/apps.scss +++ b/core/css/apps.scss @@ -602,23 +602,6 @@ kbd { user-select: none; pointer-events:none; } - - .app-navigation-subelement { - line-height: 24px; - white-space: nowrap; - text-overflow: ellipsis; - float: left; - padding-left: 14px; - & a { - //Overrides normal size for smaller subelements - line-height: 24px; - min-height: 24px; - //Removes the double border on the a element - &:visited { box-shadow:none;} - &:hover { box-shadow:none;} - &:active {box-shadow:none; } - } - } } /* APP-CONTENT ---------------------------------------------------------------*/