Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>tags/v26.0.0beta1
@@ -480,7 +480,9 @@ table td.filename .thumbnail { | |||
display: inline-block; | |||
width: 32px; | |||
height: 32px; | |||
background-size: 32px; | |||
background-size: contain; | |||
background-position: center; | |||
background-repeat: no-repeat; | |||
margin-left: 9px; | |||
margin-top: 9px; | |||
border-radius: var(--border-radius); |
@@ -380,7 +380,9 @@ table td.filename .thumbnail { | |||
display: inline-block; | |||
width: 32px; | |||
height: 32px; | |||
background-size: 32px; | |||
background-size: contain; | |||
background-position: center; | |||
background-repeat: no-repeat; | |||
margin-left: 9px; | |||
margin-top: 9px; | |||
border-radius: var(--border-radius); |
@@ -480,7 +480,9 @@ table td.filename .thumbnail { | |||
display: inline-block; | |||
width: 32px; | |||
height: 32px; | |||
background-size: 32px; | |||
background-size: contain; | |||
background-position: center; | |||
background-repeat: no-repeat; | |||
margin-left: 9px; | |||
margin-top: 9px; | |||
border-radius: var(--border-radius); |
@@ -66,7 +66,7 @@ | |||
this._filesConfig = OCP.InitialState.loadState('files', 'config', {}) | |||
var urlParams = OC.Util.History.parseUrlQuery(); | |||
var { fileid, scrollto, openfile } = OC.Util.History.parseUrlQuery(); | |||
var fileActions = new OCA.Files.FileActions(); | |||
// default actions | |||
fileActions.registerDefaultActions(); | |||
@@ -86,8 +86,8 @@ | |||
folderDropOptions: folderDropOptions, | |||
fileActions: fileActions, | |||
allowLegacyActions: true, | |||
scrollTo: urlParams.scrollto, | |||
openFile: urlParams.openfile, | |||
scrollTo: scrollto, | |||
openFile: openfile, | |||
filesClient: OC.Files.getClient(), | |||
multiSelectMenu: [ | |||
{ | |||
@@ -136,7 +136,8 @@ | |||
this._setupEvents(); | |||
// trigger URL change event handlers | |||
this._onPopState(urlParams); | |||
console.debug('F2V init', { ...OC.Util.History.parseUrlQuery(), view: this.navigation?.active?.id }) | |||
this._onPopState({ ...OC.Util.History.parseUrlQuery(), view: this.navigation?.active?.id }); | |||
this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200); | |||
this._debouncedPersistCropImagePreviewsState = _.debounce(this._persistCropImagePreviewsState, 1200); | |||
@@ -216,7 +217,8 @@ | |||
* @param viewId view id | |||
*/ | |||
setActiveView: function(viewId) { | |||
window._nc_event_bus.emit('files:navigation:changed', { id: viewId }) | |||
// The Navigation API will handle the final event | |||
window._nc_event_bus.emit('files:legacy-navigation:changed', { id: viewId }) | |||
}, | |||
/** | |||
@@ -308,20 +310,25 @@ | |||
* Event handler for when the URL changed | |||
*/ | |||
_onPopState: function(params) { | |||
console.debug('F2V onPopState', params); | |||
params = _.extend({ | |||
dir: '/', | |||
view: 'files' | |||
}, params); | |||
var lastId = this.navigation.active; | |||
if (!this.navigation.views.find(view => view.id === params.view)) { | |||
params.view = 'files'; | |||
} | |||
this.setActiveView(params.view, {silent: true}); | |||
if (lastId !== this.getActiveView()) { | |||
this.getCurrentAppContainer().trigger(new $.Event('show')); | |||
this.getCurrentAppContainer().trigger(new $.Event('show', params)); | |||
} | |||
// this.getCurrentAppContainer().trigger(new $.Event('urlChanged', params)); | |||
this.getCurrentAppContainer().trigger(new $.Event('urlChanged', params)); | |||
window._nc_event_bus.emit('files:navigation:changed') | |||
}, | |||
/** | |||
@@ -341,7 +348,8 @@ | |||
* Change the URL to point to the given dir and view | |||
*/ | |||
_changeUrl: function(view, dir, fileId) { | |||
var params = {dir: dir}; | |||
console.debug('F2V changeUrl', { arguments }); | |||
var params = { dir: dir }; | |||
if (view !== 'files') { | |||
params.view = view; | |||
} else if (fileId) { | |||
@@ -349,7 +357,7 @@ | |||
} | |||
var currentParams = OC.Util.History.parseUrlQuery(); | |||
if (currentParams.dir === params.dir && currentParams.view === params.view) { | |||
if (parseInt(currentParams.fileid) !== parseInt(params.fileid)) { | |||
if (currentParams.fileid !== params.fileid) { | |||
// if only fileid changed or was added, replace instead of push | |||
console.debug('F2V 1', currentParams.fileid, params.fileid, params); | |||
OC.Util.History.replaceState(this._makeUrlParams(params)); |
@@ -67,7 +67,7 @@ window.addEventListener('DOMContentLoaded', function() { | |||
reload: function() { | |||
this.showMask(); | |||
if (this._reloadCall) { | |||
if (this._reloadCall?.abort) { | |||
this._reloadCall.abort(); | |||
} | |||
@@ -395,7 +395,6 @@ | |||
this.$fileList.on('change', 'td.selection>.selectCheckBox', _.bind(this._onClickFileCheckbox, this)); | |||
this.$fileList.on('mouseover', 'td.selection', _.bind(this._onMouseOverCheckbox, this)); | |||
console.debug('F2V', this.$el); | |||
this.$el.on('show', _.bind(this._onShow, this)); | |||
this.$el.on('urlChanged', _.bind(this._onUrlChanged, this)); | |||
this.$el.find('.select-all').click(_.bind(this._onClickSelectAll, this)); | |||
@@ -416,7 +415,7 @@ | |||
this._setCurrentDir(options.dir || '/', false); | |||
} | |||
if(options.openFile) { | |||
if (options.openFile) { | |||
// Wait for some initialisation process to be over before triggering the default action. | |||
_.defer(() => { | |||
try { | |||
@@ -757,7 +756,7 @@ | |||
* Event handler when leaving previously hidden state | |||
*/ | |||
_onShow: function(e) { | |||
console.debug('F2V', 'onShow', e); | |||
console.debug('F2V onShow', [e.dir, e.itemId], e); | |||
OCA.Files.App && OCA.Files.App.updateCurrentFileList(this); | |||
if (e.itemId === this.id) { | |||
this._setCurrentDir('/', false); | |||
@@ -772,7 +771,7 @@ | |||
* Event handler for when the URL changed | |||
*/ | |||
_onUrlChanged: function(e) { | |||
console.debug('F2V', 'onUrlChanged', e); | |||
console.debug('F2V onUrlChanged', [e.dir], e); | |||
if (e && _.isString(e.dir)) { | |||
var currentDir = this.getCurrentDirectory(); | |||
// this._currentDirectory is NULL when fileList is first initialised |
@@ -72,7 +72,7 @@ window.addEventListener('DOMContentLoaded', function () { | |||
reload: function () { | |||
this.showMask(); | |||
if (this._reloadCall) { | |||
if (this._reloadCall?.abort) { | |||
this._reloadCall.abort(); | |||
} | |||
@@ -22,10 +22,11 @@ | |||
import Vue from 'vue' | |||
import Router from 'vue-router' | |||
import { generateUrl } from '@nextcloud/router' | |||
import { stringify } from 'query-string' | |||
Vue.use(Router) | |||
export default new Router({ | |||
const router = new Router({ | |||
mode: 'history', | |||
// if index.php is in the url AND we got this far, then it's working: | |||
@@ -40,9 +41,17 @@ export default new Router({ | |||
alias: '/files', | |||
}, | |||
{ | |||
path: '/:view/:fileId?', | |||
path: '/:view/:fileid?', | |||
name: 'filelist', | |||
props: true, | |||
}, | |||
], | |||
// Custom stringifyQuery to prevent encoding of slashes in the url | |||
stringifyQuery(query) { | |||
const result = stringify(query).replace(/%2F/gmi, '/') | |||
return result ? ('?' + result) : '' | |||
}, | |||
}) | |||
export default router |
@@ -21,29 +21,33 @@ | |||
--> | |||
<template> | |||
<NcAppNavigation> | |||
<NcAppNavigationItem v-for="view in parentViews" | |||
:key="view.id" | |||
:allow-collapse="true" | |||
:to="{name: 'filelist', params: { view: view.id }}" | |||
:icon="view.iconClass" | |||
:open="view.expanded" | |||
:pinned="view.sticky" | |||
:title="view.name" | |||
@update:open="onToggleExpand(view)"> | |||
<NcAppNavigationItem v-for="child in childViews[view.id]" | |||
:key="child.id" | |||
:to="{name: 'filelist', params: { view: child.id }}" | |||
:icon="child.iconClass" | |||
:title="child.name" /> | |||
</NcAppNavigationItem> | |||
<template #list> | |||
<NcAppNavigationItem v-for="view in parentViews" | |||
:key="view.id" | |||
:allow-collapse="true" | |||
:to="{name: 'filelist', params: { view: view.id }}" | |||
:icon="view.iconClass" | |||
:open="view.expanded" | |||
:pinned="view.sticky" | |||
:title="view.name" | |||
@update:open="onToggleExpand(view)"> | |||
<NcAppNavigationItem v-for="child in childViews[view.id]" | |||
:key="child.id" | |||
:to="{name: 'filelist', params: { view: child.id }}" | |||
:icon="child.iconClass" | |||
:title="child.name" /> | |||
</NcAppNavigationItem> | |||
</template> | |||
<!-- Settings toggle --> | |||
<template #footer> | |||
<NcAppNavigationItem :pinned="true" | |||
:title="t('files', 'Files settings')" | |||
@click.prevent.stop="openSettings"> | |||
<Cog slot="icon" :size="20" /> | |||
</NcAppNavigationItem> | |||
<ul class="app-navigation-entry__settings"> | |||
<NcAppNavigationItem :aria-label="t('files', 'Open the files app settings')" | |||
:title="t('files', 'Files settings')" | |||
@click.prevent.stop="openSettings"> | |||
<Cog slot="icon" :size="20" /> | |||
</NcAppNavigationItem> | |||
</ul> | |||
</template> | |||
<!-- Settings modal--> | |||
@@ -53,7 +57,7 @@ | |||
</template> | |||
<script> | |||
import { emit } from '@nextcloud/event-bus' | |||
import { emit, subscribe } from '@nextcloud/event-bus' | |||
import { generateUrl } from '@nextcloud/router' | |||
import axios from '@nextcloud/axios' | |||
import NcAppNavigation from '@nextcloud/vue/dist/Components/NcAppNavigation.js' | |||
@@ -90,7 +94,7 @@ export default { | |||
computed: { | |||
currentViewId() { | |||
return this.$route.params.view || 'files' | |||
return this.$route?.params?.view || 'files' | |||
}, | |||
currentView() { | |||
return this.views.find(view => view.id === this.currentViewId) | |||
@@ -137,6 +141,8 @@ export default { | |||
logger.debug('Navigation mounted. Showing requested view', { view: this.currentView }) | |||
this.showView(this.currentView) | |||
} | |||
subscribe('files:legacy-navigation:changed', this.onLegacyNavigationChanged) | |||
}, | |||
methods: { | |||
@@ -156,19 +162,43 @@ export default { | |||
newAppContent.classList.remove('hidden') | |||
// Legacy event | |||
console.debug('F2V', jQuery(newAppContent)) | |||
console.debug('F2V', $(newAppContent)) | |||
// Trigger init if not already done | |||
window.jQuery(newAppContent).trigger(new window.jQuery.Event('show')) | |||
// After show, properly send the right data | |||
this.$nextTick(() => { | |||
const { dir = '/' } = OC.Util.History.parseUrlQuery() | |||
const params = { itemId: view.id, dir } | |||
console.debug('F2V showView events', params, newAppContent); | |||
window.jQuery(newAppContent).trigger(new window.jQuery.Event('show', params)) | |||
window.jQuery(newAppContent).trigger(new window.jQuery.Event('urlChanged', params)) | |||
}) | |||
// previousItemId: oldItemId, | |||
// dir: itemDir, | |||
// view: itemView | |||
$(newAppContent).trigger(new $.Event('show', { itemId: view.id, dir: '/' })) | |||
$(newAppContent).trigger(new $.Event('urlChanged', { itemId: view.id, dir: '/' })) | |||
} | |||
this.Navigation.setActive(view) | |||
emit('files:navigation:changed', view) | |||
}, | |||
/** | |||
* Coming from the legacy files app. | |||
* TODO: remove when all views are migrated. | |||
* | |||
* @param {Navigation} view the new active view | |||
*/ | |||
onLegacyNavigationChanged({ id } = { id: 'files' }) { | |||
const view = this.Navigation.views.find(view => view.id === id) | |||
if (view && view.legacy && view.id !== this.currentView.id) { | |||
// Force update the current route as the request comes | |||
// from the legacy files app router | |||
this.$router.replace({ ...this.$route, params: { view: view.id } }) | |||
this.Navigation.setActive(view) | |||
this.showView(view) | |||
} | |||
}, | |||
/** | |||
* Expand/collapse a a view with children and permanently | |||
* save this setting in the server. | |||
@@ -206,4 +236,17 @@ export default { | |||
background-repeat: no-repeat; | |||
background-position: center; | |||
} | |||
.app-navigation > ul.app-navigation__list { | |||
// Use flex gap value for more elegant spacing | |||
padding-bottom: var(--default-grid-baseline, 4px); | |||
} | |||
.app-navigation-entry__settings { | |||
height: auto !important; | |||
overflow: hidden !important; | |||
padding-top: 0 !important; | |||
// Prevent shrinking or growing | |||
flex: 0 0 auto; | |||
} | |||
</style> |
@@ -96,7 +96,7 @@ export default { | |||
settings: OCA.Files.Settings.settings, | |||
// Webdav infos | |||
webdavUrl: generateRemoteUrl('dav/files/' + getCurrentUser()?.uid), | |||
webdavUrl: generateRemoteUrl('dav/files/' + encodeURIComponent(getCurrentUser()?.uid)), | |||
webdavDocs: 'https://docs.nextcloud.com/server/stable/go.php?to=user-webdav', | |||
} | |||
}, |
@@ -84,7 +84,7 @@ | |||
reload: function() { | |||
this.showMask(); | |||
if (this._reloadCall) { | |||
if (this._reloadCall?.abort) { | |||
this._reloadCall.abort(); | |||
} | |||
@@ -179,7 +179,7 @@ | |||
reload: function() { | |||
this.showMask() | |||
if (this._reloadCall) { | |||
if (this._reloadCall?.abort) { | |||
this._reloadCall.abort() | |||
} | |||
@@ -292,7 +292,7 @@ | |||
this._selectionSummary.clear() | |||
this.$el.find('.select-all').prop('checked', false) | |||
this.showMask() | |||
if (this._reloadCall) { | |||
if (this._reloadCall?.abort) { | |||
this._reloadCall.abort() | |||
} | |||
this._reloadCall = this.client.getFolderContents( |
@@ -117,10 +117,6 @@ export const configureNextcloud = async function() { | |||
await runExec(container, ['php', 'occ', 'config:system:set', 'force_locale', '--value', 'en_US'], true) | |||
await runExec(container, ['php', 'occ', 'config:system:set', 'enforce_theme', '--value', 'light'], true) | |||
// Enable the app and give status | |||
await runExec(container, ['php', 'occ', 'app:enable', '--force', 'viewer'], true) | |||
// await runExec(container, ['php', 'occ', 'app:list'], true) | |||
console.log('└─ Nextcloud is now ready to use 🎉') | |||
} | |||