Merge pull request 'Release v2.0.0' (#74) from develop into master
Reviewed-on: #74
This commit is contained in:
commit
6296c1c807
10
.drone.yml
10
.drone.yml
|
@ -21,8 +21,8 @@ steps:
|
||||||
- name: release
|
- name: release
|
||||||
image: deblan/devenv
|
image: deblan/devenv
|
||||||
volumes:
|
volumes:
|
||||||
- name: artefacts
|
- name: artifacts
|
||||||
path: /artefacts
|
path: /artifacts
|
||||||
environment:
|
environment:
|
||||||
APP_CERTIFICATE:
|
APP_CERTIFICATE:
|
||||||
from_secret: app_certificate
|
from_secret: app_certificate
|
||||||
|
@ -30,13 +30,13 @@ steps:
|
||||||
- mkdir -p "$HOME/.nextcloud/certificates"
|
- mkdir -p "$HOME/.nextcloud/certificates"
|
||||||
- echo "$APP_CERTIFICATE" > "$HOME/.nextcloud/certificates/side_menu.key"
|
- echo "$APP_CERTIFICATE" > "$HOME/.nextcloud/certificates/side_menu.key"
|
||||||
- export VERSION=$(grep "<version>" appinfo/info.xml | grep -o "[0-9]*\.[0-9]*\.[0-9]*" --color=never)
|
- export VERSION=$(grep "<version>" appinfo/info.xml | grep -o "[0-9]*\.[0-9]*\.[0-9]*" --color=never)
|
||||||
- export RELEASE_DIRECTORY="/artefacts/deblan/side_menu"
|
- export RELEASE_DIRECTORY="/artifacts/deblan/side_menu"
|
||||||
- make release
|
- make release
|
||||||
when:
|
when:
|
||||||
branch:
|
branch:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: artefacts
|
- name: artifacts
|
||||||
host:
|
host:
|
||||||
path: /var/www/html/_artefacts
|
path: /var/www/html/artifacts
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## 2.0.0
|
||||||
|
### Fixed
|
||||||
|
- fix #66: removing usage of setInterval
|
||||||
|
- fix #73: icon background
|
||||||
|
### Changed
|
||||||
|
- fix #67: replace jQuery with Vanilla JS
|
||||||
|
### Removed
|
||||||
|
- Nextcloud 18 is not supported anymore
|
||||||
|
|
||||||
## 1.28.0
|
## 1.28.0
|
||||||
### Added
|
### Added
|
||||||
- fix #63: add a new side menu with categories
|
- fix #63: add a new side menu with categories
|
||||||
|
|
1028
CODE_OF_CONDUCT.md
1028
CODE_OF_CONDUCT.md
File diff suppressed because one or more lines are too long
2
Makefile
2
Makefile
|
@ -13,7 +13,7 @@ release: npm-build translations
|
||||||
|
|
||||||
test -d releases/$$VERSION && rm -fr releases/$$VERSION
|
test -d releases/$$VERSION && rm -fr releases/$$VERSION
|
||||||
mkdir -p releases/$$VERSION/side_menu
|
mkdir -p releases/$$VERSION/side_menu
|
||||||
cp -r README.md CHANGELOG.md appinfo css lib img l10n js src templates screenshots releases/$$VERSION/side_menu
|
cp -r README.md CHANGELOG.md appinfo css lib img l10n js src templates screenshots vendor releases/$$VERSION/side_menu
|
||||||
cd releases/$$VERSION
|
cd releases/$$VERSION
|
||||||
zip -r side_menu_v$$VERSION.zip side_menu
|
zip -r side_menu_v$$VERSION.zip side_menu
|
||||||
tar cvzf side_menu_v$$VERSION.tar.gz side_menu
|
tar cvzf side_menu_v$$VERSION.tar.gz side_menu
|
||||||
|
|
|
@ -26,7 +26,7 @@ If you like this application and if you want to support the development:
|
||||||
* [Donate with liberapay](https://liberapay.com/deblan)
|
* [Donate with liberapay](https://liberapay.com/deblan)
|
||||||
* [Leave a comment](https://apps.nextcloud.com/apps/side_menu#comments)
|
* [Leave a comment](https://apps.nextcloud.com/apps/side_menu#comments)
|
||||||
]]></description>
|
]]></description>
|
||||||
<version>1.28.0</version>
|
<version>2.0.0</version>
|
||||||
<licence>agpl</licence>
|
<licence>agpl</licence>
|
||||||
<author mail="contact@deblan.fr" homepage="https://www.deblan.io/">Simon Vieille</author>
|
<author mail="contact@deblan.fr" homepage="https://www.deblan.io/">Simon Vieille</author>
|
||||||
<namespace>SideMenu</namespace>
|
<namespace>SideMenu</namespace>
|
||||||
|
@ -46,7 +46,7 @@ If you like this application and if you want to support the development:
|
||||||
<screenshot>https://gitnet.fr/deblan/side_menu/raw/branch/master/screenshots/nc20_big_menu_responsive.png</screenshot>
|
<screenshot>https://gitnet.fr/deblan/side_menu/raw/branch/master/screenshots/nc20_big_menu_responsive.png</screenshot>
|
||||||
<screenshot>https://gitnet.fr/deblan/side_menu/raw/branch/master/screenshots/personal_settings.png</screenshot>
|
<screenshot>https://gitnet.fr/deblan/side_menu/raw/branch/master/screenshots/personal_settings.png</screenshot>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<nextcloud min-version="18" max-version="22"/>
|
<nextcloud min-version="19" max-version="22"/>
|
||||||
<php min-version="7.3"/>
|
<php min-version="7.3"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<settings>
|
<settings>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
margin: 10px 0 10px 0;
|
margin: 10px 0 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#side-menu-section input[type="checkbox"] {
|
#-dropside-menu-section input[type="checkbox"] {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +81,12 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.side-menu-setting-list-drop {
|
||||||
|
background: yellow;
|
||||||
|
border-color: yellow;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
.side-menu-setting.arrow {
|
.side-menu-setting.arrow {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#header .side-menu-opener {
|
#header .side-menu-opener {
|
||||||
margin-left: 5px;
|
margin-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.side-menu-settings {
|
.side-menu-settings {
|
||||||
|
@ -67,10 +67,19 @@
|
||||||
|
|
||||||
.side-menu-opener {
|
.side-menu-opener {
|
||||||
background: var(--side-menu-opener, url('../img/side-menu-opener.svg'));
|
background: var(--side-menu-opener, url('../img/side-menu-opener.svg'));
|
||||||
height: 40px;
|
background-color: transparent !important;
|
||||||
width: 40px;
|
height: 40px !important;
|
||||||
border-radius: 0;
|
width: 40px !important;
|
||||||
border: 0;
|
border-radius: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
padding-right: 12px !important;
|
||||||
|
padding-left: 12px !important;
|
||||||
|
margin-left: 5px !important;
|
||||||
|
margin-left: 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-menu-opener:active {
|
||||||
|
background-color: var(--color-background-dark) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.side-menu-closer {
|
.side-menu-closer {
|
||||||
|
@ -139,7 +148,6 @@
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
padding-left: 5px;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ const mountSideMenuComponent = () => {
|
||||||
|
|
||||||
sideMenu.$mount('#side-menu')
|
sideMenu.$mount('#side-menu')
|
||||||
|
|
||||||
$('body').trigger('side-menu.ready')
|
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.ready'))
|
||||||
} else {
|
} else {
|
||||||
window.setTimeout(mountSideMenuComponent, 50)
|
window.setTimeout(mountSideMenuComponent, 50)
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,13 +122,15 @@ export default {
|
||||||
name: trim(element.querySelector('span').innerHTML),
|
name: trim(element.querySelector('span').innerHTML),
|
||||||
icon: svg,
|
icon: svg,
|
||||||
active: element.classList.contains('active')
|
active: element.classList.contains('active')
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(function(apps) {
|
(function(apps) {
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
jQuery('body').trigger('side-menu.apps', [apps])
|
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
|
||||||
|
detail: {apps: apps},
|
||||||
|
}))
|
||||||
}, 1000)
|
}, 1000)
|
||||||
})(this.apps)
|
})(this.apps)
|
||||||
},
|
},
|
||||||
|
@ -147,7 +149,7 @@ export default {
|
||||||
that.logo = config['logo']
|
that.logo = config['logo']
|
||||||
that.logoLink = config['logo-link']
|
that.logoLink = config['logo-link']
|
||||||
that.settings = config['settings']
|
that.settings = config['settings']
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
|
@ -97,8 +97,10 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery('body').trigger('side-menu.apps', [apps])
|
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
|
||||||
});
|
detail: {apps: apps},
|
||||||
|
}))
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
retrieveActiveApp() {
|
retrieveActiveApp() {
|
||||||
|
@ -116,7 +118,7 @@ export default {
|
||||||
|
|
||||||
that.targetBlankApps = config['target-blank-apps']
|
that.targetBlankApps = config['target-blank-apps']
|
||||||
that.settings = config['settings']
|
that.settings = config['settings']
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
|
@ -95,8 +95,10 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery('body').trigger('side-menu.apps', [apps])
|
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
|
||||||
});
|
detail: {apps: apps},
|
||||||
|
}))
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
retrieveActiveApp() {
|
retrieveActiveApp() {
|
||||||
|
@ -114,7 +116,7 @@ export default {
|
||||||
|
|
||||||
that.targetBlankApps = config['target-blank-apps']
|
that.targetBlankApps = config['target-blank-apps']
|
||||||
that.settings = config['settings']
|
that.settings = config['settings']
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
187
src/admin.js
187
src/admin.js
|
@ -17,13 +17,23 @@
|
||||||
|
|
||||||
let elements = []
|
let elements = []
|
||||||
|
|
||||||
const selector = '#side-menu-message';
|
const selector = '#side-menu-message'
|
||||||
|
|
||||||
const userConfig = (name, value, callbacks) => {
|
const userConfig = (name, value, callbacks) => {
|
||||||
const url = OC.generateUrl('/apps/side_menu/personalSetting/valueSet')
|
const url = OC.generateUrl('/apps/side_menu/personalSetting/valueSet')
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('name', name)
|
||||||
|
formData.append('value', value)
|
||||||
|
|
||||||
$.post(url, {name: name, value: value}, callbacks.success)
|
fetch(url, {
|
||||||
.fail(callbacks.error)
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(callbacks.success)
|
||||||
|
.catch(callbacks.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
const appConfig = (name, value, callbacks) => {
|
const appConfig = (name, value, callbacks) => {
|
||||||
|
@ -31,23 +41,29 @@ const appConfig = (name, value, callbacks) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveSettings = (key) => {
|
const saveSettings = (key) => {
|
||||||
const element = elements.get(key)
|
const element = elements[key]
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let value
|
let value
|
||||||
let name
|
let name
|
||||||
|
|
||||||
if (jQuery(element).is('[data-checkbox]')) {
|
if (element.hasAttribute('data-checkbox')) {
|
||||||
name = jQuery(element).attr('data-name')
|
name = element.getAttribute('data-name')
|
||||||
const inputs = jQuery('input[name="' + name + '[]"]:checked')
|
|
||||||
value = []
|
value = []
|
||||||
|
|
||||||
inputs.each((i, v) => {
|
const inputs = document.querySelectorAll('input[name="' + name + '[]"]:checked')
|
||||||
value.push(v.value)
|
|
||||||
})
|
for (let input of inputs) {
|
||||||
|
value.push(input.value)
|
||||||
|
}
|
||||||
|
|
||||||
value = JSON.stringify(value)
|
value = JSON.stringify(value)
|
||||||
} else {
|
} else {
|
||||||
name = jQuery(element).attr('name')
|
name = element.getAttribute('name')
|
||||||
value = jQuery(element).val()
|
value = element.value
|
||||||
}
|
}
|
||||||
|
|
||||||
const size = elements.length
|
const size = elements.length
|
||||||
|
@ -63,8 +79,8 @@ const saveSettings = (key) => {
|
||||||
t('side_menu', (key + 1) + '/' + size)
|
t('side_menu', (key + 1) + '/' + size)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (key < size - 1) {
|
if (key < size) {
|
||||||
saveSettings(++key)
|
saveSettings(key + 1)
|
||||||
} else {
|
} else {
|
||||||
OC.msg.finishedSuccess(selector, t('side_menu', 'Saved'))
|
OC.msg.finishedSuccess(selector, t('side_menu', 'Saved'))
|
||||||
}
|
}
|
||||||
|
@ -74,7 +90,7 @@ const saveSettings = (key) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jQuery(element).is('[data-personal]')) {
|
if (element.hasAttribute('data-personal')) {
|
||||||
userConfig(name, value, callbacks)
|
userConfig(name, value, callbacks)
|
||||||
} else {
|
} else {
|
||||||
appConfig(name, value, callbacks)
|
appConfig(name, value, callbacks)
|
||||||
|
@ -82,84 +98,105 @@ const saveSettings = (key) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const elementToggler = (element) => {
|
const elementToggler = (element) => {
|
||||||
jQuery(element).toggle()
|
let display = 'none'
|
||||||
|
|
||||||
|
if (window.getComputedStyle(element).display === 'none') {
|
||||||
|
display = 'block'
|
||||||
|
}
|
||||||
|
|
||||||
|
element.style.display = display
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery(document).ready(() => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
elements = jQuery('.side-menu-setting')
|
elements = document.querySelectorAll('.side-menu-setting')
|
||||||
|
|
||||||
jQuery('#side-menu-save').on('click', (event) => {
|
document.querySelector('#side-menu-save').addEventListener('click', (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
OC.msg.startSaving(selector)
|
OC.msg.startSaving(selector)
|
||||||
|
|
||||||
saveSettings(0)
|
saveSettings(0)
|
||||||
});
|
|
||||||
|
|
||||||
jQuery('.side-menu-display').on('click', (event) => {
|
|
||||||
var target = jQuery(event.target)
|
|
||||||
|
|
||||||
jQuery('.side-menu-display').removeClass('is-active')
|
|
||||||
target.addClass('is-active')
|
|
||||||
|
|
||||||
jQuery('#side-menu-always-displayed').val(target.attr('data-alwaysdiplayed'))
|
|
||||||
jQuery('#side-menu-big-menu').val(target.attr('data-bigmenu'))
|
|
||||||
jQuery('#side-menu-side-with-categories').val(target.attr('data-sidewithcategories'))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
jQuery('.side-menu-setting-live').on('change', (event) => {
|
const displays = document.querySelectorAll('.side-menu-display')
|
||||||
var target = jQuery(event.target)
|
|
||||||
var name = target.attr('name')
|
|
||||||
var value = target.val()
|
|
||||||
|
|
||||||
if ('background-color-opacity' === name) {
|
for (let display of displays) {
|
||||||
return $('#side-menu-background-color, #side-menu-background-color-to').trigger('change');
|
display.addEventListener('click', (event) => {
|
||||||
} else if ('dark-mode-background-color-opacity' === name) {
|
const target = event.target
|
||||||
return $('#side-menu-dark-mode-background-color, #side-menu-dark-mode-background-color-to').trigger('change');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name === 'opener') {
|
for (let d of displays) {
|
||||||
var url = OC.generateUrl(`/apps/side_menu/img/${value}.svg`).replace('/index.php', '')
|
d.classList.toggle('is-active', d === display)
|
||||||
|
}
|
||||||
|
|
||||||
value = `url(${url})`;
|
document.querySelector('#side-menu-always-displayed').value = target.getAttribute('data-alwaysdiplayed')
|
||||||
}
|
document.querySelector('#side-menu-big-menu').value = target.getAttribute('data-bigmenu')
|
||||||
|
document.querySelector('#side-menu-side-with-categories').value = target.getAttribute('data-sidewithcategories')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (name === 'icon-invert-filter' || name === 'icon-opacity') {
|
for (let item of document.querySelectorAll('.side-menu-setting-live')) {
|
||||||
value/=100;
|
item.addEventListener('change', (event) => {
|
||||||
}
|
const target = event.target
|
||||||
|
const name = target.getAttribute('name')
|
||||||
|
|
||||||
if (['dark-mode-background-color', 'dark-mode-background-color-to'].indexOf(name) > -1) {
|
let value = target.value
|
||||||
var opacity = parseInt($('#side-menu-dark-mode-background-color-opacity').val() * 255 / 100);
|
let id = null
|
||||||
|
|
||||||
value = [value, opacity.toString(16)].join('');
|
if (name === 'background-color-opacity') {
|
||||||
} else if (['background-color', 'background-color-to'].indexOf(name) > -1) {
|
id = '#side-menu-background-color, #side-menu-background-color-to'
|
||||||
var opacity = parseInt($('#side-menu-background-color-opacity').val() * 255 / 100);
|
} else if (name === 'dark-mode-background-color-opacity') {
|
||||||
|
id = '#side-menu-dark-mode-background-color, #side-menu-dark-mode-background-color-to'
|
||||||
|
}
|
||||||
|
|
||||||
value = [value, opacity.toString(16)].join('');
|
if (id) {
|
||||||
}
|
document.querySelector(id).dispatchEvent(new CustomEvent('change'))
|
||||||
|
|
||||||
document.documentElement.style.setProperty('--side-menu-' + name, value)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'opener') {
|
||||||
|
const url = OC.generateUrl(`/apps/side_menu/img/${value}.svg`).replace('/index.php', '')
|
||||||
|
|
||||||
|
value = `url(${url})`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'icon-invert-filter' || name === 'icon-opacity') {
|
||||||
|
value/=100
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['dark-mode-background-color', 'dark-mode-background-color-to'].indexOf(name) > -1) {
|
||||||
|
const opacity = parseInt(document.querySelector('#side-menu-dark-mode-background-color-opacity').value * 255 / 100)
|
||||||
|
|
||||||
|
value = [value, opacity.toString(16)].join('')
|
||||||
|
} else if (['background-color', 'background-color-to'].indexOf(name) > -1) {
|
||||||
|
const opacity = parseInt(document.querySelector('#side-menu-background-color-opacity').value * 255 / 100)
|
||||||
|
|
||||||
|
value = [value, opacity.toString(16)].join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
document.documentElement.style.setProperty('--side-menu-' + name, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let toggler of document.querySelectorAll('.side-menu-toggler')) {
|
||||||
|
toggler.addEventListener('click', (event) => {
|
||||||
|
const target = event.target
|
||||||
|
const element = document.querySelector(target.getAttribute('data-target'))
|
||||||
|
|
||||||
|
elementToggler(element)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sortable('#categories-list .side-menu-setting-list', {
|
||||||
|
placeholderClass: 'side-menu-setting-list-drop'
|
||||||
})
|
})
|
||||||
|
|
||||||
jQuery('.side-menu-toggler').on('click', (event) => {
|
sortable('#categories-list .side-menu-setting-list')[0].addEventListener('sortstop', (e) => {
|
||||||
var target = jQuery(event.target)
|
let value = []
|
||||||
var element = target.attr('data-target')
|
|
||||||
|
|
||||||
elementToggler(element)
|
for (let item of document.querySelectorAll('#categories-list .side-menu-setting-list-item')) {
|
||||||
|
value.push(item.getAttribute('data-id'))
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector('input[name="categories-order"]').value = JSON.stringify(value)
|
||||||
})
|
})
|
||||||
|
})
|
||||||
jQuery("#categories-list .side-menu-setting-list").sortable({
|
|
||||||
forcePlaceholderSize: true,
|
|
||||||
placeholder: 'placeholder',
|
|
||||||
stop: function (event, ui) {
|
|
||||||
let value = []
|
|
||||||
|
|
||||||
jQuery('#categories-list .side-menu-setting-list-item').each(function() {
|
|
||||||
value.push(jQuery(this).attr('data-id'))
|
|
||||||
});
|
|
||||||
|
|
||||||
value = JSON.stringify(value)
|
|
||||||
|
|
||||||
jQuery('input[name="categories-order"]').val(value)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
var alwaysDisplayed = function() {
|
const alwaysDisplayed = function() {
|
||||||
var elements = document.querySelectorAll('*');
|
const elements = querySelectorAll('*')
|
||||||
var fixedElements = []
|
const fixedElements = []
|
||||||
|
|
||||||
for (var i in elements) {
|
|
||||||
var element = elements[i]
|
|
||||||
|
|
||||||
|
for (var element of elements) {
|
||||||
if (typeof element !== 'object') {
|
if (typeof element !== 'object') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var position = window.getComputedStyle(element, null).getPropertyValue('position');
|
const position = window.getComputedStyle(element, null).getPropertyValue('position')
|
||||||
|
|
||||||
if (position !== 'fixed') {
|
if (position !== 'fixed') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = element.getAttribute('id')
|
const id = element.getAttribute('id')
|
||||||
|
|
||||||
if (id === 'header' || id === 'side-menu' || id === 'side-menu-loader') {
|
if (id === 'header' || id === 'side-menu' || id === 'side-menu-loader') {
|
||||||
continue
|
continue
|
||||||
|
@ -25,7 +23,21 @@ var alwaysDisplayed = function() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jQuery(element).parents('#side-menu').length) {
|
let elementIsInSideMenu = false
|
||||||
|
let parent = element.parentNode
|
||||||
|
|
||||||
|
while (parent && !elementIsInSideMenu) {
|
||||||
|
try {
|
||||||
|
if (parent.getAttribute('id') === 'side-menu') {
|
||||||
|
elementIsInSideMenu = true
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = parent.parentNode
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementIsInSideMenu) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,19 +45,19 @@ var alwaysDisplayed = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i in fixedElements) {
|
for (var i in fixedElements) {
|
||||||
var element = fixedElements[i]
|
const element = fixedElements[i]
|
||||||
var computedStyle = window.getComputedStyle(element, null)
|
const computedStyle = window.getComputedStyle(element, null)
|
||||||
var left = computedStyle.getPropertyValue('left')
|
const left = computedStyle.getPropertyValue('left')
|
||||||
var right = computedStyle.getPropertyValue('right')
|
const right = computedStyle.getPropertyValue('right')
|
||||||
|
|
||||||
if (right !== '0px') {
|
if (right !== '0px') {
|
||||||
var intValue = parseInt(left.replace('px', ''))
|
const intValue = parseInt(left.replace('px', '')) + 50
|
||||||
element.style.setProperty('transform', 'translateX(' + (intValue + 50) + 'px)')
|
element.style.setProperty('transform', 'translateX(' + intValue.toString() + 'px)')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = document.getElementById('content')
|
const content = querySelector('#content')
|
||||||
|
|
||||||
if (content && content.classList.contains('app-settings')) {
|
if (content && content.classList.contains('app-settings')) {
|
||||||
let loaded = false
|
let loaded = false
|
||||||
|
@ -56,7 +68,7 @@ if (content && content.classList.contains('app-settings')) {
|
||||||
}
|
}
|
||||||
const observer = new MutationObserver(() => {
|
const observer = new MutationObserver(() => {
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = content.querySelector('#app-category-your-apps') || content.querySelector('#app-navigation ul')
|
const element = content.querySelector('#app-category-your-apps') || content.querySelector('#app-navigation ul')
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
var pageLoader = jQuery('<div id="side-menu-loader">')
|
let pageLoader = createElement('div', {id: 'side-menu-loader'})
|
||||||
var pageLoaderBar = jQuery('<div id="side-menu-loader-bar">')
|
let pageLoaderBar = createElement('div', {id: 'side-menu-loader-bar'})
|
||||||
|
|
||||||
body.append(pageLoader)
|
pageLoader.appendChild(pageLoaderBar)
|
||||||
pageLoader.append(pageLoaderBar)
|
querySelector('body').appendChild(pageLoader)
|
||||||
|
|
||||||
var pageLoaderValue = 0
|
let pageLoaderValue = 0
|
||||||
|
|
||||||
$(window).on('beforeunload', function() {
|
|
||||||
setInterval(function() {
|
|
||||||
pageLoaderBar.width(pageLoaderValue.toString() + '%')
|
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', () => {
|
||||||
|
setInterval(() => {
|
||||||
|
pageLoaderBar.style.width = pageLoaderValue.toString() + '%'
|
||||||
pageLoaderValue = Math.min(pageLoaderValue + .2, 100)
|
pageLoaderValue = Math.min(pageLoaderValue + .2, 100)
|
||||||
}, 25)
|
}, 25)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,32 +1,55 @@
|
||||||
var menuCache = null
|
let menuCache = null
|
||||||
|
|
||||||
var updateTopMenu = function() {
|
const breakpointMobileWidth = 1024
|
||||||
var breakpointMobileWidth = 1024
|
const usePercentualAppMenuLimit = 0.8
|
||||||
var menu = jQuery('#appmenu')
|
const minAppsDesktop = 8
|
||||||
var apps = menu.find('li')
|
|
||||||
var minAppsDesktop = 8
|
|
||||||
var usePercentualAppMenuLimit = 0.8
|
|
||||||
var isMobile = jQuery(window).width() < breakpointMobileWidth
|
|
||||||
var lastShownApp = null
|
|
||||||
var appShown = []
|
|
||||||
var moreApps = jQuery('#more-apps')
|
|
||||||
var navigation = jQuery('#navigation')
|
|
||||||
var navigationApps = jQuery('#apps ul')
|
|
||||||
var appCount = null
|
|
||||||
|
|
||||||
var currentMenuCache = menu.html() + menu.next().html()
|
const handleMenuClick = (e, icon) => {
|
||||||
|
let element = e.target
|
||||||
|
|
||||||
if (currentMenuCache === menuCache) {
|
while (element.tagName !== 'LI') {
|
||||||
|
element = element.parentNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const a = querySelector('a', element)
|
||||||
|
|
||||||
|
if (a.getAttribute('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey) {
|
||||||
|
for (let tag of ['svg', 'div']) {
|
||||||
|
let el = querySelector(tag, element)
|
||||||
|
|
||||||
|
if (el) {
|
||||||
|
el.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loader = createElement('div', {'class': icon})
|
||||||
|
|
||||||
|
a.insertBefore(loader, querySelector('span', a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateTopMenu = function() {
|
||||||
|
const isMobile = window.innerWidth < breakpointMobileWidth
|
||||||
|
const menu = querySelector('#appmenu')
|
||||||
|
const moreApps = querySelector('#more-apps')
|
||||||
|
const navigation = querySelector('#navigation')
|
||||||
|
const navigationApps = querySelector('#apps ul')
|
||||||
|
|
||||||
|
let apps = querySelectorAll('li', menu)
|
||||||
|
let lastShownApp = null
|
||||||
|
let appShown = []
|
||||||
|
|
||||||
|
if ((menu.innerHTML + menu.nextSibling.innerHTML) === menuCache) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationApps.html('')
|
navigationAppsHtml = ''
|
||||||
|
|
||||||
apps.each(function(i, app) {
|
for (let app of apps) {
|
||||||
var dataId = app.getAttribute('data-id')
|
const dataId = app.getAttribute('data-id')
|
||||||
|
|
||||||
if (dataId === null) {
|
if (dataId === null) {
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topMenuApps.indexOf(dataId) === -1) {
|
if (topMenuApps.indexOf(dataId) === -1) {
|
||||||
|
@ -35,26 +58,31 @@ var updateTopMenu = function() {
|
||||||
} else {
|
} else {
|
||||||
app.classList.remove('hidden')
|
app.classList.remove('hidden')
|
||||||
app.classList.add('app-external-site')
|
app.classList.add('app-external-site')
|
||||||
|
|
||||||
appShown.push(app)
|
appShown.push(app)
|
||||||
navigationApps.append(app.outerHTML)
|
|
||||||
|
navigationAppsHtml = navigationAppsHtml + app.outerHTML
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetBlankApps.indexOf(dataId) !== -1) {
|
if (targetBlankApps.indexOf(dataId) !== -1) {
|
||||||
jQuery(app).children('a').attr('target', '_blank');
|
querySelector('a', app).setAttribute('target', '_blank')
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
var rightHeaderWidth = jQuery('.header-right').outerWidth()
|
|
||||||
var headerWidth = jQuery('header').outerWidth()
|
|
||||||
var availableWidth = headerWidth - jQuery('#nextcloud').outerWidth()
|
|
||||||
- jQuery('#header .side-menu-opener').outerWidth()
|
|
||||||
- (rightHeaderWidth > 230 ? rightHeaderWidth : 230)
|
|
||||||
|
|
||||||
if (!isMobile) {
|
|
||||||
availableWidth = availableWidth * usePercentualAppMenuLimit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appCount = Math.floor(availableWidth / jQuery('#appmenu li').width())
|
navigationApps.innerHTML = navigationAppsHtml
|
||||||
|
|
||||||
|
const rightHeaderWidth = querySelector('.header-right').offsetWidth
|
||||||
|
const headerWidth = querySelector('header').offsetWidth
|
||||||
|
|
||||||
|
let availableWidth = headerWidth
|
||||||
|
|
||||||
|
availableWidth -= nextcloud.offsetWidth
|
||||||
|
availableWidth -= querySelector('#header .side-menu-opener').offsetWidth
|
||||||
|
availableWidth -= rightHeaderWidth > 230 ? rightHeaderWidth : 230
|
||||||
|
availableWidth *= isMobile ? usePercentualAppMenuLimit : 1
|
||||||
|
|
||||||
|
let appCount = Math.floor(availableWidth / querySelector('#appmenu li:not(.hidden)').offsetWidth)
|
||||||
|
|
||||||
if (isMobile && appCount > minAppsDesktop) {
|
if (isMobile && appCount > minAppsDesktop) {
|
||||||
appCount = minAppsDesktop
|
appCount = minAppsDesktop
|
||||||
|
@ -62,111 +90,125 @@ var updateTopMenu = function() {
|
||||||
appCount = minAppsDesktop
|
appCount = minAppsDesktop
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appCount === 0) {
|
menu.style.opacity = 1
|
||||||
menu.addClass('hidden')
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.removeClass('hidden')
|
|
||||||
menu.css('opacity', 1)
|
|
||||||
|
|
||||||
if (appShown.length - 1 - appCount >= 1) {
|
if (appShown.length - 1 - appCount >= 1) {
|
||||||
appCount--
|
appCount--
|
||||||
}
|
}
|
||||||
|
|
||||||
moreApps.find('a').removeClass('active')
|
for (let item of querySelectorAll('a', moreApps)) {
|
||||||
|
item.classList.remove('active')
|
||||||
|
}
|
||||||
|
|
||||||
var k = 0
|
let k = 0
|
||||||
var notInHeader = 0
|
let notInHeader = 0
|
||||||
var name
|
|
||||||
|
|
||||||
jQuery(appShown).each(function(i, app) {
|
|
||||||
app = jQuery(app)
|
for (let app of appShown) {
|
||||||
name = app.data('id')
|
const name = app.getAttribute('data-id')
|
||||||
|
const li = querySelector('#apps li[data-id=' + name + '].app-external-site')
|
||||||
|
|
||||||
if (k < appCount && appCount > 0) {
|
if (k < appCount && appCount > 0) {
|
||||||
app.removeClass('hidden')
|
app.classList.remove('hidden')
|
||||||
lastShownApp = app
|
li.classList.add('in-header')
|
||||||
|
|
||||||
jQuery('#apps li[data-id=' + name + '].app-external-site').addClass('in-header')
|
lastShownApp = app
|
||||||
} else {
|
} else {
|
||||||
app.addClass('hidden')
|
app.classList.add('hidden')
|
||||||
|
li.classList.remove('in-header')
|
||||||
|
|
||||||
notInHeader++
|
notInHeader++
|
||||||
|
|
||||||
jQuery('#apps li[data-id=' + name + '].app-external-site').removeClass('in-header')
|
const a = querySelector('a', app)
|
||||||
|
|
||||||
if (appCount > 0 && app.children('a').hasClass('active')) {
|
if (appCount > 0 && a.classList.contains('active')) {
|
||||||
lastShownApp.addClass('hidden')
|
lastShownApp.classList.add('hidden')
|
||||||
app.removeClass('hidden')
|
app.classList.remove('hidden')
|
||||||
notInHeader++
|
notInHeader++
|
||||||
|
|
||||||
jQuery('#apps li[data-id=' + name + '].app-external-site')
|
li.classList.add('in-header')
|
||||||
.removeClass('in-header')
|
|
||||||
.addClass('in-header')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
k++
|
k++
|
||||||
})
|
}
|
||||||
|
|
||||||
// Hack for https://github.com/nextcloud/server/blob/23b0b63c213f5b31eecae817ffd4a9e26f6624d0/core/src/components/MainMenu.js#L74-L96
|
// Hack for:
|
||||||
menu.undelegate('li:not(#more-apps) > a', 'click')
|
// - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
|
||||||
menu.delegate('li:not(#more-apps) > a', 'click', function(e) {
|
// - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
|
||||||
var a = $(e.target)
|
jQuery(menu).undelegate('li:not(#more-apps) > a', 'click')
|
||||||
|
jQuery(navigation).undelegate('a', 'click')
|
||||||
|
|
||||||
if (!a.is('a')) {
|
const confs = [
|
||||||
a = a.closest('a')
|
{
|
||||||
|
items: querySelectorAll('#navigation li'),
|
||||||
|
icon: 'icon-loading-small'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: querySelectorAll('li:not(#more-apps)', menu),
|
||||||
|
icon: OCA.Theming && OCA.Theming.inverted ? 'icon-loading-small' : 'icon-loading-small-dark'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
for (let conf of confs) {
|
||||||
|
for (let item of conf.items) {
|
||||||
|
item.addEventListener('click', (e) => {
|
||||||
|
handleMenuClick(e, conf.icon)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (a.attr('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey && a.parent('#more-apps').length === 0) {
|
for (let app of querySelectorAll('#apps li.app-external-site')) {
|
||||||
a.find('svg').remove()
|
const appId = app.getAttribute('data-id')
|
||||||
a.find('div').remove()
|
|
||||||
a.prepend(jQuery('<div/>').addClass(
|
|
||||||
OCA.Theming && OCA.Theming.inverted
|
|
||||||
? 'icon-loading-small'
|
|
||||||
: 'icon-loading-small-dark'
|
|
||||||
))
|
|
||||||
|
|
||||||
window.location.href = a.attr('href')
|
if (app.classList.contains('in-header')) {
|
||||||
}
|
for (let defs of querySelectorAll('svg defs', app)) {
|
||||||
})
|
defs.remove()
|
||||||
|
}
|
||||||
jQuery('#apps li.app-external-site').each(function(i, app) {
|
|
||||||
app = jQuery(app)
|
|
||||||
var appId = app.attr('data-id')
|
|
||||||
|
|
||||||
if (app.hasClass('in-header')) {
|
|
||||||
app.find('svg').find('defs').remove()
|
|
||||||
} else {
|
} else {
|
||||||
var svg = app.find('svg');
|
const svg = querySelector('svg', app)
|
||||||
|
|
||||||
if (svg.find('defs').length > 0) {
|
if (querySelectorAll('svg defs', app).length > 0) {
|
||||||
return;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var defs = `
|
const defs = `
|
||||||
<defs>
|
<defs>
|
||||||
<filter id="invertMenuMore-${appId}">
|
<filter id="invertMenuMore-${appId}">
|
||||||
<feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix>
|
<feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix>
|
||||||
</filter>
|
</filter>
|
||||||
</defs>`
|
</defs>`
|
||||||
|
|
||||||
svg.prepend(defs)
|
svg.innerHTML = defs + svg.innerHTML
|
||||||
svg.find('image').attr('filter', `url(#invertMenuMore-${appId})`)
|
|
||||||
|
|
||||||
var html = svg.get(0).innerHTML.replace(/fecolormatrix/g, 'feColorMatrix');
|
for (let image of querySelectorAll('image', svg)) {
|
||||||
|
image.setAttribute('filter', `url(#invertMenuMore-${appId})`)
|
||||||
|
}
|
||||||
|
|
||||||
svg.html(html)
|
svg.innerHTML = svg.innerHTML.replace(/fecolormatrix/g, 'feColorMatrix')
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
if (notInHeader === 0) {
|
|
||||||
moreApps.hide()
|
|
||||||
navigation.hide()
|
|
||||||
} else {
|
|
||||||
moreApps.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menuCache = menu.html() + menu.next().html()
|
if (notInHeader === 0) {
|
||||||
|
moreApps.style.display = 'none'
|
||||||
|
navigation.style.display = 'none'
|
||||||
|
} else {
|
||||||
|
moreApps.style.display = 'flex'
|
||||||
|
}
|
||||||
|
|
||||||
|
menuCache = menu.innerHTML + menu.nextSibling.innerHTML
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(updateTopMenu, 50)
|
for (let timeout of [300, 500, 700, 900, 1100]) {
|
||||||
|
setTimeout(updateTopMenu, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
let resizeTimeout = null;
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
if (resizeTimeout !== null) {
|
||||||
|
clearTimeout(resizeTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
resizeTimeout = setTimeout(updateTopMenu, 100)
|
||||||
|
})
|
||||||
|
|
|
@ -13,63 +13,98 @@ if ($_['always-displayed']) {
|
||||||
?>
|
?>
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var sideMenuContainer = jQuery('<div id="side-menu-container">')
|
const querySelector = function(selector, element) {
|
||||||
var sideMenuOpener = jQuery('<button class="side-menu-opener"></button>')
|
if (element) {
|
||||||
var sideMenu = jQuery('<div id="side-menu">')
|
return element.querySelector(selector)
|
||||||
var body = jQuery('body')
|
}
|
||||||
var html = jQuery('html')
|
|
||||||
var isTouchDevice = window.matchMedia("(pointer: coarse)").matches
|
return document.querySelector(selector)
|
||||||
|
}
|
||||||
|
|
||||||
|
const querySelectorAll = function(selector, element) {
|
||||||
|
if (element) {
|
||||||
|
return element.querySelectorAll(selector)
|
||||||
|
}
|
||||||
|
|
||||||
|
return document.querySelectorAll(selector)
|
||||||
|
}
|
||||||
|
|
||||||
|
const createElement = function(tagName, attributes) {
|
||||||
|
const element = document.createElement(tagName)
|
||||||
|
|
||||||
|
if (typeof attributes === 'object') {
|
||||||
|
for (let i in attributes) {
|
||||||
|
element.setAttribute(i, attributes[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
const sideMenuContainer = createElement('div', {id: 'side-menu-container'})
|
||||||
|
const sideMenuOpener = createElement('button', {'class': 'side-menu-opener'})
|
||||||
|
const sideMenu = createElement('div', {id: 'side-menu'})
|
||||||
|
|
||||||
|
const body = querySelector('body')
|
||||||
|
const html = querySelector('html')
|
||||||
|
const nextcloud = querySelector('#nextcloud')
|
||||||
|
|
||||||
|
const isTouchDevice = window.matchMedia("(pointer: coarse)").matches
|
||||||
|
const targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>
|
||||||
|
|
||||||
<?php if ($display === 'big-menu'): ?>
|
<?php if ($display === 'big-menu'): ?>
|
||||||
sideMenu.attr('data-bigmenu', '1')
|
sideMenu.setAttribute('data-bigmenu', '1')
|
||||||
<?php elseif ($display === 'side-with-categories'): ?>
|
<?php elseif ($display === 'side-with-categories'): ?>
|
||||||
sideMenu.attr('data-sidewithcategories', '1')
|
sideMenu.setAttribute('data-sidewithcategories', '1')
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
var targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>;
|
querySelector('body').addEventListener('side-menu.apps', (e) => {
|
||||||
|
const apps = e.detail.apps;
|
||||||
|
|
||||||
body.on('side-menu.apps', function(e, apps) {
|
|
||||||
<?php if ($_['hide-when-no-apps']): ?>
|
<?php if ($_['hide-when-no-apps']): ?>
|
||||||
sideMenu = jQuery('#side-menu')
|
const sideMenu = querySelector('#side-menu')
|
||||||
|
|
||||||
if (apps.length === 0) {
|
if (apps.length === 0) {
|
||||||
sideMenu.removeClass('open')
|
sideMenu.classList.remove('open')
|
||||||
sideMenu.addClass('hide')
|
sideMenu.classList.add('hide')
|
||||||
sideMenuOpener.addClass('hide')
|
sideMenuOpener.classList.add('hide')
|
||||||
} else {
|
} else {
|
||||||
sideMenu.removeClass('hide')
|
sideMenu.classList.remove('hide')
|
||||||
sideMenuOpener.removeClass('hide')
|
sideMenuOpener.classList.remove('hide')
|
||||||
}
|
}
|
||||||
|
|
||||||
<?php if ($display === 'always-displayed'): ?>
|
<?php if ($display === 'always-displayed'): ?>
|
||||||
if (apps.length === 0) {
|
if (apps.length === 0) {
|
||||||
html.removeClass('side-menu-always-displayed');
|
html.classList.remove('side-menu-always-displayed')
|
||||||
} else {
|
} else {
|
||||||
html.addClass('side-menu-always-displayed');
|
html.classList.add('side-menu-always-displayed')
|
||||||
}
|
}
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<?php if ($display === 'always-displayed'): ?>
|
<?php if ($display === 'always-displayed'): ?>
|
||||||
if (apps.length === 0) {
|
if (apps.length === 0) {
|
||||||
html.removeClass('side-menu-always-displayed');
|
html.classList.remove('side-menu-always-displayed')
|
||||||
} else {
|
} else {
|
||||||
html.addClass('side-menu-always-displayed');
|
html.classList.add('side-menu-always-displayed')
|
||||||
}
|
}
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
})
|
})
|
||||||
|
|
||||||
body.on('side-menu.ready', function() {
|
body.addEventListener('side-menu.ready', () => {
|
||||||
sideMenu = jQuery('#side-menu')
|
const sideMenu = querySelector('#side-menu')
|
||||||
|
const headerMenuOpener = querySelector('#header .side-menu-opener')
|
||||||
|
const sideMenuOpener = querySelectorAll('#side-menu .side-menu-opener')
|
||||||
|
|
||||||
var headerMenuOpener = jQuery('#header .side-menu-opener')
|
sideMenuFocus = () => {
|
||||||
var sideMenuOpener = jQuery('#side-menu .side-menu-opener')
|
let a = querySelector('.side-menu-app.active a', sideMenu)
|
||||||
|
|
||||||
sideMenuFocus = function() {
|
if (!a) {
|
||||||
var a = sideMenu.find('.side-menu-app.active a')
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (a.length === 0) {
|
if (a.length === 0) {
|
||||||
a = sideMenu.find('.side-menu-app:first-child a')
|
a = querySelector('.side-menu-app:first-child a', sideMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.length > 0) {
|
if (a.length > 0) {
|
||||||
|
@ -77,79 +112,82 @@ if ($_['always-displayed']) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<?php if ($_['opener-hover'] || $display === 'always-displayed'): ?>
|
<?php if ($_['opener-hover']): ?>
|
||||||
var sideMenuMouseLeave = function() {
|
const sideMenuMouseLeave = () => {
|
||||||
sideMenu
|
sideMenu.classList.remove('open')
|
||||||
.removeClass('open')
|
sideMenu.removeEventListener('mouseleave', sideMenuMouseLeave)
|
||||||
.off('mouseleave', sideMenuMouseLeave)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var sideMenuMouseEnter = function() {
|
const sideMenuMouseEnter = () => {
|
||||||
sideMenu.on('mouseleave', sideMenuMouseLeave)
|
sideMenu.addEventListener('mouseleave', sideMenuMouseLeave)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sideMenuOpenerMouseEnter = function() {
|
const sideMenuOpenerMouseEnter = () => {
|
||||||
sideMenu
|
sideMenu.classList.add('open')
|
||||||
.addClass('open')
|
sideMenu.addEventListener('mouseenter', sideMenuMouseEnter)
|
||||||
.on('mouseenter', sideMenuMouseEnter)
|
|
||||||
|
|
||||||
sideMenuFocus()
|
sideMenuFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isTouchDevice) {
|
if (!isTouchDevice) {
|
||||||
<?php if ($_['opener-hover']): ?>
|
<?php if ($_['opener-hover']): ?>
|
||||||
headerMenuOpener.on('mouseenter', sideMenuOpenerMouseEnter)
|
headerMenuOpener.addEventListener('mouseenter', sideMenuOpenerMouseEnter)
|
||||||
|
|
||||||
sideMenu.addClass('hide-opener')
|
sideMenu.classList.add('hide-opener')
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
sideMenu.on('mouseleave', sideMenuMouseLeave)
|
sideMenu.addEventListener('mouseleave', sideMenuMouseLeave)
|
||||||
sideMenu.on('mouseenter', sideMenuOpenerMouseEnter)
|
sideMenu.addEventListener('mouseenter', sideMenuOpenerMouseEnter)
|
||||||
}
|
}
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
headerMenuOpener.on('click', function() {
|
headerMenuOpener.addEventListener('click', () => {
|
||||||
sideMenu.addClass('open')
|
sideMenu.classList.add('open')
|
||||||
sideMenu.find('.side-menu-app.active a').focus()
|
|
||||||
|
const a = querySelector('.side-menu-app.active a', sideMenu)
|
||||||
|
|
||||||
|
if (a !== null) {
|
||||||
|
a.focus()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
<?php if ($display === 'always-displayed'): ?>
|
for (let opener of sideMenuOpener) {
|
||||||
sideMenuOpener.on('click', function() {
|
opener.addEventListener('click', () => {
|
||||||
sideMenu.toggleClass('open')
|
<?php if ($display === 'always-displayed'): ?>
|
||||||
|
sideMenu.classList.toggle('open')
|
||||||
|
<?php else: ?>
|
||||||
|
sideMenu.classList.remove('open')
|
||||||
|
<?php endif; ?>
|
||||||
})
|
})
|
||||||
<?php else: ?>
|
}
|
||||||
sideMenuOpener.on('click', function() {
|
|
||||||
sideMenu.removeClass('open')
|
|
||||||
})
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
jQuery(document).keydown(function(e) {
|
document.addEventListener('keydown', (e) => {
|
||||||
var key = e.key || e.keyCode
|
var key = e.key || e.keyCode
|
||||||
|
|
||||||
if ((key === 'o' || key === 79) && e.ctrlKey === true) {
|
if ((key === 'o' || key === 79) && e.ctrlKey === true) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
sideMenu.toggleClass('open')
|
sideMenu.classList.toggle('open')
|
||||||
sideMenuFocus()
|
sideMenuFocus()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
body.append(sideMenuContainer)
|
body.appendChild(sideMenuContainer)
|
||||||
sideMenuContainer.append(sideMenu)
|
sideMenuContainer.appendChild(sideMenu)
|
||||||
|
|
||||||
<?php if ($_['loader-enabled'] === true): ?>
|
<?php if ($_['loader-enabled'] === true): ?>
|
||||||
<?php require_once __DIR__.'/_loaderEnabled.js'; ?>
|
<?php require_once __DIR__.'/_loaderEnabled.js'; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($_['opener-position'] === 'before'): ?>
|
<?php if ($_['opener-position'] === 'before'): ?>
|
||||||
sideMenuOpener.insertBefore('#nextcloud')
|
nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud)
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
sideMenuOpener.insertAfter('#nextcloud')
|
nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud.nextSibling)
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (!empty($_['top-menu-apps'])): ?>
|
<?php if (!empty($_['top-menu-apps'])): ?>
|
||||||
var topMenuApps = <?php echo json_encode($_['top-menu-apps']); ?>;
|
const topMenuApps = <?php echo json_encode($_['top-menu-apps']); ?>
|
||||||
|
|
||||||
<?php require_once __DIR__.'/_topMenuApps.js'; ?>
|
<?php require_once __DIR__.'/_topMenuApps.js'; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
|
@ -20,6 +20,7 @@ use OCP\IURLGenerator;
|
||||||
use OCP\IConfig;
|
use OCP\IConfig;
|
||||||
use OCA\SideMenu\AppInfo\Application;
|
use OCA\SideMenu\AppInfo\Application;
|
||||||
|
|
||||||
|
vendor_script('side_menu', 'html5sortable.min');
|
||||||
script('side_menu', 'admin');
|
script('side_menu', 'admin');
|
||||||
style('side_menu', 'admin');
|
style('side_menu', 'admin');
|
||||||
|
|
||||||
|
@ -799,7 +800,7 @@ $choicesSizes = [
|
||||||
🖱️ <?php p($l->t('Show and hide the list of categories')); ?>
|
🖱️ <?php p($l->t('Show and hide the list of categories')); ?>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="side-menu-setting" data-name="categories" id="categories-list" style="display: none">
|
<div id="categories-list" style="display: none">
|
||||||
<ul class="side-menu-setting-list">
|
<ul class="side-menu-setting-list">
|
||||||
<?php foreach ($_['categories'] as $key => $label): ?>
|
<?php foreach ($_['categories'] as $key => $label): ?>
|
||||||
<li data-id="<?php echo $key; ?>" class="side-menu-setting-list-item">
|
<li data-id="<?php echo $key; ?>" class="side-menu-setting-list-item">
|
||||||
|
|
|
@ -44,8 +44,6 @@ $choicesYesNo = [
|
||||||
<?php p($l->t('Menu')); ?>
|
<?php p($l->t('Menu')); ?>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="side-menu-enabled">
|
<label for="side-menu-enabled">
|
||||||
<?php p($l->t('Enable the custom menu')); ?>
|
<?php p($l->t('Enable the custom menu')); ?>
|
||||||
|
|
2
vendor/html5sortable.min.js
vendored
Normal file
2
vendor/html5sortable.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue