Compare commits

..

11 Commits

Author SHA1 Message Date
Simon Vieille cc71fda3b0 Merge branch 'develop' 2021-10-21 21:43:51 +02:00
Simon Vieille fd367fe2d4 Merge branch 'develop' 2021-10-21 21:37:40 +02:00
Simon Vieille 3f590a97bc Merge branch 'develop' 2021-10-21 20:06:41 +02:00
Simon Vieille aac9f2cb16 Merge branch 'develop' 2021-08-11 11:58:25 +02:00
Simon Vieille f7d4a8284b Merge branch 'develop' 2021-08-02 21:49:02 +02:00
Simon Vieille 04d161ad9b Merge branch 'develop' 2021-07-09 12:55:07 +02:00
Simon Vieille dab5566be4 Merge branch 'develop' 2021-07-09 12:54:32 +02:00
Simon Vieille d735e1cfa6 Merge branch 'develop' 2021-07-09 12:43:01 +02:00
Simon Vieille 96a4235a10 Merge branch 'develop' 2021-07-09 11:52:28 +02:00
Simon Vieille 4413623618 merge develop 2021-07-07 21:36:02 +02:00
Simon Vieille 7306a31a7d release v1.24.0 2021-07-03 20:32:39 +02:00
50 changed files with 2247 additions and 1791 deletions
-54
View File
@@ -1,54 +0,0 @@
---
kind: pipeline
type: docker
name: default
steps:
- name: dependencies
image: deblan/devenv
commands:
- npm install
- name: build
image: deblan/devenv
commands:
- make npm-build
when:
branch:
exclude:
- master
include:
- develop
- feature/*
event:
- push
- pull_request
- name: release
image: deblan/devenv
volumes:
- name: artifacts
path: /artifacts
environment:
APP_CERTIFICATE:
from_secret: app_certificate
commands:
- mkdir -p "$HOME/.nextcloud/certificates"
- 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 RELEASE_DIRECTORY="/artifacts/deblan/side_menu"
- make release
when:
branch:
exclude:
- develop
- feature/*
include:
- master
event:
- push
volumes:
- name: artifacts
host:
path: /var/www/html/artifacts
-40
View File
@@ -1,40 +0,0 @@
pipeline:
dependencies:
image: deblan/devenv
commands:
- npm install
when:
event: [tag, push, pull_request]
build:
image: deblan/devenv
commands:
- make npm-build
when:
event: [push, pull_request]
package:
image: deblan/devenv
volumes:
- /var/www/html/artifacts:/var/www/html/artifacts
secrets: [app_certificate]
commands:
- mkdir -p "$HOME/.nextcloud/certificates"
- 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 RELEASE_DIRECTORY="/var/www/html/artifacts/deblan/side_menu"
- make release
when:
event: [tag]
release:
image: plugins/gitea-release
volumes:
- /var/www/html/artifacts:/var/www/html/artifacts
settings:
api_key:
from_secret: gitnet_api_key
base_url: https://gitnet.fr
files: /var/www/html/artifacts/deblan/side_menu/${CI_COMMIT_TAG/v//}/*
when:
event: [tag]
-81
View File
@@ -1,86 +1,5 @@
## [Unreleased] ## [Unreleased]
## 2.4.2
### Fixed
* fix typo
### Changed
* change ci/cd
## 2.4.1
### Fixed
* fix user setting save
## 2.4.0
### Added
* remove focus on opener after click
* add button to set default colors
* add menu hover effect
* add translations
### Fixed
* fix deprecated app.php file
* fix menu with categories header
* fix minor issues
### Changed
* change saving progression
### Removed
* Nextcloud 19 is not supported anymore
* PHP 7.3 is not supported anymore
## 2.3.5
### Fixed
* fix white square (#99)
## 2.3.4
### Fixed
* fix blank line when settings are open (#96)
## 2.3.3
### Added
* hide the scrollbar when mouse is out (menu always displayed)
### Fixed
* fix SQL Exception InvalidFieldNameException (#93)
## 2.3.2
### Fixed
- fix hidden menu
## 2.3.1
### Fixed
- fix #88: does not work with default menu
## 2.3.0
### Added
- fix #82: add an option to keep visible an app in both menus
- fix #83: add custom categories
- add auto-reload when settings are saved
## 2.2.0
### Added
- fix #84: update icons
- fix #85: use Nextcloud colors by default
### Fixed
- fix categories order in large menu
## 2.1.0
### Added
- add compatibility with Nextcloud 23
## 2.0.1
### Fixed
- fix #78: Top menu is broken - invisible apps are shown
- fix #77: Update personal settings - HTTP error 412 (Precondition Failed)
- fix js error on the personal settings page (undefined sortable)
## 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
+1025 -3
View File
File diff suppressed because one or more lines are too long
+4 -8
View File
@@ -11,14 +11,10 @@ release: npm-build translations
exit 1 exit 1
fi fi
if [ -z "$$RELEASE_DIRECTORY" ]; then test -d releases/$$VERSION && rm -fr releases/$$VERSION
RELEASE_DIRECTORY=releases mkdir -p releases/$$VERSION/side_menu
fi cp -r README.md CHANGELOG.md appinfo css lib img l10n js src templates screenshots releases/$$VERSION/side_menu
cd releases/$$VERSION
test -d $$RELEASE_DIRECTORY/$$VERSION && rm -fr $$RELEASE_DIRECTORY/$$VERSION
mkdir -p $$RELEASE_DIRECTORY/$$VERSION/side_menu
cp -r README.md CHANGELOG.md appinfo css lib img l10n js src templates screenshots vendor $$RELEASE_DIRECTORY/$$VERSION/side_menu
cd $$RELEASE_DIRECTORY/$$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
rm -fr side_menu rm -fr side_menu
+2 -10
View File
@@ -2,7 +2,7 @@
=============================== ===============================
Allows you to modify the position of the main menu by creating a panel on the left of the interface or with a big menu on the top. Allows you to modify the position of the main menu by creating a panel on the left of the interface or with a big menu on the top.
You can also add and sort custom categories, define apps that must be displayed in the top menu, etc. Fully customisable. You can also define apps that must be displayed in the top menu. Fully customisable.
This application is rather suitable for instances that activate a lot of applications. This application is rather suitable for instances that activate a lot of applications.
@@ -10,17 +10,14 @@ You can customize colors depending of the theme (Dark theme and Breeze Dark). Co
* [Installation and upgrade](#installation-and-upgrade) * [Installation and upgrade](#installation-and-upgrade)
* [How to contribute?](#how-to-contribute) * [How to contribute?](#how-to-contribute)
* [Support](#support)
* [Screenshots](https://gitnet.fr/deblan/side_menu/src/branch/master/screenshots/) * [Screenshots](https://gitnet.fr/deblan/side_menu/src/branch/master/screenshots/)
You like this app and you want to support me? ☕ [Buy me a coffee](https://www.buymeacoffee.com/deblan) or [Donate with liberapay](https://liberapay.com/deblan) You like this app and you want to support me? ☕ [Buy me a coffee](https://www.buymeacoffee.com/deblan) or [Donate with liberapay](https://liberapay.com/deblan)
[![Build Status](https://ci.gitnet.fr/api/badges/deblan/side_menu/status.svg)](https://ci.gitnet.fr/deblan/side_menu)
Requirements Requirements
------------ ------------
* PHP >= 7.4 * PHP >= 7.3
* App `theming` enabled * App `theming` enabled
Installation and upgrade Installation and upgrade
@@ -61,8 +58,3 @@ If you are a developer:
Build javascripts using `make npm-build` (or `make npm-watch` to build them in real time). Build javascripts using `make npm-build` (or `make npm-watch` to build them in real time).
Then commit and create a pull request. Then commit and create a pull request.
Support
-------
You can join the official room on Matrix: [#custommenu:neutralnetwork.org](https://matrix.to/#/#custommenu:neutralnetwork.org).
+10
View File
@@ -0,0 +1,10 @@
<?php
use OCA\SideMenu\AppInfo\Application;
$app = new Application();
if ($app->isEnabled()) {
$app->registerAssets();
$app->registerServices();
}
+4 -4
View File
@@ -17,7 +17,7 @@ You can report a bug or request a feature by opening an issue.
Requirements: Requirements:
* PHP >= 7.4 * PHP >= 7.3
* App `theming` enabled * App `theming` enabled
If you like this application and if you want to support the development: If you like this application and if you want to support the development:
@@ -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>2.4.2</version> <version>1.28.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,8 +46,8 @@ 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="20" max-version="24"/> <nextcloud min-version="18" max-version="22"/>
<php min-version="7.4"/> <php min-version="7.3"/>
</dependencies> </dependencies>
<settings> <settings>
<admin>OCA\SideMenu\Settings\Admin</admin> <admin>OCA\SideMenu\Settings\Admin</admin>
+2 -27
View File
@@ -20,7 +20,7 @@
margin: 10px 0 10px 0; margin: 10px 0 10px 0;
} }
#-dropside-menu-section input[type="checkbox"] { #side-menu-section input[type="checkbox"] {
vertical-align: middle; vertical-align: middle;
} }
@@ -81,12 +81,6 @@
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;
@@ -97,10 +91,6 @@
margin-top: -1px; margin-top: -1px;
} }
#apps-categories-custom-list select {
width: 100%;
}
.side-menu-setting-table { .side-menu-setting-table {
display: table; display: table;
@@ -119,7 +109,7 @@
.side-menu-setting-form { .side-menu-setting-form {
display: table-cell; display: table-cell;
min-width: 300px; width: 300px;
} }
.side-menu-setting-label-short { .side-menu-setting-label-short {
@@ -129,18 +119,3 @@
.side-menu-setting-form-long { .side-menu-setting-form-long {
width: 400px; width: 400px;
} }
#side-menu-save-progress {
display: inline-block;
width: 0;
height: 15px;
background: #fff;
}
.btn-reset {
display: inline-block;
cursor: pointer;
position: absolute;
margin-top: 17px;
margin-left: 5px;
}
+6 -33
View File
@@ -29,16 +29,12 @@
display: none; display: none;
} }
#side-menu a {
transition: 0.2s;
}
#side-menu.open { #side-menu.open {
display: block; display: block;
} }
#header .side-menu-opener { #header .side-menu-opener {
margin-left: 0px; margin-left: 5px;
} }
.side-menu-settings { .side-menu-settings {
@@ -63,8 +59,6 @@
.side-menu-settings img { .side-menu-settings img {
vertical-align: bottom; vertical-align: bottom;
margin-left: 3px; margin-left: 3px;
width: 32px;
height: 32px;
} }
#side-menu.open .side-menu-settings { #side-menu.open .side-menu-settings {
@@ -73,19 +67,10 @@
.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'));
background-color: transparent !important; height: 40px;
height: 40px !important; width: 40px;
width: 40px !important; border-radius: 0;
border-radius: 0 !important; border: 0;
border: 0 !important;
padding-right: 12px !important;
padding-left: 12px !important;
margin-left: 5px !important;
margin-left: 3px !important;
}
.side-menu-opener:active, .side-menu-opener:focus {
background-color: var(--side-menu-current-app-background-color, #444) !important;
} }
.side-menu-closer { .side-menu-closer {
@@ -154,13 +139,10 @@
max-width: 250px; max-width: 250px;
position: fixed; position: fixed;
padding-top: 2px; padding-top: 2px;
padding-left: 5px;
top: 0; top: 0;
} }
#side-menu.side-menu-with-categories .side-menu-header {
max-width: 295px;
}
#side-menu.hide-opener .side-menu-logo { #side-menu.hide-opener .side-menu-logo {
margin-top: 20px; margin-top: 20px;
} }
@@ -257,11 +239,6 @@
.side-menu-always-displayed .side-menu-apps-list { .side-menu-always-displayed .side-menu-apps-list {
height: calc(100vh - 49px); height: calc(100vh - 49px);
top: 49px; top: 49px;
overflow: hidden;
}
.side-menu-always-displayed .side-menu-apps-list:hover {
overflow: auto;
} }
.side-menu-always-displayed #side-menu, .side-menu-always-displayed #side-menu,
@@ -308,10 +285,6 @@
padding: 10px 0; padding: 10px 0;
} }
.side-menu-always-displayed #body-settings, #body-settings.body-settings-side-menu {
overflow-x: visible;
}
@media screen and (max-width: 1024px) { @media screen and (max-width: 1024px) {
#side-menu.side-menu-big { #side-menu.side-menu-big {
max-width: 290px; max-width: 290px;
@@ -1,224 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="571.907"
height="156.921"
viewBox="0 0 151.317 41.519"
version="1.1"
id="svg901"
sodipodi:docname="layout-side-menu-with-categories.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata907">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs905" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1036"
id="namedview903"
showgrid="false"
inkscape:zoom="1.6086532"
inkscape:cx="455.61054"
inkscape:cy="16.694081"
inkscape:window-x="0"
inkscape:window-y="21"
inkscape:window-maximized="0"
inkscape:current-layer="svg901"
showguides="false" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#fff"
stroke="#b3b3b3"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M.18.18h58.532v41.16H.18zM62.735.18h58.532v41.16H62.735z"
id="path853" />
<g
fill="#b3b3b3"
stroke="#ccc"
fill-rule="evenodd"
stroke-width="1.465"
stroke-linecap="round"
id="g857">
<path
d="M84.066 21.35l5.055-5.056M82.925 29.835l18.152-18.151M95.893 25.225l3.585-3.586"
id="path855" />
</g>
<path
style="marker:none"
color="#000"
overflow="visible"
fill="none"
stroke="#b3b3b3"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M62.735.18h58.532v41.16H62.735z"
id="path861" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#f9f9f9"
stroke="#ccc"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M.18.18h58.532v5.063H.18z"
id="path877" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="none"
stroke="#b3b3b3"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M.18.18h58.532v41.16H.18z"
id="path879" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#666"
stroke="#ccc"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M1.357 1.034h3.496V4.39H1.357z"
id="path881" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#e6e6e6"
stroke="#ccc"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M6.068 1.034h6.102V4.39H6.068z"
id="path883" />
<g
fill="#b3b3b3"
stroke="#ccc"
fill-rule="evenodd"
stroke-width="1.465"
stroke-linecap="round"
id="g887">
<path
d="M21.51 21.35l5.056-5.056M20.37 29.835L38.52 11.684M33.337 25.225l3.586-3.586"
id="path885" />
</g>
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#fff"
stroke="#b3b3b3"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M125.857.18h25.28v41.16h-25.28z"
id="path889" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#f9f9f9"
stroke="#ccc"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M125.857.18h25.257v5.063h-25.257z"
id="path891" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="none"
stroke="#b3b3b3"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M125.857.18h25.257v41.16h-25.257z"
id="path893" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#4d4d4d"
stroke="#b3b3b3"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M125.857.18h20.829v41.16h-20.83z"
id="path895" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#666"
stroke="#ccc"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M127.034 1.034h3.496V4.39h-3.496z"
id="path897" />
<path
style="marker:none"
color="#000"
overflow="visible"
fill="#e6e6e6"
stroke="#ccc"
stroke-width=".359"
stroke-linecap="square"
paint-order="fill markers stroke"
d="M127.569 10.155h1.893v1.81h-1.893zM130.498 10.486h12.463v1.148h-12.463zM127.569 13.696h1.893v1.81h-1.893zM130.498 14.027h10.592v1.148h-10.592zM127.569 17.104h1.893v1.81h-1.893zM130.498 17.435h12.997v1.148h-12.997zM127.569 24.708h1.893v1.81h-1.893zM130.498 25.04h7.585v1.147h-7.585zM127.569 28.116h1.893v1.81h-1.893zM130.498 28.447h11.46v1.148h-11.46zM127.569 31.657h1.893v1.81h-1.893zM130.498 31.988h9.322v1.148h-9.322zM127.569 35.065h1.893v1.81h-1.893zM130.498 35.396h11.126v1.148h-11.126zM127.616 6.848h11.518v1.148h-11.518zM127.569 21.311h9.344v1.148h-9.344z"
id="path899" />
<path
inkscape:connector-curvature="0"
style="color:#000000;overflow:visible;fill:#4d4d4d;stroke:#b3b3b3;stroke-width:0.359;stroke-linecap:square;marker:none;paint-order:fill markers stroke"
overflow="visible"
d="m 62.728587,0.17999881 h 20.829 V 41.34 h -20.83 z"
id="path895-5" />
<path
inkscape:connector-curvature="0"
style="color:#000000;overflow:visible;fill:#666666;stroke:#cccccc;stroke-width:0.359;stroke-linecap:square;marker:none;paint-order:fill markers stroke"
overflow="visible"
d="m 63.905587,1.0339988 h 3.496 V 4.389999 h -3.496 z"
id="path897-3" />
<path
inkscape:connector-curvature="0"
style="color:#000000;overflow:visible;fill:#e6e6e6;stroke:#cccccc;stroke-width:0.359;stroke-linecap:square;marker:none;paint-order:fill markers stroke"
overflow="visible"
d="m 64.440587,10.154999 h 1.893 v 1.81 h -1.893 z m 2.929,0.331 h 12.463 v 1.148 h -12.463 z m -2.929,3.21 h 1.893 v 1.81 h -1.893 z m 2.929,0.331 h 10.592 v 1.148 h -10.592 z m -2.929,3.077 h 1.893 v 1.81 h -1.893 z m 2.929,0.331 h 12.997 v 1.148 h -12.997 z m -2.929,7.273 h 1.893 V 26.518 h -1.893 z m 2.929,0.332 h 7.585 v 1.147 h -7.585 z m -2.929,3.076001 h 1.893 v 1.81 h -1.893 z m 2.929,0.330999 h 11.46 v 1.147999 h -11.46 z m -2.929,3.21 h 1.893 v 1.809999 h -1.893 z m 2.929,0.330999 h 9.322 v 1.148001 h -9.322 z m -2.929,3.077001 h 1.893 v 1.809999 h -1.893 z m 2.929,0.331001 h 11.126 v 1.147999 h -11.126 z m -2.882,-28.5480012 h 11.518 v 1.1480001 h -11.518 z m -0.047,14.4630002 h 9.344 v 1.148 h -9.344 z"
id="path899-5" />
</svg>

Before

Width:  |  Height:  |  Size: 7.3 KiB

+6 -1
View File
@@ -1 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"><g fill="#fff" color="#000" transform="translate(-.067 .224)"><rect width="5.027" height=".777" x="-2.307" y="6.984" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none" transform="rotate(-45)"/><rect width="5.027" height=".777" x="4.859" y="-.595" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none" transform="rotate(45)"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583">
<g color="#000" fill="#fff">
<rect transform="rotate(135)" ry=".545" rx=".545" y="-8.209" x="-3.608" height="1.451" width="7.216" style="marker:none" overflow="visible" paint-order="stroke markers fill"/>
<rect transform="rotate(-135)" ry=".545" rx=".545" y="-.726" x="-11.091" height="1.451" width="7.216" style="marker:none" overflow="visible" paint-order="stroke markers fill"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 495 B

After

Width:  |  Height:  |  Size: 498 B

+173 -1
View File
@@ -1 +1,173 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"><g fill-opacity=".898" color="#000" transform="matrix(.90559 0 0 .86896 .772 -247.893)"><rect width="1.451" height="1.451" x="4.266" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><g transform="translate(-.13)"><rect width="1.451" height="1.451" x="6.445" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="1.451" height="1.451" x="2.345" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g><rect width="1.451" height="1.451" x="4.266" y="290.631" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><g transform="translate(-.13 2.157)"><rect width="1.451" height="1.451" x="6.445" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="1.451" height="1.451" x="2.345" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g><rect width="1.451" height="1.451" x="4.266" y="292.808" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><g transform="translate(-.13 4.334)"><rect width="1.451" height="1.451" x="6.445" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="1.451" height="1.451" x="2.345" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g></g></svg> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="40"
height="40"
viewBox="0 0 10.583 10.583"
version="1.1"
id="svg935"
sodipodi:docname="side-menu-opener-dark.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata941">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs939" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1008"
id="namedview937"
showgrid="false"
inkscape:zoom="8.34386"
inkscape:cx="83.025045"
inkscape:cy="14.304895"
inkscape:window-x="0"
inkscape:window-y="41"
inkscape:window-maximized="0"
inkscape:current-layer="svg935" />
<g
transform="translate(.3 -286.074)"
fill="#fff"
color="#000"
fill-opacity=".855"
id="g933"
style="fill:#000000;fill-opacity:0.89855075">
<rect
ry="0"
rx="0"
y="288.474"
x="4.266"
height="1.451"
width="1.451"
style="marker:none;fill:#000000;fill-opacity:0.89855075"
overflow="visible"
paint-order="stroke markers fill"
id="rect909" />
<g
transform="translate(-.13)"
id="g915"
style="fill:#000000;fill-opacity:0.89855075">
<rect
style="marker:none;fill:#000000;fill-opacity:0.89855075"
width="1.451"
height="1.451"
x="6.445"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect911" />
<rect
style="marker:none;fill:#000000;fill-opacity:0.89855075"
width="1.451"
height="1.451"
x="2.345"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect913" />
</g>
<rect
ry="0"
rx="0"
y="290.631"
x="4.266"
height="1.451"
width="1.451"
style="marker:none;fill:#000000;fill-opacity:0.89855075"
overflow="visible"
paint-order="stroke markers fill"
id="rect917" />
<g
transform="translate(-.13 2.157)"
id="g923"
style="fill:#000000;fill-opacity:0.89855075">
<rect
style="marker:none;fill:#000000;fill-opacity:0.89855075"
width="1.451"
height="1.451"
x="6.445"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect919" />
<rect
style="marker:none;fill:#000000;fill-opacity:0.89855075"
width="1.451"
height="1.451"
x="2.345"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect921" />
</g>
<rect
ry="0"
rx="0"
y="292.808"
x="4.266"
height="1.451"
width="1.451"
style="marker:none;fill:#000000;fill-opacity:0.89855075"
overflow="visible"
paint-order="stroke markers fill"
id="rect925" />
<g
transform="translate(-.13 4.334)"
id="g931"
style="fill:#000000;fill-opacity:0.89855075">
<rect
style="marker:none;fill:#000000;fill-opacity:0.89855075"
width="1.451"
height="1.451"
x="6.445"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect927" />
<rect
style="marker:none;fill:#000000;fill-opacity:0.89855075"
width="1.451"
height="1.451"
x="2.345"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect929" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

+102 -1
View File
@@ -1 +1,102 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"><rect width="7.62" height="7.62" x="1.482" y="1.482" fill="none" stroke="#000" stroke-linecap="square" stroke-width=".777" color="#000" overflow="visible" paint-order="markers fill stroke" rx="0" ry="0" style="marker:none"/><rect width="5.027" height=".777" x="2.778" y="3.148" color="#000" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="5.027" height=".777" x="2.778" y="6.658" color="#000" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="5.027" height=".777" x="2.778" y="4.936" color="#000" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></svg> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="40"
height="40"
viewBox="0 0 10.583 10.583"
version="1.1"
id="svg1090"
sodipodi:docname="side-menu-opener-hamburger-2-dark.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata1096">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs1094" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1008"
id="namedview1092"
showgrid="false"
inkscape:zoom="8.34386"
inkscape:cx="84.523455"
inkscape:cy="12.270318"
inkscape:window-x="0"
inkscape:window-y="41"
inkscape:window-maximized="0"
inkscape:current-layer="svg1090" />
<rect
overflow="visible"
style="marker:none;fill:#000000;fill-opacity:1"
width="4.806"
height="1.256"
x="2.888"
y="2.787"
rx="0"
ry=".472"
color="#000"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="rect1082" />
<rect
overflow="visible"
style="marker:none;fill:#000000;fill-opacity:1"
width="4.806"
height="1.256"
x="2.888"
y="4.655"
rx="0"
ry=".472"
color="#000"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="rect1084" />
<rect
overflow="visible"
style="marker:none;fill:#000000;fill-opacity:1"
width="4.806"
height="1.256"
x="2.888"
y="6.54"
rx="0"
ry=".472"
color="#000"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="rect1086" />
<path
style="marker:none;fill:#000000;fill-opacity:1"
d="M1.243.71A.469.469 0 0 0 .881.88a.469.469 0 0 0-.171.362V9.34c0 .146.067.275.171.362a.469.469 0 0 0 .362.171H9.34a.469.469 0 0 0 .362-.171.469.469 0 0 0 .171-.362V1.243a.469.469 0 0 0-.171-.362A.469.469 0 0 0 9.34.71zm.723 1.256h6.65v6.65h-6.65z"
color="#000"
overflow="visible"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="path1088" />
</svg>

Before

Width:  |  Height:  |  Size: 786 B

After

Width:  |  Height:  |  Size: 2.8 KiB

+101 -1
View File
@@ -1 +1,101 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"><rect width="7.62" height="7.62" x="1.482" y="1.482" fill="none" stroke="#fff" stroke-linecap="square" stroke-width=".777" color="#000" overflow="visible" paint-order="markers fill stroke" rx="0" ry="0" style="marker:none"/><g fill="#fff" color="#000" transform="translate(0 .034)"><rect width="5.027" height=".777" x="2.778" y="3.114" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="5.027" height=".777" x="2.778" y="6.624" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="5.027" height=".777" x="2.778" y="4.903" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g></svg> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="40"
height="40"
viewBox="0 0 10.583 10.583"
version="1.1"
id="svg1443"
sodipodi:docname="side-menu-opener-hamburger-2.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata1449">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs1447" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1008"
id="namedview1445"
showgrid="false"
inkscape:zoom="5.9"
inkscape:cx="90.508475"
inkscape:cy="4.5762712"
inkscape:window-x="0"
inkscape:window-y="41"
inkscape:window-maximized="0"
inkscape:current-layer="svg1443" />
<rect
overflow="visible"
style="marker:none;fill:#ffffff;fill-opacity:1"
width="4.806"
height="1.256"
x="2.888"
y="2.787"
rx="0"
ry=".472"
color="#000"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="rect1435" />
<rect
overflow="visible"
style="marker:none;fill:#ffffff;fill-opacity:1"
width="4.806"
height="1.256"
x="2.888"
y="4.655"
rx="0"
ry=".472"
color="#000"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="rect1437" />
<rect
overflow="visible"
style="marker:none;fill:#ffffff;fill-opacity:1"
width="4.806"
height="1.256"
x="2.888"
y="6.54"
rx="0"
ry=".472"
color="#000"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="rect1439" />
<path
style="marker:none;fill:#ffffff;fill-opacity:1"
d="M1.243.71A.469.469 0 0 0 .881.88a.469.469 0 0 0-.171.362V9.34c0 .146.067.275.171.362a.469.469 0 0 0 .362.171H9.34a.469.469 0 0 0 .362-.171.469.469 0 0 0 .171-.362V1.243a.469.469 0 0 0-.171-.362A.469.469 0 0 0 9.34.71zm.723 1.256h6.65v6.65h-6.65z"
color="#000"
overflow="visible"
fill="#fff"
fill-opacity=".855"
paint-order="stroke markers fill"
id="path1441" />
</svg>

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 2.8 KiB

+92 -1
View File
@@ -1 +1,92 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"><g color="#000" transform="matrix(.85624 0 0 .9944 .747 .03)"><g transform="matrix(1.0055 0 0 1 -.013 0)"><rect width="5.839" height=".782" x="2.372" y="2.764" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="5.839" height=".782" x="2.372" y="7.037" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g><rect width="5.871" height=".782" x="2.372" y="4.901" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g></svg> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="40"
height="40"
viewBox="0 0 10.583 10.583"
version="1.1"
id="svg1168"
sodipodi:docname="side-menu-opener-hamburger-dark.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata1174">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs1172" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1008"
id="namedview1170"
showgrid="false"
inkscape:zoom="5.9"
inkscape:cx="112.71186"
inkscape:cy="0.16949153"
inkscape:window-x="0"
inkscape:window-y="41"
inkscape:window-maximized="0"
inkscape:current-layer="svg1168" />
<g
color="#000"
fill="#fff"
fill-opacity=".855"
transform="translate(0 -286.417)"
id="g1166"
style="fill:#000000;fill-opacity:0.99637681">
<rect
ry=".545"
rx="0"
y="288.816"
x="2.516"
height="1.451"
width="5.551"
style="marker:none;fill:#000000;fill-opacity:0.99637681"
overflow="visible"
paint-order="stroke markers fill"
id="rect1160" />
<rect
ry=".545"
rx="0"
y="290.973"
x="2.516"
height="1.451"
width="5.551"
style="marker:none;fill:#000000;fill-opacity:0.99637681"
overflow="visible"
paint-order="stroke markers fill"
id="rect1162" />
<rect
ry=".545"
rx="0"
y="293.15"
x="2.516"
height="1.451"
width="5.551"
style="marker:none;fill:#000000;fill-opacity:0.99637681"
overflow="visible"
paint-order="stroke markers fill"
id="rect1164" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 2.5 KiB

+91 -1
View File
@@ -1 +1,91 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"><g fill="#fff" color="#000" transform="matrix(.85624 0 0 .9944 .747 .03)"><g transform="matrix(1.0055 0 0 1 -.013 0)"><rect width="5.839" height=".782" x="2.372" y="2.764" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="5.839" height=".782" x="2.372" y="7.037" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g><rect width="5.871" height=".782" x="2.372" y="4.901" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g></svg> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="40"
height="40"
viewBox="0 0 10.583 10.583"
version="1.1"
id="svg1382"
sodipodi:docname="side-menu-opener-hamburger.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata1388">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs1386" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1008"
id="namedview1384"
showgrid="false"
inkscape:zoom="5.9"
inkscape:cx="108.13559"
inkscape:cy="3.8983051"
inkscape:window-x="0"
inkscape:window-y="41"
inkscape:window-maximized="0"
inkscape:current-layer="svg1382" />
<g
color="#000"
fill="#fff"
fill-opacity=".855"
transform="translate(0 -286.417)"
id="g1380"
style="fill:#ffffff;fill-opacity:1">
<rect
ry=".545"
rx="0"
y="288.816"
x="2.516"
height="1.451"
width="5.551"
style="marker:none;fill:#ffffff;fill-opacity:1"
overflow="visible"
paint-order="stroke markers fill"
id="rect1374" />
<rect
ry=".545"
rx="0"
y="290.973"
x="2.516"
height="1.451"
width="5.551"
style="marker:none;fill:#ffffff;fill-opacity:1"
overflow="visible"
paint-order="stroke markers fill"
id="rect1376" />
<rect
ry=".545"
rx="0"
y="293.15"
x="2.516"
height="1.451"
width="5.551"
style="marker:none;fill:#ffffff;fill-opacity:1"
overflow="visible"
paint-order="stroke markers fill"
id="rect1378" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 2.4 KiB

+172 -1
View File
@@ -1 +1,172 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"><g fill="#fff" fill-opacity=".946" color="#000" transform="matrix(.90559 0 0 .86896 .772 -247.893)"><rect width="1.451" height="1.451" x="4.266" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><g transform="translate(-.13)"><rect width="1.451" height="1.451" x="6.445" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="1.451" height="1.451" x="2.345" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g><rect width="1.451" height="1.451" x="4.266" y="290.631" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><g transform="translate(-.13 2.157)"><rect width="1.451" height="1.451" x="6.445" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="1.451" height="1.451" x="2.345" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g><rect width="1.451" height="1.451" x="4.266" y="292.808" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><g transform="translate(-.13 4.334)"><rect width="1.451" height="1.451" x="6.445" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/><rect width="1.451" height="1.451" x="2.345" y="288.474" overflow="visible" paint-order="stroke markers fill" rx="0" ry="0" style="marker:none"/></g></g></svg> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="40"
height="40"
viewBox="0 0 10.583 10.583"
version="1.1"
id="svg1321"
sodipodi:docname="side-menu-opener.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata1327">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs1325" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1008"
id="namedview1323"
showgrid="false"
inkscape:zoom="5.9"
inkscape:cx="78.983051"
inkscape:cy="5.5932203"
inkscape:window-x="0"
inkscape:window-y="41"
inkscape:window-maximized="0"
inkscape:current-layer="svg1321" />
<g
transform="translate(.3 -286.074)"
fill="#fff"
color="#000"
fill-opacity=".855"
id="g1319"
style="fill:#ffffff;fill-opacity:0.94565219">
<rect
ry="0"
rx="0"
y="288.474"
x="4.266"
height="1.451"
width="1.451"
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
overflow="visible"
paint-order="stroke markers fill"
id="rect1295" />
<g
transform="translate(-.13)"
id="g1301"
style="fill:#ffffff;fill-opacity:0.94565219">
<rect
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
width="1.451"
height="1.451"
x="6.445"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect1297" />
<rect
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
width="1.451"
height="1.451"
x="2.345"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect1299" />
</g>
<rect
ry="0"
rx="0"
y="290.631"
x="4.266"
height="1.451"
width="1.451"
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
overflow="visible"
paint-order="stroke markers fill"
id="rect1303" />
<g
transform="translate(-.13 2.157)"
id="g1309"
style="fill:#ffffff;fill-opacity:0.94565219">
<rect
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
width="1.451"
height="1.451"
x="6.445"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect1305" />
<rect
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
width="1.451"
height="1.451"
x="2.345"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect1307" />
</g>
<rect
ry="0"
rx="0"
y="292.808"
x="4.266"
height="1.451"
width="1.451"
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
overflow="visible"
paint-order="stroke markers fill"
id="rect1311" />
<g
transform="translate(-.13 4.334)"
id="g1317"
style="fill:#ffffff;fill-opacity:0.94565219">
<rect
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
width="1.451"
height="1.451"
x="6.445"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect1313" />
<rect
style="marker:none;fill:#ffffff;fill-opacity:0.94565219"
width="1.451"
height="1.451"
x="2.345"
y="288.474"
rx="0"
ry="0"
overflow="visible"
paint-order="stroke markers fill"
id="rect1315" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

+53 -50
View File
@@ -9,9 +9,6 @@ use OCA\SideMenu\Service\AppRepository;
use OCA\SideMenu\Service\CategoryRepository; use OCA\SideMenu\Service\CategoryRepository;
use OCA\SideMenu\Service\ConfigProxy; use OCA\SideMenu\Service\ConfigProxy;
use OCP\AppFramework\App; use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\IUserSession; use OCP\IUserSession;
use OCP\Util; use OCP\Util;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
@@ -21,7 +18,7 @@ use Psr\Container\ContainerInterface;
* *
* @author Simon Vieille <simon@deblan.fr> * @author Simon Vieille <simon@deblan.fr>
*/ */
class Application extends App implements IBootstrap class Application extends App
{ {
public const APP_ID = 'side_menu'; public const APP_ID = 'side_menu';
@@ -47,9 +44,16 @@ class Application extends App implements IBootstrap
public function __construct(array $urlParams = []) public function __construct(array $urlParams = [])
{ {
parent::__construct(self::APP_ID, $urlParams); parent::__construct(self::APP_ID, $urlParams);
$this->config = OC::$server->getConfig();
$this->cspnm = OC::$server->getContentSecurityPolicyNonceManager();
$this->user = OC::$server[IUserSession::class]->getUser();
} }
protected function isEnabled(): bool /**
* Checks if this app is enabled.
*/
public function isEnabled(): bool
{ {
$enabled = true; $enabled = true;
$isForced = (bool) $this->config->getAppValue(self::APP_ID, 'force', '0'); $isForced = (bool) $this->config->getAppValue(self::APP_ID, 'force', '0');
@@ -70,65 +74,64 @@ class Application extends App implements IBootstrap
return $enabled; return $enabled;
} }
protected function addAssets() /**
* Registes services.
*/
public function registerServices()
{ {
Util::addScript(self::APP_ID, 'sideMenu'); $container = $this->getContainer();
Util::addStyle(self::APP_ID, 'sideMenu');
$assets = [ $container->registerService('AppRepository', function (ContainerInterface $c) {
'stylesheet' => [
'route' => 'side_menu.Css.stylesheet',
'type' => 'link',
'route_attr' => 'href',
'attr' => [
'rel' => 'stylesheet',
],
],
'script' => [
'route' => 'side_menu.Js.script',
'type' => 'script',
'route_attr' => 'src',
'attr' => [
'nonce' => $this->cspnm->getNonce(),
],
],
];
$cache = $this->config->getAppValue(self::APP_ID, 'cache', '0');
foreach ($assets as $key => $value) {
$route = OC::$server->getURLGenerator()->linkToRoute($value['route'], ['v' => $cache]);
$value['attr'][$value['route_attr']] = $route;
Util::addHeader($value['type'], $value['attr'], '');
}
}
public function register(IRegistrationContext $context): void
{
$context->registerService('AppRepository', function (ContainerInterface $c) {
return new AppRepository(); return new AppRepository();
}); });
$context->registerService('CategoryRepository', function (ContainerInterface $c) { $container->registerService('CategoryRepository', function (ContainerInterface $c) {
return new CategoryRepository(); return new CategoryRepository();
}); });
$context->registerService('ConfigProxy', function (ContainerInterface $c) { $container->registerService('ConfigProxy', function (ContainerInterface $c) {
return new ConfigProxy(); return new ConfigProxy();
}); });
} }
public function boot(IBootContext $context): void /**
* Registers assets.
*/
public function registerAssets()
{ {
$this->config = OC::$server->getConfig(); Util::addScript(self::APP_ID, 'sideMenu');
$this->cspnm = OC::$server->getContentSecurityPolicyNonceManager(); Util::addStyle(self::APP_ID, 'sideMenu');
$this->user = OC::$server[IUserSession::class]->getUser();
if (!$this->isEnabled()) { $stylesheet = OC::$server->getURLGenerator()->linkToRoute(
return; 'side_menu.Css.stylesheet',
} [
'v' => $this->config->getAppValue(self::APP_ID, 'cache', '0'),
]
);
$this->addAssets(); $script = OC::$server->getURLGenerator()->linkToRoute(
'side_menu.Js.script',
[
'v' => $this->config->getAppValue(self::APP_ID, 'cache', '0'),
]
);
Util::addHeader(
'link',
[
'href' => $stylesheet,
'rel' => 'stylesheet',
],
''
);
Util::addHeader(
'script',
[
'src' => $script,
'nonce' => $this->cspnm->getNonce(),
],
''
);
} }
} }
+11 -44
View File
@@ -27,8 +27,6 @@ use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUserSession; use OCP\IUserSession;
use OCA\Theming\ThemingDefaults;
use OCA\SideMenu\Service\Color;
class CssController extends Controller class CssController extends Controller
{ {
@@ -42,30 +40,12 @@ class CssController extends Controller
*/ */
protected $user; protected $user;
/** public function __construct(string $appName, IRequest $request, ConfigProxy $config)
* @var ThemingDefaults
*/
protected $theming;
/**
* @var Color
*/
protected $color;
public function __construct(
string $appName,
IRequest $request,
ConfigProxy $config,
ThemingDefaults $theming,
Color $color
)
{ {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->user = OC::$server[IUserSession::class]->getUser(); $this->user = OC::$server[IUserSession::class]->getUser();
$this->config = $config; $this->config = $config;
$this->theming = $theming;
$this->color = $color;
} }
/** /**
@@ -87,7 +67,6 @@ class CssController extends Controller
{ {
$isForced = $this->config->getAppValueBool('force', '0'); $isForced = $this->config->getAppValueBool('force', '0');
$topMenuApps = $this->config->getAppValueArray('top-menu-apps', '[]'); $topMenuApps = $this->config->getAppValueArray('top-menu-apps', '[]');
$topSideMenuApps = $this->config->getAppValueArray('top-side-menu-apps', '[]');
$isAccessibilityAppEnabled = $this->config->getAppValueBool('enabled', '0', 'accessibility'); $isAccessibilityAppEnabled = $this->config->getAppValueBool('enabled', '0', 'accessibility');
$isBreezeDarkAppEnabled = $this->config->getAppValueBool('enabled', '0', 'breezedark'); $isBreezeDarkAppEnabled = $this->config->getAppValueBool('enabled', '0', 'breezedark');
@@ -95,16 +74,11 @@ class CssController extends Controller
if ($this->user) { if ($this->user) {
$userTopMenuApps = $this->config->getUserValueArray($this->user, 'top-menu-apps', '[]'); $userTopMenuApps = $this->config->getUserValueArray($this->user, 'top-menu-apps', '[]');
$userTopSideMenuApps = $this->config->getUserValueArray($this->user, 'top-side-menu-apps', '[]');
if (!empty($userTopMenuApps) && !$isForced) { if (!empty($userTopMenuApps) && !$isForced) {
$topMenuApps = $userTopMenuApps; $topMenuApps = $userTopMenuApps;
} }
if (!empty($userTopSideMenuApps) && !$isForced) {
$topSideMenuApps = $userTopSideMenuApps;
}
$isDarkThemeUserEnabled = $this->config->getUserValue($this->user, 'theme', '', 'accessibility') === 'dark'; $isDarkThemeUserEnabled = $this->config->getUserValue($this->user, 'theme', '', 'accessibility') === 'dark';
$isBreezeDarkUserEnabled = $this->config->getUserValue($this->user, 'theme_enabled', '', 'breezedark'); $isBreezeDarkUserEnabled = $this->config->getUserValue($this->user, 'theme_enabled', '', 'breezedark');
@@ -116,29 +90,23 @@ class CssController extends Controller
$isDarkMode = ($isAccessibilityAppEnabled && $isDarkThemeUserEnabled) || ($isBreezeDarkAppEnabled && $isBreezeDarkUserEnabled); $isDarkMode = ($isAccessibilityAppEnabled && $isDarkThemeUserEnabled) || ($isBreezeDarkAppEnabled && $isBreezeDarkUserEnabled);
$primaryColor = $this->theming->getColorPrimary();
$lightenPrimaryColor = $this->color->adjustBrightness($primaryColor, 0.2);
$darkenPrimaryColor = $this->color->adjustBrightness($primaryColor, -0.2);
$darkenPrimaryColor2 = $this->color->adjustBrightness($primaryColor, -0.3);
$textColor = $this->theming->getTextColorPrimary();
if ($isDarkMode) { if ($isDarkMode) {
$backgroundColor = $this->config->getAppValue('dark-mode-background-color', $darkenPrimaryColor); $backgroundColor = $this->config->getAppValue('dark-mode-background-color', '#333333');
$backgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $darkenPrimaryColor); $backgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $backgroundColor);
$currentAppBackgroundColor = $this->config->getAppValue('dark-mode-current-app-background-color', $darkenPrimaryColor2); $currentAppBackgroundColor = $this->config->getAppValue('dark-mode-current-app-background-color', '#444444');
$loaderColor = $this->config->getAppValue('dark-mode-loader-color', $lightenPrimaryColor); $loaderColor = $this->config->getAppValue('dark-mode-loader-color', '#cccccc');
$textColor = $this->config->getAppValue('dark-mode-text-color', $textColor); $textColor = $this->config->getAppValue('dark-mode-text-color', '#FFFFFF');
$iconInvertFilter = abs($this->config->getAppValueInt('dark-mode-icon-invert-filter', '0')).'%'; $iconInvertFilter = abs($this->config->getAppValueInt('dark-mode-icon-invert-filter', '0')).'%';
$iconOpacity = abs($this->config->getAppValueInt('dark-mode-icon-opacity', '100') / 100); $iconOpacity = abs($this->config->getAppValueInt('dark-mode-icon-opacity', '100') / 100);
$opener = $this->config->getAppValue('dark-mode-opener', 'side-menu-opener'); $opener = $this->config->getAppValue('dark-mode-opener', 'side-menu-opener');
$backgroundOpacity = dechex($this->config->getAppValueInt('dark-mode-background-color-opacity', '100') * 255 / 100); $backgroundOpacity = dechex($this->config->getAppValueInt('dark-mode-background-color-opacity', '100') * 255 / 100);
} else { } else {
$backgroundColor = $this->config->getAppValue('background-color', $darkenPrimaryColor); $backgroundColor = $this->config->getAppValue('background-color', '#333333');
$backgroundColorTo = $this->config->getAppValue('background-color-to', $darkenPrimaryColor); $backgroundColorTo = $this->config->getAppValue('background-color-to', $backgroundColor);
$currentAppBackgroundColor = $this->config->getAppValue('current-app-background-color', $darkenPrimaryColor2); $currentAppBackgroundColor = $this->config->getAppValue('current-app-background-color', '#444444');
$loaderColor = $this->config->getAppValue('loader-color', $lightenPrimaryColor); $loaderColor = $this->config->getAppValue('loader-color', '#0e75ac');
$textColor = $this->config->getAppValue('text-color', $textColor); $textColor = $this->config->getAppValue('text-color', '#FFFFFF');
$iconInvertFilter = abs($this->config->getAppValueInt('icon-invert-filter', '0')).'%'; $iconInvertFilter = abs($this->config->getAppValueInt('icon-invert-filter', '0')).'%';
$iconOpacity = abs($this->config->getAppValueInt('icon-opacity', '100') / 100); $iconOpacity = abs($this->config->getAppValueInt('icon-opacity', '100') / 100);
$opener = $this->config->getAppValue('opener', 'side-menu-opener'); $opener = $this->config->getAppValue('opener', 'side-menu-opener');
@@ -168,7 +136,6 @@ class CssController extends Controller
'always-displayed' => $this->config->getAppValueBool('always-displayed', '0'), 'always-displayed' => $this->config->getAppValueBool('always-displayed', '0'),
'big-menu' => $this->config->getAppValueBool('big-menu', '0'), 'big-menu' => $this->config->getAppValueBool('big-menu', '0'),
'top-menu-apps' => $topMenuApps, 'top-menu-apps' => $topMenuApps,
'top-side-menu-apps' => $topSideMenuApps,
]; ];
} }
} }
-7
View File
@@ -94,7 +94,6 @@ class JsController extends Controller
protected function getConfig(): array protected function getConfig(): array
{ {
$topMenuApps = $this->config->getAppValueArray('top-menu-apps', '[]'); $topMenuApps = $this->config->getAppValueArray('top-menu-apps', '[]');
$topSideMenuApps = $this->config->getAppValueArray('top-side-menu-apps', '[]');
$targetBlankApps = $this->config->getAppValueArray('target-blank-apps', '[]'); $targetBlankApps = $this->config->getAppValueArray('target-blank-apps', '[]');
$useAvatar = $this->config->getAppValueBool('use-avatar', '0'); $useAvatar = $this->config->getAppValueBool('use-avatar', '0');
$isForced = $this->config->getAppValueBool('force', '0'); $isForced = $this->config->getAppValueBool('force', '0');
@@ -104,16 +103,11 @@ class JsController extends Controller
if ($this->user) { if ($this->user) {
$userTopMenuApps = $this->config->getUserValueArray($this->user, 'top-menu-apps', '[]'); $userTopMenuApps = $this->config->getUserValueArray($this->user, 'top-menu-apps', '[]');
$userTopSideMenuApps = $this->config->getUserValueArray($this->user, 'top-side-menu-apps', '[]');
if (!empty($userTopMenuApps) && !$isForced) { if (!empty($userTopMenuApps) && !$isForced) {
$topMenuApps = $userTopMenuApps; $topMenuApps = $userTopMenuApps;
} }
if (!empty($userTopSideMenuApps) && !$isForced) {
$topSideMenuApps = $userTopSideMenuApps;
}
$userTargetBlankMode = $this->config->getUserValueInt($this->user, 'target-blank-mode', '1'); $userTargetBlankMode = $this->config->getUserValueInt($this->user, 'target-blank-mode', '1');
$userTargetBlankApps = $this->config->getUserValueArray($this->user, 'target-blank-apps', '[]'); $userTargetBlankApps = $this->config->getUserValueArray($this->user, 'target-blank-apps', '[]');
@@ -163,7 +157,6 @@ class JsController extends Controller
'big-menu-hidden-apps' => $this->config->getAppValueArray('big-menu-hidden-apps', '[]'), 'big-menu-hidden-apps' => $this->config->getAppValueArray('big-menu-hidden-apps', '[]'),
'avatar' => $avatar, 'avatar' => $avatar,
'top-menu-apps' => $topMenuApps, 'top-menu-apps' => $topMenuApps,
'top-side-menu-apps' => $topSideMenuApps,
'target-blank-apps' => $targetBlankApps, 'target-blank-apps' => $targetBlankApps,
'settings' => $settings, 'settings' => $settings,
'logo' => $this->themingDefaults->getLogo(), 'logo' => $this->themingDefaults->getLogo(),
-9
View File
@@ -187,18 +187,9 @@ class NavController extends Controller
usort($items, function ($a, $b) use ($categoriesLabels) { usort($items, function ($a, $b) use ($categoriesLabels) {
foreach ($categoriesLabels as $key => $value) { foreach ($categoriesLabels as $key => $value) {
if ($a['categoryId'] === 'other') {
return -1;
}
if ($b['categoryId'] === 'other') {
return 1;
}
if ($a['categoryId'] === $key) { if ($a['categoryId'] === $key) {
return -1; return -1;
} }
if ($b['categoryId'] === $key) { if ($b['categoryId'] === $key) {
return 1; return 1;
} }
+1 -2
View File
@@ -54,7 +54,6 @@ class PersonalSettingController extends Controller
/** /**
* @NoAdminRequired * @NoAdminRequired
* @NoCSRFRequired
* *
* @param mixed $name * @param mixed $name
* @param mixed $value * @param mixed $value
@@ -97,7 +96,7 @@ class PersonalSettingController extends Controller
} }
} }
if (in_array($name, ['top-menu-apps', 'top-side-menu-apps'])) { if ('top-menu-apps' === $name) {
$doSave = true; $doSave = true;
$data = json_decode($value, true); $data = json_decode($value, true);
+1 -27
View File
@@ -21,27 +21,10 @@ class AppRepository
*/ */
protected $l10nFactory; protected $l10nFactory;
/** public function __construct(\OC_App $ocApp, IFactory $l10nFactory)
* @var ConfigProxy
*/
protected $config;
/**
* @var CategoryRepository
*/
protected $categoryRepository;
public function __construct(
\OC_App $ocApp,
IFactory $l10nFactory,
ConfigProxy $config,
CategoryRepository $categoryRepository
)
{ {
$this->ocApp = $ocApp; $this->ocApp = $ocApp;
$this->l10nFactory = $l10nFactory; $this->l10nFactory = $l10nFactory;
$this->config = $config;
$this->categoryRepository = $categoryRepository;
} }
/** /**
@@ -52,9 +35,6 @@ class AppRepository
public function getVisibleApps() public function getVisibleApps()
{ {
$navigation = $this->ocApp->getNavigation(); $navigation = $this->ocApp->getNavigation();
$appCategoriesCustom = $this->config->getAppValueArray('apps-categories-custom', '[]');
$categoriesCustom = $this->config->getAppValueArray('categories-custom', '[]');
$categories = $this->categoryRepository->getOrderedCategories();
$apps = $this->ocApp->listAllApps(); $apps = $this->ocApp->listAllApps();
$visibleApps = []; $visibleApps = [];
@@ -94,12 +74,6 @@ class AppRepository
} }
} }
foreach ($visibleApps as $id => $app) {
if (isset($appCategoriesCustom[$id], $categories[$appCategoriesCustom[$id]])) {
$visibleApps[$id]['category'] = [$appCategoriesCustom[$id]];
}
}
usort($visibleApps, function ($a, $b) { usort($visibleApps, function ($a, $b) {
return ($a['name'] < $b['name']) ? -1 : 1; return ($a['name'] < $b['name']) ? -1 : 1;
}); });
+2 -22
View File
@@ -5,7 +5,6 @@ namespace OCA\SideMenu\Service;
use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher;
use OCA\SideMenu\AppInfo\Application; use OCA\SideMenu\AppInfo\Application;
use OCP\IConfig; use OCP\IConfig;
use OCP\IUserSession;
use OCP\L10N\IFactory; use OCP\L10N\IFactory;
/** /**
@@ -35,23 +34,16 @@ class CategoryRepository
*/ */
protected $iConfig; protected $iConfig;
/**
* @var IUserSession
*/
protected $userSession;
public function __construct( public function __construct(
CategoryFetcher $categoryFetcher, CategoryFetcher $categoryFetcher,
ConfigProxy $config, ConfigProxy $config,
IConfig $iConfig, IConfig $iConfig,
IFactory $l10nFactory, IFactory $l10nFactory
IUserSession $userSession
) { ) {
$this->categoryFetcher = $categoryFetcher; $this->categoryFetcher = $categoryFetcher;
$this->l10nFactory = $l10nFactory; $this->l10nFactory = $l10nFactory;
$this->config = $config; $this->config = $config;
$this->iConfig = $iConfig; $this->iConfig = $iConfig;
$this->userSession = $userSession;
} }
/** /**
@@ -64,8 +56,8 @@ class CategoryRepository
$currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2); $currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2);
$type = $this->config->getAppValue('categories-order-type', 'default'); $type = $this->config->getAppValue('categories-order-type', 'default');
$order = $this->config->getAppValueArray('categories-order', '[]'); $order = $this->config->getAppValueArray('categories-order', '[]');
$categoriesLabels = $this->config->getAppValueArray('cache-categories', '[]'); $categoriesLabels = $this->config->getAppValueArray('cache-categories', '[]');
$customCategories = $this->config->getAppValueArray('categories-custom', '[]');
if (empty($categoriesLabels)) { if (empty($categoriesLabels)) {
$categoriesLabels = $this->categoryFetcher->get(); $categoriesLabels = $this->categoryFetcher->get();
@@ -82,18 +74,6 @@ class CategoryRepository
$categoriesLabels['external_links'] = $this->l10nFactory->get('external')->t('External sites'); $categoriesLabels['external_links'] = $this->l10nFactory->get('external')->t('External sites');
$categoriesLabels['other'] = ''; $categoriesLabels['other'] = '';
$user = $this->userSession->getUser();
if ($user) {
$lang = $this->iConfig->getUserValue($user->getUid(), 'core', 'lang');
} else {
$lang = 'en';
}
foreach ($customCategories as $category) {
$categoriesLabels[$category['id']] = $category[$lang] ?? $category['en'];
}
asort($categoriesLabels); asort($categoriesLabels);
if ('custom' === $type) { if ('custom' === $type) {
-34
View File
@@ -1,34 +0,0 @@
<?php
namespace OCA\SideMenu\Service;
/**
* class Color.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class Color
{
/**
* @thanks https://stackoverflow.com/posts/54393956/revision
*/
public function adjustBrightness(string $hexCode, float $adjustPercent): string
{
$hexCode = ltrim($hexCode, '#');
if (3 == strlen($hexCode)) {
$hexCode = $hexCode[0].$hexCode[0].$hexCode[1].$hexCode[1].$hexCode[2].$hexCode[2];
}
$hexCode = array_map('hexdec', str_split($hexCode, 2));
foreach ($hexCode as &$color) {
$adjustableLimit = $adjustPercent < 0 ? $color : 255 - $color;
$adjustAmount = ceil($adjustableLimit * $adjustPercent);
$color = str_pad(dechex($color + $adjustAmount), 2, '0', STR_PAD_LEFT);
}
return '#'.implode($hexCode);
}
}
-48
View File
@@ -1,48 +0,0 @@
<?php
namespace OCA\SideMenu\Service;
use OCP\IDBConnection;
/**
* class LangRepository.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class LangRepository
{
/**
* @var IDBConnection
*/
protected $db;
public function __construct(IDBConnection $db)
{
$this->db = $db;
}
public function getUsedLangs(): array
{
$qb = $this->db->getQueryBuilder();
$qb->select($qb->createFunction('DISTINCT configvalue'))
->where('configkey=:configkey and appid=:appid and configvalue<>:configvalue')
->setParameters([
'configkey' => 'lang',
'appid' => 'core',
'configvalue' => 'en',
])
->from('preferences')
;
$stmt = $qb->execute();
$langs = ['en'];
foreach ($stmt->fetchAll() as $result) {
$langs[] = $result['configvalue'];
}
return $langs;
}
}
+12 -58
View File
@@ -26,9 +26,6 @@ use OCP\AppFramework\Http\TemplateResponse;
use OCP\IL10N; use OCP\IL10N;
use OCP\ILogger; use OCP\ILogger;
use OCP\Settings\ISettings; use OCP\Settings\ISettings;
use OCA\Theming\ThemingDefaults;
use OCA\SideMenu\Service\Color;
use OCA\SideMenu\Service\LangRepository;
class Admin implements ISettings class Admin implements ISettings
{ {
@@ -57,39 +54,18 @@ class Admin implements ISettings
*/ */
private $categoryRepository; private $categoryRepository;
/**
* @var ThemingDefaults
*/
protected $theming;
/**
* @var Color
*/
protected $color;
/**
* @var LangRepository
*/
protected $langRepository;
public function __construct( public function __construct(
IL10N $l, IL10N $l,
ILogger $logger, ILogger $logger,
ConfigProxy $config, ConfigProxy $config,
AppRepository $appRepository, AppRepository $appRepository,
CategoryRepository $categoryRepository, CategoryRepository $categoryRepository
ThemingDefaults $theming,
Color $color,
LangRepository $langRepository
) { ) {
$this->l = $l; $this->l = $l;
$this->logger = $logger; $this->logger = $logger;
$this->config = $config; $this->config = $config;
$this->appRepository = $appRepository; $this->appRepository = $appRepository;
$this->categoryRepository = $categoryRepository; $this->categoryRepository = $categoryRepository;
$this->theming = $theming;
$this->color = $color;
$this->langRepository = $langRepository;
} }
/** /**
@@ -97,47 +73,29 @@ class Admin implements ISettings
*/ */
public function getForm() public function getForm()
{ {
$primaryColor = $this->theming->getColorPrimary(); $backgroundColor = $this->config->getAppValue('background-color', '#333333');
$lightenPrimaryColor = $this->color->adjustBrightness($primaryColor, 0.2); $backgroundColorTo = $this->config->getAppValue('background-color-to', $backgroundColor);
$darkenPrimaryColor = $this->color->adjustBrightness($primaryColor, -0.2);
$darkenPrimaryColor2 = $this->color->adjustBrightness($primaryColor, -0.3);
$textColor = $this->theming->getTextColorPrimary();
$backgroundColor = $this->config->getAppValue('background-color', $darkenPrimaryColor); $darkModeBackgroundColor = $this->config->getAppValue('dark-mode-background-color', '#333333');
$backgroundColorTo = $this->config->getAppValue('background-color-to', $darkenPrimaryColor); $darkModeBackgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $darkModeBackgroundColor);
$darkModeBackgroundColor = $this->config->getAppValue('dark-mode-background-color', $darkenPrimaryColor);
$darkModeBackgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $darkenPrimaryColor);
$parameters = [ $parameters = [
'defaults' => [
'background-color' => $darkenPrimaryColor,
'background-color-to' => $darkenPrimaryColor,
'current-app-background-color' => $darkenPrimaryColor2,
'text-color' => $textColor,
'loader-color' => $lightenPrimaryColor,
'dark-mode-background-color' => $darkenPrimaryColor,
'dark-mode-background-color-to' => $darkenPrimaryColor,
'dark-mode-current-app-background-color' => $darkenPrimaryColor2,
'dark-mode-text-color' => $textColor,
'dark-mode-loader-color' => $textColor,
],
'background-color' => $backgroundColor, 'background-color' => $backgroundColor,
'background-color-to' => $backgroundColorTo, 'background-color-to' => $backgroundColorTo,
'background-color-opacity' => $this->config->getAppValueInt('background-color-opacity', '100'), 'background-color-opacity' => $this->config->getAppValueInt('background-color-opacity', '100'),
'current-app-background-color' => $this->config->getAppValue('current-app-background-color', $darkenPrimaryColor2), 'current-app-background-color' => $this->config->getAppValue('current-app-background-color', '#444444'),
'loader-color' => $this->config->getAppValue('loader-color', $lightenPrimaryColor), 'loader-color' => $this->config->getAppValue('loader-color', '#0e75ac'),
'icon-invert-filter' => $this->config->getAppValueInt('icon-invert-filter', '0'), 'icon-invert-filter' => $this->config->getAppValueInt('icon-invert-filter', '0'),
'icon-opacity' => $this->config->getAppValueInt('icon-opacity', '100'), 'icon-opacity' => $this->config->getAppValueInt('icon-opacity', '100'),
'text-color' => $this->config->getAppValue('text-color', $textColor), 'text-color' => $this->config->getAppValue('text-color', '#FFFFFF'),
'dark-mode-background-color' => $darkModeBackgroundColor, 'dark-mode-background-color' => $darkModeBackgroundColor,
'dark-mode-background-color-to' => $darkModeBackgroundColorTo, 'dark-mode-background-color-to' => $darkModeBackgroundColorTo,
'dark-mode-background-color-opacity' => $this->config->getAppValueInt('dark-mode-background-color-opacity', '100'), 'dark-mode-background-color-opacity' => $this->config->getAppValueInt('dark-mode-background-color-opacity', '100'),
'dark-mode-current-app-background-color' => $this->config->getAppValue('dark-mode-current-app-background-color', $darkenPrimaryColor2), 'dark-mode-current-app-background-color' => $this->config->getAppValue('dark-mode-current-app-background-color', '#444444'),
'dark-mode-loader-color' => $this->config->getAppValue('dark-mode-loader-color', $textColor), 'dark-mode-loader-color' => $this->config->getAppValue('dark-mode-loader-color', '#cccccc'),
'dark-mode-icon-invert-filter' => $this->config->getAppValueInt('dark-mode-icon-invert-filter', '0'), 'dark-mode-icon-invert-filter' => $this->config->getAppValueInt('dark-mode-icon-invert-filter', '0'),
'dark-mode-icon-opacity' => $this->config->getAppValueInt('dark-mode-icon-opacity', '100'), 'dark-mode-icon-opacity' => $this->config->getAppValueInt('dark-mode-icon-opacity', '100'),
'dark-mode-text-color' => $this->config->getAppValue('dark-mode-text-color', $textColor), 'dark-mode-text-color' => $this->config->getAppValue('dark-mode-text-color', '#FFFFFF'),
'dark-mode-opener' => $this->config->getAppValue('dark-mode-opener', 'side-menu-opener'), 'dark-mode-opener' => $this->config->getAppValue('dark-mode-opener', 'side-menu-opener'),
'opener' => $this->config->getAppValue('opener', 'side-menu-opener'), 'opener' => $this->config->getAppValue('opener', 'side-menu-opener'),
'loader-enabled' => $this->config->getAppValue('loader-enabled', '1'), 'loader-enabled' => $this->config->getAppValue('loader-enabled', '1'),
@@ -159,15 +117,11 @@ class Admin implements ISettings
'force' => $this->config->getAppValue('force', '0'), 'force' => $this->config->getAppValue('force', '0'),
'target-blank-apps' => $this->config->getAppValueArray('target-blank-apps', '[]'), 'target-blank-apps' => $this->config->getAppValueArray('target-blank-apps', '[]'),
'top-menu-apps' => $this->config->getAppValueArray('top-menu-apps', '[]'), 'top-menu-apps' => $this->config->getAppValueArray('top-menu-apps', '[]'),
'top-side-menu-apps' => $this->config->getAppValueArray('top-side-menu-apps', '[]'),
'default-enabled' => $this->config->getAppValue('default-enabled', '1'), 'default-enabled' => $this->config->getAppValue('default-enabled', '1'),
'apps' => $this->appRepository->getVisibleApps(),
'apps-categories-custom' => $this->config->getAppValueArray('apps-categories-custom', '[]'),
'categories-order-type' => $this->config->getAppValue('categories-order-type', 'default'), 'categories-order-type' => $this->config->getAppValue('categories-order-type', 'default'),
'categories-order' => $this->config->getAppValueArray('categories-order', '[]'), 'categories-order' => $this->config->getAppValueArray('categories-order', '[]'),
'categories-custom' => $this->config->getAppValueArray('categories-custom', '[]'), 'apps' => $this->appRepository->getVisibleApps(),
'categories' => $this->categoryRepository->getOrderedCategories(), 'categories' => $this->categoryRepository->getOrderedCategories(),
'langs' => $this->langRepository->getUsedLangs(),
]; ];
return new TemplateResponse(Application::APP_ID, 'settings/admin-form', $parameters, ''); return new TemplateResponse(Application::APP_ID, 'settings/admin-form', $parameters, '');
-1
View File
@@ -78,7 +78,6 @@ class Personal implements ISettings
$this->config->getAppValue('default-enabled', '1') $this->config->getAppValue('default-enabled', '1')
), ),
'top-menu-apps' => $this->config->getUserValueArray($user, 'top-menu-apps', '[]'), 'top-menu-apps' => $this->config->getUserValueArray($user, 'top-menu-apps', '[]'),
'top-side-menu-apps' => $this->config->getUserValueArray($user, 'top-side-menu-apps', '[]'),
'target-blank-mode' => $this->config->getUserValue($user, 'target-blank-mode', '1'), 'target-blank-mode' => $this->config->getUserValue($user, 'target-blank-mode', '1'),
'target-blank-apps' => $this->config->getUserValueArray($user, 'target-blank-apps', '[]'), 'target-blank-apps' => $this->config->getUserValueArray($user, 'target-blank-apps', '[]'),
'apps' => $this->appRepository->getVisibleApps(), 'apps' => $this->appRepository->getVisibleApps(),
+5 -5
View File
@@ -11,9 +11,9 @@
"stylelint:fix": "stylelint src --fix" "stylelint:fix": "stylelint src --fix"
}, },
"dependencies": { "dependencies": {
"@nextcloud/axios": "^1.8.0", "@nextcloud/axios": "^1.3.2",
"@nextcloud/vue": "^1.5.0", "@nextcloud/vue": "^1.4.0",
"axios": "^0.24.0", "axios": "^0.19.2",
"trim": "0.0.1", "trim": "0.0.1",
"vue": "^2.6.11" "vue": "^2.6.11"
}, },
@@ -21,7 +21,7 @@
"extends @nextcloud/browserslist-config" "extends @nextcloud/browserslist-config"
], ],
"engines": { "engines": {
"node": ">=16.0.0" "node": ">=10.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.9.0", "@babel/core": "^7.9.0",
@@ -43,9 +43,9 @@
"eslint-plugin-standard": "^4.0.1", "eslint-plugin-standard": "^4.0.1",
"eslint-plugin-vue": "^5.2.3", "eslint-plugin-vue": "^5.2.3",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"node-sass": "^4.13.1",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"stylelint": "^8.4.0", "stylelint": "^8.4.0",
"sass": "^1.49.9",
"stylelint-config-recommended-scss": "^3.3.0", "stylelint-config-recommended-scss": "^3.3.0",
"stylelint-scss": "^3.16.0", "stylelint-scss": "^3.16.0",
"stylelint-webpack-plugin": "^0.10.5", "stylelint-webpack-plugin": "^0.10.5",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 KiB

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

-182
View File
@@ -1,182 +0,0 @@
<!--
@license GNU AGPL version 3 or any later version
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/>.
-->
<template>
<div>
<ul class="side-menu-setting-list">
<li v-for="item in values" class="side-menu-setting-list-item" v-on:click="showEditForm(item)">
<span v-html="item.en"></span>
</li>
</ul>
<Actions>
<ActionButton @click="showAddForm" icon="icon-add"></ActionButton>
</Actions>
<Modal v-if="addForm" @close="hideAddForm">
<div class="modal__content">
<div v-for="lang in langs">
<span class="lang" v-html="lang"></span>
<input type="text" v-model="newValue[lang]" required>
</div>
<Actions>
<ActionButton @click="saveAdd" icon="icon-checkmark"></ActionButton>
</Actions>
</div>
</Modal>
<Modal v-if="editForm" @close="hideEditForm">
<div class="modal__content">
<div v-for="lang in langs">
<span class="lang" v-html="lang"></span>
<input type="text" v-model="editValue[lang]" required>
</div>
<div class="pull-right">
<Actions>
<ActionButton @click="removeEdit" icon="icon-delete"></ActionButton>
</Actions>
</div>
<Actions>
<ActionButton @click="saveEdit" icon="icon-checkmark"></ActionButton>
</Actions>
</div>
</Modal>
</div>
</template>
<style scoped>
.modal__content {
width: 200px;
padding: 10px;
}
.modal__content .lang {
width: 60px;
display: inline-block;
padding: 4px;
box-sizing: border-box;
}
.modal__content input[type=text] {
width: calc(100% - 85px);
display: inline-block;
margin: 0;
}
.pull-right {
float: right;
}
</style>
<script>
import Modal from '@nextcloud/vue/dist/Components/Modal'
import Actions from '@nextcloud/vue/dist/Components/Actions'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
export default {
name: 'AdminCategoriesCustom',
components: {
Modal,
Actions,
ActionButton,
},
data() {
return {
input: null,
values: [],
langs: [],
addForm: false,
editForm: false,
newValue: {},
editValue: {},
}
},
methods: {
init() {
this.values = JSON.parse(this.input.value)
this.langs = JSON.parse(this.input.getAttribute('data-langs'))
},
update() {
this.input.value = JSON.stringify(this.values)
},
showAddForm() {
this.newValue = {id: 'cat' + Math.random().toString().replace('0.', '')}
this.addForm = true
},
showEditForm(value) {
this.editValue = {id: value.id}
for (let i of this.langs) {
this.editValue[i] = typeof value[i] !== 'undefined' ? value[i] : ''
}
this.editForm = true
},
saveAdd() {
for (let i of this.langs) {
if (!this.newValue[i] || /^\s*$/.test(this.newValue[i])) {
return
}
}
this.values.push(this.newValue)
this.update()
this.hideAddForm()
this.newValue = {}
},
saveEdit() {
for (let i of this.langs) {
if (!this.editValue[i] || /^\s*$/.test(this.editValue[i])) {
return
}
}
for (let i in this.values) {
if (this.values[i].id === this.editValue.id) {
this.values[i] = this.editValue
}
}
this.update()
this.hideEditForm()
},
removeEdit() {
for (let i in this.values) {
if (this.values[i].id === this.editValue.id) {
this.values.splice(i, 1);
}
}
this.update()
this.hideEditForm()
},
hideAddForm() {
this.addForm = false
},
hideEditForm() {
this.editForm = false
},
},
mounted() {
this.input = document.querySelector('input[name="categories-custom"]')
this.init()
}
}
</script>
+1 -1
View File
@@ -41,7 +41,7 @@ const mountSideMenuComponent = () => {
sideMenu.$mount('#side-menu') sideMenu.$mount('#side-menu')
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.ready')) $('body').trigger('side-menu.ready')
} else { } else {
window.setTimeout(mountSideMenuComponent, 50) window.setTimeout(mountSideMenuComponent, 50)
} }
+4 -6
View File
@@ -100,7 +100,7 @@ export default {
var dataId = parent.getAttribute('data-id') var dataId = parent.getAttribute('data-id')
dataId = dataId !== null ? dataId : '' dataId = dataId !== null ? dataId : ''
if (!parent.classList.contains('app-top-side-menu') && !parent.classList.contains('app-hidden') && !menuIsHidden) { if (!parent.classList.contains('app-hidden') && !menuIsHidden) {
continue continue
} }
@@ -122,15 +122,13 @@ 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() {
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', { jQuery('body').trigger('side-menu.apps', [apps])
detail: {apps: apps},
}))
}, 1000) }, 1000)
})(this.apps) })(this.apps)
}, },
@@ -149,7 +147,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() {
+3 -5
View File
@@ -97,10 +97,8 @@ export default {
} }
} }
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', { jQuery('body').trigger('side-menu.apps', [apps])
detail: {apps: apps}, });
}))
})
}, },
retrieveActiveApp() { retrieveActiveApp() {
@@ -118,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() {
+3 -5
View File
@@ -95,10 +95,8 @@ export default {
} }
} }
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', { jQuery('body').trigger('side-menu.apps', [apps])
detail: {apps: apps}, });
}))
})
}, },
retrieveActiveApp() { retrieveActiveApp() {
@@ -116,7 +114,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() {
+78 -173
View File
@@ -15,32 +15,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import AdminCategoriesCustom from './AdminCategoriesCustom.vue'
import Vue from 'vue'
Vue.prototype.OC = window.OC
Vue.prototype.OCA = window.OCA
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 = []
formData.push('name=' + encodeURIComponent(name)) $.post(url, {name: name, value: value}, callbacks.success)
formData.push('value=' + encodeURIComponent(value)) .fail(callbacks.error)
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.join('&')
})
.then(callbacks.success)
.catch(callbacks.error)
} }
const appConfig = (name, value, callbacks) => { const appConfig = (name, value, callbacks) => {
@@ -48,29 +31,23 @@ const appConfig = (name, value, callbacks) => {
} }
const saveSettings = (key) => { const saveSettings = (key) => {
const element = elements[key] const element = elements.get(key)
if (!element) {
return
}
let value let value
let name let name
if (element.hasAttribute('data-checkbox')) { if (jQuery(element).is('[data-checkbox]')) {
name = element.getAttribute('data-name') name = jQuery(element).attr('data-name')
const inputs = jQuery('input[name="' + name + '[]"]:checked')
value = [] value = []
const inputs = document.querySelectorAll('input[name="' + name + '[]"]:checked') inputs.each((i, v) => {
value.push(v.value)
for (let input of inputs) { })
value.push(input.value)
}
value = JSON.stringify(value) value = JSON.stringify(value)
} else { } else {
name = element.getAttribute('name') name = jQuery(element).attr('name')
value = element.value value = jQuery(element).val()
} }
const size = elements.length const size = elements.length
@@ -79,21 +56,17 @@ const saveSettings = (key) => {
++value ++value
} }
const progress = document.querySelector('#side-menu-save-progress')
progress.style.width = '40px';
progress.style.marginLeft = '5px';
const callbacks = { const callbacks = {
success: () => { success: () => {
const percent = parseInt((key + 1) * 100 / size); OC.msg.finishedSuccess(
selector,
progress.setAttribute('value', percent) t('side_menu', (key + 1) + '/' + size)
)
if (key < size - 1) { if (key < size - 1) {
saveSettings(key + 1) saveSettings(++key)
} else { } else {
location.reload() OC.msg.finishedSuccess(selector, t('side_menu', 'Saved'))
} }
}, },
error: () => { error: () => {
@@ -101,7 +74,7 @@ const saveSettings = (key) => {
} }
} }
if (element.hasAttribute('data-personal')) { if (jQuery(element).is('[data-personal]')) {
userConfig(name, value, callbacks) userConfig(name, value, callbacks)
} else { } else {
appConfig(name, value, callbacks) appConfig(name, value, callbacks)
@@ -109,152 +82,84 @@ const saveSettings = (key) => {
} }
const elementToggler = (element) => { const elementToggler = (element) => {
let display = 'none' jQuery(element).toggle()
if (window.getComputedStyle(element).display === 'none') {
display = 'block'
}
element.style.display = display
} }
const updateAppsCategoriesCustom = () => { jQuery(document).ready(() => {
let values = {} elements = jQuery('.side-menu-setting')
for (let item of document.querySelectorAll('.apps-categories-custom')) { jQuery('#side-menu-save').on('click', (event) => {
let app = item.getAttribute('data-app')
let value = item.value
if (value) {
values[app] = value
}
}
document.querySelector('#apps-categories-custom').value = JSON.stringify(values)
}
document.addEventListener('DOMContentLoaded', () => {
$('*[data-toggle="tooltip"]').tooltip();
if (document.querySelector('#side-menu-categories-custom')) {
const View = Vue.extend(AdminCategoriesCustom)
const adminCategoriesCustom = new View({})
adminCategoriesCustom.$mount('#side-menu-categories-custom')
}
elements = document.querySelectorAll('.side-menu-setting')
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'))
}) })
const resets = document.querySelectorAll('.btn-reset') jQuery('.side-menu-setting-live').on('change', (event) => {
var target = jQuery(event.target)
var name = target.attr('name')
var value = target.val()
for (let btn of resets) { if ('background-color-opacity' === name) {
btn.addEventListener('click', (event) => { return $('#side-menu-background-color, #side-menu-background-color-to').trigger('change');
const target = event.target } else if ('dark-mode-background-color-opacity' === name) {
const values = JSON.parse(target.getAttribute('data-reset')) return $('#side-menu-dark-mode-background-color, #side-menu-dark-mode-background-color-to').trigger('change');
}
for (let i in values) { if (name === 'opener') {
document.querySelector(`#${i}`).value = values[i] var url = OC.generateUrl(`/apps/side_menu/img/${value}.svg`).replace('/index.php', '')
}
})
}
const displays = document.querySelectorAll('.side-menu-display') value = `url(${url})`;
}
for (let display of displays) { if (name === 'icon-invert-filter' || name === 'icon-opacity') {
display.addEventListener('click', (event) => { value/=100;
const target = event.target }
for (let d of displays) { if (['dark-mode-background-color', 'dark-mode-background-color-to'].indexOf(name) > -1) {
d.classList.toggle('is-active', d === display) var opacity = parseInt($('#side-menu-dark-mode-background-color-opacity').val() * 255 / 100);
}
document.querySelector('#side-menu-always-displayed').value = target.getAttribute('data-alwaysdiplayed') value = [value, opacity.toString(16)].join('');
document.querySelector('#side-menu-big-menu').value = target.getAttribute('data-bigmenu') } else if (['background-color', 'background-color-to'].indexOf(name) > -1) {
document.querySelector('#side-menu-side-with-categories').value = target.getAttribute('data-sidewithcategories') var opacity = parseInt($('#side-menu-background-color-opacity').val() * 255 / 100);
})
}
for (let item of document.querySelectorAll('.apps-categories-custom')) { value = [value, opacity.toString(16)].join('');
item.addEventListener('change', (event) => { }
updateAppsCategoriesCustom()
})
}
for (let item of document.querySelectorAll('.side-menu-setting-live')) { document.documentElement.style.setProperty('--side-menu-' + name, value)
item.addEventListener('change', (event) => {
const target = event.target
const name = target.getAttribute('name')
let value = target.value
let id = null
if (name === 'background-color-opacity') {
id = '#side-menu-background-color, #side-menu-background-color-to'
} else if (name === 'dark-mode-background-color-opacity') {
id = '#side-menu-dark-mode-background-color, #side-menu-dark-mode-background-color-to'
}
if (id) {
document.querySelector(id).dispatchEvent(new CustomEvent('change'))
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'
}) })
try { jQuery('.side-menu-toggler').on('click', (event) => {
sortable('#categories-list .side-menu-setting-list')[0].addEventListener('sortstop', (e) => { var target = jQuery(event.target)
var element = target.attr('data-target')
elementToggler(element)
})
jQuery("#categories-list .side-menu-setting-list").sortable({
forcePlaceholderSize: true,
placeholder: 'placeholder',
stop: function (event, ui) {
let value = [] let value = []
for (let item of document.querySelectorAll('#categories-list .side-menu-setting-list-item')) { jQuery('#categories-list .side-menu-setting-list-item').each(function() {
console.log(item.getAttribute('data-id')) value.push(jQuery(this).attr('data-id'))
value.push(item.getAttribute('data-id')) });
}
document.querySelector('input[name="categories-order"]').value = JSON.stringify(value) value = JSON.stringify(value)
})
} catch (e) { jQuery('input[name="categories-order"]').val(value)
} }
}) });
});
-14
View File
@@ -77,17 +77,3 @@
"This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "Tyto parametry jsou použity v případě, že je zapnutý (Breeze) tmavý motiv vzhledu." "This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "Tyto parametry jsou použity v případě, že je zapnutý (Breeze) tmavý motiv vzhledu."
"Dark mode colors": "Barvy tmavého režimu" "Dark mode colors": "Barvy tmavého režimu"
"With categories": "S kategoriemi" "With categories": "S kategoriemi"
"Custom categories": "Vlastní kategorie"
"Customize application categories": "Personnaliser les catégories des applications"
"Customize application categories": "Přizpůsobte kategorie aplikací"
"Apps only visible in the top menu": "Aplikace jsou viditelné pouze v horní nabídce "
"Apps visible in the top and side menus": "Aplikace viditelné v horní a boční nabídce"
"Reset to default": "Vrátit zpět na výchozí hodnoty"
"Hidden icon": "Skrytá ikona"
"Small icon": "Malá ikona"
"Normal icon": "Normální ikona"
"Big icon": "Velká ikona"
"Hidden text": "Skrytý text"
"Small text": "Malý text"
"Normal text": "Normální text"
"Big text": "Velký text"
-13
View File
@@ -77,16 +77,3 @@
"This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "Diese Optionen werden auf <code>Dark Theme</code> oder <code>Breeze Dark Theme</code> angewendet." "This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "Diese Optionen werden auf <code>Dark Theme</code> oder <code>Breeze Dark Theme</code> angewendet."
"Dark mode colors": "Farben für den dunklen Modus" "Dark mode colors": "Farben für den dunklen Modus"
"With categories": "Mit Kategorien" "With categories": "Mit Kategorien"
"Custom categories": "Benutzerdefinierte Kategorien"
"Customize application categories": "Anwendungskategorien anpassen"
"Apps only visible in the top menu": "Apps nur im oberen Menü sichtbar "
"Apps visible in the top and side menus": "Apps im oberen und seitlichen Menü sichtbar"
"Reset to default": "Auf Standard zurücksetzen"
"Hidden icon": "Verstecktes Symbol"
"Small icon": "Kleines Symbol"
"Normal icon": "Normales Symbol"
"Big icon": "Große Ikone"
"Hidden text": "Versteckter Text"
"Small text": "Kleiner Text"
"Normal text": "Normaler Text"
"Big text": "Großer Text"
-13
View File
@@ -15,14 +15,6 @@
"Small": "Petit" "Small": "Petit"
"Normal": "Normal" "Normal": "Normal"
"Big": "Gros" "Big": "Gros"
"Hidden icon": "Icône masqué"
"Small icon": "Petit icône"
"Normal icon": "Icône normal"
"Big icon": "Gros icône"
"Hidden text": "Text masqué"
"Small text": "Texte petit"
"Normal text": "Texte normal"
"Big text": "Gros texte"
"Colors": "Couleurs" "Colors": "Couleurs"
"Background color": "Couleur de fond" "Background color": "Couleur de fond"
"Background color of current app": "Couleur de fond de l'application en cours" "Background color of current app": "Couleur de fond de l'application en cours"
@@ -85,8 +77,3 @@
"This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "Ces paramètres sont utilisés lorsque le thème sombre ou le thème Breeze Dark sont activés." "This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "Ces paramètres sont utilisés lorsque le thème sombre ou le thème Breeze Dark sont activés."
"Dark mode colors": "Couleurs du mode sombre" "Dark mode colors": "Couleurs du mode sombre"
"With categories": "Avec les catégories" "With categories": "Avec les catégories"
"Custom categories": "Catégories personnalisées"
"Customize application categories": "Personnaliser les catégories des applications"
"Apps only visible in the top menu": "Applications visibles uniquement dans le menu supérieur"
"Apps visible in the top and side menus": "Applications visibles dans le menus supérieur et latéral"
"Reset to default": "Restaurer les valeurs par défaut"
-13
View File
@@ -77,16 +77,3 @@
"This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "此参数将应用于暗黑主题激活时。" "This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "此参数将应用于暗黑主题激活时。"
"Dark mode colors": "暗黑模式颜色" "Dark mode colors": "暗黑模式颜色"
"With categories": "有类别" "With categories": "有类别"
"Custom categories": "自定义类别"
"Customize application categories": "自定义应用程序类别"
"Apps only visible in the top menu": "应用程序仅在顶部菜单中可见"
"Apps visible in the top and side menus": "顶部和侧边菜单中可见的应用程序"
"Reset to default": "重置为默认设置"
"Hidden icon": "隐藏图标"
"Small icon": "小图标"
"Normal icon": "正常图标"
"Big icon": "大图标"
"Hidden text": "隐藏文字"
"Small text": "小文本"
"Normal text": "普通文本"
"Big text": "大文本"
+1 -1
View File
@@ -8,7 +8,7 @@
<?php endforeach; ?> <?php endforeach; ?>
} }
<?php if (empty($_['top-menu-apps']) && empty($_['top-side-menu-apps'])): ?> <?php if (empty($_['top-menu-apps'])): ?>
#appmenu { #appmenu {
display: none; display: none;
} }
+17 -29
View File
@@ -1,19 +1,21 @@
const alwaysDisplayed = function() { var alwaysDisplayed = function() {
const elements = querySelectorAll('*') var elements = document.querySelectorAll('*');
const fixedElements = [] var 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
} }
const position = window.getComputedStyle(element, null).getPropertyValue('position') var position = window.getComputedStyle(element, null).getPropertyValue('position');
if (position !== 'fixed') { if (position !== 'fixed') {
continue continue
} }
const id = element.getAttribute('id') var 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
@@ -23,21 +25,7 @@ const alwaysDisplayed = function() {
continue continue
} }
let elementIsInSideMenu = false if (jQuery(element).parents('#side-menu').length) {
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
} }
@@ -45,19 +33,19 @@ const alwaysDisplayed = function() {
} }
for (var i in fixedElements) { for (var i in fixedElements) {
const element = fixedElements[i] var element = fixedElements[i]
const computedStyle = window.getComputedStyle(element, null) var computedStyle = window.getComputedStyle(element, null)
const left = computedStyle.getPropertyValue('left') var left = computedStyle.getPropertyValue('left')
const right = computedStyle.getPropertyValue('right') var right = computedStyle.getPropertyValue('right')
if (right !== '0px') { if (right !== '0px') {
const intValue = parseInt(left.replace('px', '')) + 50 var intValue = parseInt(left.replace('px', ''))
element.style.setProperty('transform', 'translateX(' + intValue.toString() + 'px)') element.style.setProperty('transform', 'translateX(' + (intValue + 50) + 'px)')
} }
} }
} }
const content = querySelector('#content') let content = document.getElementById('content')
if (content && content.classList.contains('app-settings')) { if (content && content.classList.contains('app-settings')) {
let loaded = false let loaded = false
@@ -68,7 +56,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')
+9 -8
View File
@@ -1,14 +1,15 @@
let pageLoader = createElement('div', {id: 'side-menu-loader'}) var pageLoader = jQuery('<div id="side-menu-loader">')
let pageLoaderBar = createElement('div', {id: 'side-menu-loader-bar'}) var pageLoaderBar = jQuery('<div id="side-menu-loader-bar">')
pageLoader.appendChild(pageLoaderBar) body.append(pageLoader)
querySelector('body').appendChild(pageLoader) pageLoader.append(pageLoaderBar)
let pageLoaderValue = 0 var 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)
}) })
+97 -141
View File
@@ -1,91 +1,60 @@
let menuCache = null var menuCache = null
const breakpointMobileWidth = 1024 var updateTopMenu = function() {
const usePercentualAppMenuLimit = 0.8 var breakpointMobileWidth = 1024
const minAppsDesktop = 8 var menu = jQuery('#appmenu')
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
const handleMenuClick = (e, icon) => { var currentMenuCache = menu.html() + menu.next().html()
let element = e.target
while (element.tagName !== 'LI') { if (currentMenuCache === menuCache) {
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
} }
navigationAppsHtml = '' navigationApps.html('')
for (let app of apps) { apps.each(function(i, app) {
const dataId = app.getAttribute('data-id') var dataId = app.getAttribute('data-id')
if (dataId === null) { if (dataId === null) {
continue return
} }
if (topMenuApps.indexOf(dataId) === -1 && topSideMenuApps.indexOf(dataId) === -1) { if (topMenuApps.indexOf(dataId) === -1) {
app.classList.add('hidden') app.classList.add('hidden')
app.classList.add('app-hidden') app.classList.add('app-hidden')
} else { } else {
app.classList.remove('hidden') app.classList.remove('hidden')
app.classList.add('app-external-site') app.classList.add('app-external-site')
if (topSideMenuApps.indexOf(dataId) !== -1) {
app.classList.add('app-top-side-menu')
}
appShown.push(app) appShown.push(app)
navigationApps.append(app.outerHTML)
navigationAppsHtml = navigationAppsHtml + app.outerHTML
} }
if (targetBlankApps.indexOf(dataId) !== -1) { if (targetBlankApps.indexOf(dataId) !== -1) {
querySelector('a', app).setAttribute('target', '_blank') jQuery(app).children('a').attr('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
} }
navigationApps.innerHTML = navigationAppsHtml appCount = Math.floor(availableWidth / jQuery('#appmenu li').width())
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
@@ -93,124 +62,111 @@ const updateTopMenu = function() {
appCount = minAppsDesktop appCount = minAppsDesktop
} }
menu.style.opacity = 1 if (appCount === 0) {
menu.addClass('hidden')
}
menu.removeClass('hidden')
menu.css('opacity', 1)
if (appShown.length - 1 - appCount >= 1) { if (appShown.length - 1 - appCount >= 1) {
appCount-- appCount--
} }
for (let item of querySelectorAll('a', moreApps)) { moreApps.find('a').removeClass('active')
item.classList.remove('active')
}
let k = 0 var k = 0
let notInHeader = 0 var notInHeader = 0
var name
for (let app of appShown) { jQuery(appShown).each(function(i, app) {
const name = app.getAttribute('data-id') app = jQuery(app)
const li = querySelector('#apps li[data-id=' + name + '].app-external-site') name = app.data('id')
if (k < appCount && appCount > 0) { if (k < appCount && appCount > 0) {
app.classList.remove('hidden') app.removeClass('hidden')
li.classList.add('in-header')
lastShownApp = app lastShownApp = app
} else {
app.classList.add('hidden')
li.classList.remove('in-header')
jQuery('#apps li[data-id=' + name + '].app-external-site').addClass('in-header')
} else {
app.addClass('hidden')
notInHeader++ notInHeader++
const a = querySelector('a', app) jQuery('#apps li[data-id=' + name + '].app-external-site').removeClass('in-header')
if (appCount > 0 && a.classList.contains('active')) { if (appCount > 0 && app.children('a').hasClass('active')) {
lastShownApp.classList.add('hidden') lastShownApp.addClass('hidden')
app.classList.remove('hidden') app.removeClass('hidden')
notInHeader++ notInHeader++
li.classList.add('in-header') jQuery('#apps li[data-id=' + name + '].app-external-site')
.removeClass('in-header')
.addClass('in-header')
} }
} }
k++ k++
} })
// Hack for: // Hack for https://github.com/nextcloud/server/blob/23b0b63c213f5b31eecae817ffd4a9e26f6624d0/core/src/components/MainMenu.js#L74-L96
// - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119 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) {
jQuery(menu).undelegate('li:not(#more-apps) > a', 'click') var a = $(e.target)
jQuery(navigation).undelegate('a', 'click')
const confs = [ if (!a.is('a')) {
{ 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)
})
} }
}
for (let app of querySelectorAll('#apps li.app-external-site')) { if (a.attr('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey && a.parent('#more-apps').length === 0) {
const appId = app.getAttribute('data-id') a.find('svg').remove()
a.find('div').remove()
a.prepend(jQuery('<div/>').addClass(
OCA.Theming && OCA.Theming.inverted
? 'icon-loading-small'
: 'icon-loading-small-dark'
))
if (app.classList.contains('in-header')) { window.location.href = a.attr('href')
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 {
const svg = querySelector('svg', app) var svg = app.find('svg');
if (querySelectorAll('svg defs', app).length > 0) { if (svg.find('defs').length > 0) {
continue return;
} }
const defs = ` var 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.innerHTML = defs + svg.innerHTML svg.prepend(defs)
svg.find('image').attr('filter', `url(#invertMenuMore-${appId})`)
for (let image of querySelectorAll('image', svg)) { var html = svg.get(0).innerHTML.replace(/fecolormatrix/g, 'feColorMatrix');
image.setAttribute('filter', `url(#invertMenuMore-${appId})`)
}
svg.innerHTML = svg.innerHTML.replace(/fecolormatrix/g, 'feColorMatrix') svg.html(html)
} }
} })
if (notInHeader === 0) { if (notInHeader === 0) {
moreApps.style.display = 'none' moreApps.hide()
navigation.style.display = 'none' navigation.hide()
} else { } else {
moreApps.style.display = 'flex' moreApps.show()
} }
menuCache = menu.innerHTML + menu.nextSibling.innerHTML menuCache = menu.html() + menu.next().html()
} }
for (let i = 0; i < 4000; i+= 100) { setInterval(updateTopMenu, 50)
setTimeout(updateTopMenu, i)
}
let resizeTimeout = null;
window.addEventListener('resize', () => {
if (resizeTimeout !== null) {
clearTimeout(resizeTimeout)
}
resizeTimeout = setTimeout(updateTopMenu, 100)
})
+61 -117
View File
@@ -13,98 +13,63 @@ if ($_['always-displayed']) {
?> ?>
(function() { (function() {
const querySelector = function(selector, element) { var sideMenuContainer = jQuery('<div id="side-menu-container">')
if (element) { var sideMenuOpener = jQuery('<button class="side-menu-opener"></button>')
return element.querySelector(selector) var sideMenu = jQuery('<div id="side-menu">')
} var body = jQuery('body')
var html = jQuery('html')
return document.querySelector(selector) var isTouchDevice = window.matchMedia("(pointer: coarse)").matches
}
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.setAttribute('data-bigmenu', '1') sideMenu.attr('data-bigmenu', '1')
<?php elseif ($display === 'side-with-categories'): ?> <?php elseif ($display === 'side-with-categories'): ?>
sideMenu.setAttribute('data-sidewithcategories', '1') sideMenu.attr('data-sidewithcategories', '1')
<?php endif; ?> <?php endif; ?>
querySelector('body').addEventListener('side-menu.apps', (e) => { var targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>;
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']): ?>
const sideMenu = querySelector('#side-menu') sideMenu = jQuery('#side-menu')
if (apps.length === 0) { if (apps.length === 0) {
sideMenu.classList.remove('open') sideMenu.removeClass('open')
sideMenu.classList.add('hide') sideMenu.addClass('hide')
sideMenuOpener.classList.add('hide') sideMenuOpener.addClass('hide')
} else { } else {
sideMenu.classList.remove('hide') sideMenu.removeClass('hide')
sideMenuOpener.classList.remove('hide') sideMenuOpener.removeClass('hide')
} }
<?php if ($display === 'always-displayed'): ?> <?php if ($display === 'always-displayed'): ?>
if (apps.length === 0) { if (apps.length === 0) {
html.classList.remove('side-menu-always-displayed') html.removeClass('side-menu-always-displayed');
} else { } else {
html.classList.add('side-menu-always-displayed') html.addClass('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.classList.remove('side-menu-always-displayed') html.removeClass('side-menu-always-displayed');
} else { } else {
html.classList.add('side-menu-always-displayed') html.addClass('side-menu-always-displayed');
} }
<?php endif; ?> <?php endif; ?>
<?php endif; ?> <?php endif; ?>
}) })
body.addEventListener('side-menu.ready', () => { body.on('side-menu.ready', function() {
const sideMenu = querySelector('#side-menu') sideMenu = jQuery('#side-menu')
const headerMenuOpener = querySelector('#header .side-menu-opener')
const sideMenuOpener = querySelectorAll('#side-menu .side-menu-opener')
sideMenuFocus = () => { var headerMenuOpener = jQuery('#header .side-menu-opener')
let a = querySelector('.side-menu-app.active a', sideMenu) var sideMenuOpener = jQuery('#side-menu .side-menu-opener')
if (!a) { sideMenuFocus = function() {
return var a = sideMenu.find('.side-menu-app.active a')
}
if (a.length === 0) { if (a.length === 0) {
a = querySelector('.side-menu-app:first-child a', sideMenu) a = sideMenu.find('.side-menu-app:first-child a')
} }
if (a.length > 0) { if (a.length > 0) {
@@ -112,100 +77,79 @@ if ($_['always-displayed']) {
} }
} }
<?php if ($_['opener-hover']): ?> <?php if ($_['opener-hover'] || $display === 'always-displayed'): ?>
const sideMenuMouseLeave = () => { var sideMenuMouseLeave = function() {
sideMenu.classList.remove('open') sideMenu
sideMenu.removeEventListener('mouseleave', sideMenuMouseLeave) .removeClass('open')
.off('mouseleave', sideMenuMouseLeave)
} }
const sideMenuMouseEnter = () => { var sideMenuMouseEnter = function() {
sideMenu.addEventListener('mouseleave', sideMenuMouseLeave) sideMenu.on('mouseleave', sideMenuMouseLeave)
} }
const sideMenuOpenerMouseEnter = () => { var sideMenuOpenerMouseEnter = function() {
sideMenu.classList.add('open') sideMenu
sideMenu.addEventListener('mouseenter', sideMenuMouseEnter) .addClass('open')
.on('mouseenter', sideMenuMouseEnter)
sideMenuFocus() sideMenuFocus()
} }
if (!isTouchDevice) { if (!isTouchDevice) {
<?php if ($_['opener-hover']): ?> <?php if ($_['opener-hover']): ?>
headerMenuOpener.addEventListener('mouseenter', sideMenuOpenerMouseEnter) headerMenuOpener.on('mouseenter', sideMenuOpenerMouseEnter)
sideMenu.classList.add('hide-opener') sideMenu.addClass('hide-opener')
<?php endif ?> <?php endif ?>
sideMenu.addEventListener('mouseleave', sideMenuMouseLeave) sideMenu.on('mouseleave', sideMenuMouseLeave)
sideMenu.addEventListener('mouseenter', sideMenuOpenerMouseEnter) sideMenu.on('mouseenter', sideMenuOpenerMouseEnter)
} }
<?php endif; ?> <?php endif; ?>
headerMenuOpener.addEventListener('click', () => { headerMenuOpener.on('click', function() {
sideMenu.classList.add('open') sideMenu.addClass('open')
sideMenu.find('.side-menu-app.active a').focus()
const a = querySelector('.side-menu-app.active a', sideMenu)
if (a !== null) {
a.focus()
}
headerMenuOpener.blur()
}) })
for (let opener of sideMenuOpener) { <?php if ($display === 'always-displayed'): ?>
opener.addEventListener('click', () => { sideMenuOpener.on('click', function() {
<?php if ($display === 'always-displayed'): ?> sideMenu.toggleClass('open')
sideMenu.classList.toggle('open')
<?php else: ?>
sideMenu.classList.remove('open')
<?php endif; ?>
}) })
} <?php else: ?>
sideMenuOpener.on('click', function() {
sideMenu.removeClass('open')
})
<?php endif; ?>
document.addEventListener('keydown', (e) => { jQuery(document).keydown(function(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.classList.toggle('open') sideMenu.toggleClass('open')
sideMenuFocus() sideMenuFocus()
} }
}) })
const sideMenuObserver = new MutationObserver((e) => {
if (body.getAttribute('id') !== 'body-settings') {
return
}
body.classList.toggle('body-settings-side-menu', sideMenu.classList.contains('open'))
})
sideMenuObserver.observe(sideMenu, {
attributes: true,
attributeFilter: ['class'],
childList: false,
characterData: false
})
}) })
body.appendChild(sideMenuContainer) body.append(sideMenuContainer)
sideMenuContainer.appendChild(sideMenu) sideMenuContainer.append(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'): ?>
nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud) sideMenuOpener.insertBefore('#nextcloud')
<?php else: ?> <?php else: ?>
nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud.nextSibling) sideMenuOpener.insertAfter('#nextcloud')
<?php endif; ?> <?php endif; ?>
<?php if (!empty($_['top-menu-apps']) || !empty($_['top-side-menu-apps'])): ?> <?php if (!empty($_['top-menu-apps'])): ?>
const topMenuApps = <?php echo json_encode($_['top-menu-apps']), "\n"; ?> var topMenuApps = <?php echo json_encode($_['top-menu-apps']); ?>;
const topSideMenuApps = <?php echo json_encode($_['top-side-menu-apps']); ?>
<?php require_once __DIR__.'/_topMenuApps.js'; ?> <?php require_once __DIR__.'/_topMenuApps.js'; ?>
<?php endif; ?> <?php endif; ?>
+8 -131
View File
@@ -20,7 +20,6 @@ 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');
@@ -40,6 +39,7 @@ $choicesSizes = [
]; ];
?> ?>
<div id="side-menu-section"> <div id="side-menu-section">
<div class="section"> <div class="section">
<h2> <h2>
@@ -67,10 +67,6 @@ $choicesSizes = [
class="side-menu-setting side-menu-setting-live" class="side-menu-setting side-menu-setting-live"
value="<?php print_unescaped($_['background-color-to']); ?>"> value="<?php print_unescaped($_['background-color-to']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-background-color' => $_['defaults']['background-color'],
'side-menu-background-color-to' => $_['defaults']['background-color-to'],
])) ?>"></div>
<div> <div>
<em> <em>
<?php p($l->t('Transparent')); ?> <?php p($l->t('Transparent')); ?>
@@ -106,10 +102,6 @@ $choicesSizes = [
type="color" type="color"
class="side-menu-setting side-menu-setting-live" class="side-menu-setting side-menu-setting-live"
value="<?php print_unescaped($_['current-app-background-color']); ?>"> value="<?php print_unescaped($_['current-app-background-color']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-current-app-background-color' => $_['defaults']['current-app-background-color'],
])) ?>"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -126,10 +118,6 @@ $choicesSizes = [
type="color" type="color"
class="side-menu-setting side-menu-setting-live" class="side-menu-setting side-menu-setting-live"
value="<?php print_unescaped($_['text-color']); ?>"> value="<?php print_unescaped($_['text-color']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-text-color' => $_['defaults']['text-color'],
])) ?>"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -146,10 +134,6 @@ $choicesSizes = [
type="color" type="color"
class="side-menu-setting" class="side-menu-setting"
value="<?php print_unescaped($_['loader-color']); ?>"> value="<?php print_unescaped($_['loader-color']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-loader-color' => $_['defaults']['loader-color'],
])) ?>"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -243,23 +227,16 @@ $choicesSizes = [
</div> </div>
<div class="side-menu-setting-form side-menu-setting-form-long"> <div class="side-menu-setting-form side-menu-setting-form-long">
<input <input
id="side-menu-dark-mode-background-color"
name="dark-mode-background-color" name="dark-mode-background-color"
type="color" type="color"
class="side-menu-setting" class="side-menu-setting"
value="<?php print_unescaped($_['dark-mode-background-color']); ?>"> value="<?php print_unescaped($_['dark-mode-background-color']); ?>">
<input <input
id="side-menu-dark-mode-background-color-to"
name="dark-mode-background-color-to" name="dark-mode-background-color-to"
type="color" type="color"
class="side-menu-setting" class="side-menu-setting"
value="<?php print_unescaped($_['dark-mode-background-color-to']); ?>"> value="<?php print_unescaped($_['dark-mode-background-color-to']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-dark-mode-background-color' => $_['defaults']['dark-mode-background-color'],
'side-menu-dark-mode-background-color-to' => $_['defaults']['dark-mode-background-color-to'],
])) ?>"></div>
<div> <div>
<em> <em>
<?php p($l->t('Transparent')); ?> <?php p($l->t('Transparent')); ?>
@@ -289,15 +266,10 @@ $choicesSizes = [
</div> </div>
<div class="side-menu-setting-form side-menu-setting-form-long"> <div class="side-menu-setting-form side-menu-setting-form-long">
<input <input
id="side-menu-dark-mode-current-app-background-color"
name="dark-mode-current-app-background-color" name="dark-mode-current-app-background-color"
type="color" type="color"
class="side-menu-setting" class="side-menu-setting"
value="<?php print_unescaped($_['dark-mode-current-app-background-color']); ?>"> value="<?php print_unescaped($_['dark-mode-current-app-background-color']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-dark-mode-current-app-background-color' => $_['defaults']['dark-mode-current-app-background-color'],
])) ?>"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -309,15 +281,10 @@ $choicesSizes = [
</div> </div>
<div class="side-menu-setting-form side-menu-setting-form-long"> <div class="side-menu-setting-form side-menu-setting-form-long">
<input <input
id="side-menu-dark-mode-text-color"
name="dark-mode-text-color" name="dark-mode-text-color"
type="color" type="color"
class="side-menu-setting" class="side-menu-setting"
value="<?php print_unescaped($_['dark-mode-text-color']); ?>"> value="<?php print_unescaped($_['dark-mode-text-color']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-dark-mode-text-color' => $_['defaults']['dark-mode-text-color'],
])) ?>"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -329,15 +296,10 @@ $choicesSizes = [
</div> </div>
<div class="side-menu-setting-form side-menu-setting-form-long"> <div class="side-menu-setting-form side-menu-setting-form-long">
<input <input
id="side-menu-dark-mode-loader-color"
name="dark-mode-loader-color" name="dark-mode-loader-color"
type="color" type="color"
class="side-menu-setting" class="side-menu-setting"
value="<?php print_unescaped($_['dark-mode-loader-color']); ?>"> value="<?php print_unescaped($_['dark-mode-loader-color']); ?>">
<div class="theme-undo icon icon-history btn-reset" data-toggle="tooltip" data-original-title="<?php echo p($l->t('Reset to default')); ?>" data-reset="<?php echo htmlentities(json_encode([
'side-menu-dark-mode-loader-color' => $_['defaults']['dark-mode-loader-color'],
])) ?>"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -535,6 +497,7 @@ $choicesSizes = [
<div> <div>
<label for="side-menu-opener"> <label for="side-menu-opener">
<?php p($l->t('Always displayed')); ?> <?php p($l->t('Always displayed')); ?>
<small><span class="warning"><?php p($l->t('Experimental')); ?></span></small>
</label> </label>
</div> </div>
<p><em><?php p($l->t('Not compatible with touch screens.')); ?></em></p> <p><em><?php p($l->t('Not compatible with touch screens.')); ?></em></p>
@@ -697,7 +660,7 @@ $choicesSizes = [
<select id="side-menu-size-icon" name="size-icon" class="side-menu-setting"> <select id="side-menu-size-icon" name="size-icon" class="side-menu-setting">
<?php foreach ($choicesSizes as $label => $value): ?> <?php foreach ($choicesSizes as $label => $value): ?>
<option value="<?php echo $value ?>" <?php if ($value === $_['size-icon']): ?>selected<?php endif; ?>> <option value="<?php echo $value ?>" <?php if ($value === $_['size-icon']): ?>selected<?php endif; ?>>
<?php echo $l->t($label.' icon'); ?> <?php echo $l->t($label); ?> icon
</option> </option>
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
@@ -705,7 +668,7 @@ $choicesSizes = [
<select id="side-menu-size-text" name="size-text" class="side-menu-setting"> <select id="side-menu-size-text" name="size-text" class="side-menu-setting">
<?php foreach ($choicesSizes as $label => $value): ?> <?php foreach ($choicesSizes as $label => $value): ?>
<option value="<?php echo $value ?>" <?php if ($value === $_['size-text']): ?>selected<?php endif; ?>> <option value="<?php echo $value ?>" <?php if ($value === $_['size-text']): ?>selected<?php endif; ?>>
<?php echo $l->t($label.' text'); ?> <?php echo $l->t($label); ?> text
</option> </option>
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
@@ -768,7 +731,7 @@ $choicesSizes = [
<div class="side-menu-setting-table"> <div class="side-menu-setting-table">
<div class="side-menu-setting-row"> <div class="side-menu-setting-row">
<div class="side-menu-setting-label"> <div class="side-menu-setting-label">
<?php p($l->t('Apps only visible in the top menu')); ?> <?php p($l->t('Apps that not must be moved in the side menu')); ?>
</div> </div>
<div class="side-menu-setting-form"> <div class="side-menu-setting-form">
<a class="side-menu-toggler" data-target="#top-menu-apps" href="#_"> <a class="side-menu-toggler" data-target="#top-menu-apps" href="#_">
@@ -797,39 +760,6 @@ $choicesSizes = [
</div> </div>
</div> </div>
</div> </div>
<div class="side-menu-setting-table">
<div class="side-menu-setting-row">
<div class="side-menu-setting-label">
<?php p($l->t('Apps visible in the top and side menus')); ?>
</div>
<div class="side-menu-setting-form">
<a class="side-menu-toggler" data-target="#top-side-menu-apps" href="#_">
🖱️ <?php p($l->t('Show and hide the list of applications')); ?>
</a>
<div class="side-menu-setting" data-name="top-side-menu-apps" id="top-side-menu-apps" data-checkbox style="display: none">
<ul class="side-menu-setting-list">
<?php foreach ($_['apps'] as $app): ?>
<li class="side-menu-setting-list-item">
<input
type="checkbox"
name="top-side-menu-apps[]"
value="<?php echo $app['id'] ?>"
id="top-side-menu-app-<?php echo $app['id'] ?>"
<?php if (in_array($app['id'], $_['top-side-menu-apps'])): ?>checked<?php endif; ?>
/>
<label for="top-side-menu-app-<?php echo $app['id'] ?>">
<?php echo p($l->t($app['name'])); ?>
</label>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
</div> </div>
@@ -860,60 +790,6 @@ $choicesSizes = [
</div> </div>
</div> </div>
<div class="side-menu-setting-row">
<div class="side-menu-setting-label">
<?php p($l->t('Custom categories')); ?>
</div>
<div class="side-menu-setting-form">
<input type="hidden" name="categories-custom" class="side-menu-setting" data-langs="<?php echo htmlentities(json_encode($langs)) ?>" value="<?php echo htmlentities(json_encode($_['categories-custom'])) ?>">
<div id="side-menu-categories-custom">
</div>
</div>
</div>
<div class="side-menu-setting-row">
<div class="side-menu-setting-label">
<?php p($l->t('Customize application categories')); ?>
</div>
<div class="side-menu-setting-form">
<a class="side-menu-toggler" data-target="#apps-categories-custom-list" href="#_">
🖱️ <?php p($l->t('Show and hide the list of applications')); ?>
</a>
<div id="apps-categories-custom-list" style="display: none">
<ul class="side-menu-setting-list">
<?php foreach ($_['apps'] as $app): ?>
<li class="side-menu-setting-list-item">
<label for="apps-categories-custom-<?php echo $app['id'] ?>">
<?php echo p($l->t($app['name'])); ?>
</label>
<br>
<select data-app="<?php echo $app['id'] ?>" class="apps-categories-custom">
<option value=""></option>
<?php foreach ($_['categories'] as $id => $category): ?>
<?php if ($category): ?>
<option
value="<?php echo $id ?>"
<?php if (($_['apps-categories-custom'][$app['id']] ?? '') === $id): ?>
selected
<?php endif; ?>
><?php echo $category ?></option>
<?php endif; ?>
<?php endforeach; ?>
</select>
</li>
<?php endforeach; ?>
</ul>
</div>
<input type="hidden" class="side-menu-setting" id="apps-categories-custom" name="apps-categories-custom" value="<?php echo htmlentities(json_encode($_['apps-categories-custom'])) ?>">
</div>
</div>
<div class="side-menu-setting-row"> <div class="side-menu-setting-row">
<div class="side-menu-setting-label"> <div class="side-menu-setting-label">
<?php p($l->t('Customize sorting')); ?> <?php p($l->t('Customize sorting')); ?>
@@ -923,7 +799,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 id="categories-list" style="display: none"> <div class="side-menu-setting" data-name="categories" 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">
@@ -994,9 +870,10 @@ $choicesSizes = [
<div class="section" id="more"> <div class="section" id="more">
<button id="side-menu-save" class="btn btn-info"> <button id="side-menu-save" class="btn btn-info">
<?php p($l->t('Save')); ?> <?php p($l->t('Save')); ?>
<progress max="100" value="0" id="side-menu-save-progress"></progress>
</button> </button>
<span id="side-menu-message" class="msg"></span>
<a href="<?php echo $urlGenerator->linkToRoute('side_menu.AdminSetting.exportConfiguration') ?>" target="_blank"> <a href="<?php echo $urlGenerator->linkToRoute('side_menu.AdminSetting.exportConfiguration') ?>" target="_blank">
<button class="btn btn-primary" > <button class="btn btn-primary" >
<?php p($l->t('Export the configuration')); ?> <?php p($l->t('Export the configuration')); ?>
+90 -139
View File
@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
vendor_script('side_menu', 'html5sortable.min');
script('side_menu', 'admin'); script('side_menu', 'admin');
style('side_menu', 'admin'); style('side_menu', 'admin');
@@ -26,6 +25,8 @@ $choicesYesNo = [
]; ];
?> ?>
<div id="side-menu-section"> <div id="side-menu-section">
<?php if ($_['force']): ?> <?php if ($_['force']): ?>
<div class="section"> <div class="section">
@@ -43,73 +44,71 @@ $choicesYesNo = [
<?php p($l->t('Menu')); ?> <?php p($l->t('Menu')); ?>
</h2> </h2>
<div>
<label for="side-menu-enabled">
<?php p($l->t('Enable the custom menu')); ?>
</label>
</div>
<p> <p>
<em><?php echo $l->t('Use the shortcut <span class="keyboard-key">Ctrl</span>+<span class="keyboard-key">o</span> to open and to hide the side menu. Use <span class="keyboard-key">tab</span> to navigate.'); ?></em> <em><?php echo $l->t('Use the shortcut <span class="keyboard-key">Ctrl</span>+<span class="keyboard-key">o</span> to open and to hide the side menu. Use <span class="keyboard-key">tab</span> to navigate.'); ?></em>
</p> </p>
<div class="side-menu-setting-table"> <div>
<div class="side-menu-setting-row"> <select id="side-menu-enabled" name="enabled" class="side-menu-setting" data-personal>
<div class="side-menu-setting-label"> <?php foreach ($choicesYesNo as $label => $value): ?>
<?php p($l->t('Enable the custom menu')); ?> <option value="<?php echo $value ?>" <?php if ($value === $_['enabled']): ?>selected<?php endif; ?>>
</div> <?php echo $l->t($label); ?>
<div class="side-menu-setting-form"> </option>
<select id="side-menu-enabled" name="enabled" class="side-menu-setting" data-personal> <?php endforeach; ?>
<?php foreach ($choicesYesNo as $label => $value): ?> </select>
<option value="<?php echo $value ?>" <?php if ($value === $_['enabled']): ?>selected<?php endif; ?>>
<?php echo $l->t($label); ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
</div> </div>
<div class="side-menu-setting-table"> <div>
<div class="side-menu-setting-row"> <label for="side-menu-target-blank">
<div class="side-menu-setting-label"> <?php p($l->t('Open apps in new tab')); ?>
<?php p($l->t('Open apps in new tab')); ?> </label>
</div>
<div>
<?php $choices = [
'Use the global setting' => '1',
'Use my selection' => '2',
]; ?>
<select id="side-menu-loader-enabled" name="target-blank-mode" class="side-menu-setting" data-personal>
<?php foreach ($choices as $label => $value): ?>
<option value="<?php echo $value ?>" <?php if ($value === $_['target-blank-mode']): ?>selected<?php endif; ?>>
<?php echo $l->t($label); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<p>
<a class="side-menu-toggler" data-target="#target-blank-apps" href="#_">
🖱️ <?php p($l->t('Show and hide the list of applications')); ?>
</a>
</p>
<div class="side-menu-setting" data-name="target-blank-apps" id="target-blank-apps" data-personal data-checkbox style="display: none">
<?php foreach ($_['apps'] as $app): ?>
<div>
<input
type="checkbox"
name="target-blank-apps[]"
value="<?php echo $app['id'] ?>"
id="target-blank-app-<?php echo $app['id'] ?>"
<?php if (in_array($app['id'], $_['target-blank-apps'])): ?>checked<?php endif; ?>
/>
<label for="target-blank-app-<?php echo $app['id'] ?>">
<?php echo p($l->t($app['name'])); ?>
</label>
</div> </div>
<div class="side-menu-setting-form"> <?php endforeach; ?>
<?php $choices = [
'Use the global setting' => '1',
'Use my selection' => '2',
]; ?>
<select id="side-menu-loader-enabled" name="target-blank-mode" class="side-menu-setting" data-personal>
<?php foreach ($choices as $label => $value): ?>
<option value="<?php echo $value ?>" <?php if ($value === $_['target-blank-mode']): ?>selected<?php endif; ?>>
<?php echo $l->t($label); ?>
</option>
<?php endforeach; ?>
</select>
<p>
<a class="side-menu-toggler" data-target="#target-blank-apps" href="#_">
🖱️ <?php p($l->t('Show and hide the list of applications')); ?>
</a>
</p>
<div class="side-menu-setting" data-name="target-blank-apps" id="target-blank-apps" data-personal data-checkbox style="display: none">
<ul class="side-menu-setting-list">
<?php foreach ($_['apps'] as $app): ?>
<li class="side-menu-setting-list-item">
<input
type="checkbox"
name="target-blank-apps[]"
value="<?php echo $app['id'] ?>"
id="target-blank-app-<?php echo $app['id'] ?>"
<?php if (in_array($app['id'], $_['target-blank-apps'])): ?>checked<?php endif; ?>
/>
<label for="target-blank-app-<?php echo $app['id'] ?>">
<?php echo p($l->t($app['name'])); ?>
</label>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div> </div>
</div> </div>
@@ -117,95 +116,47 @@ $choicesYesNo = [
<h2> <h2>
<?php p($l->t('Top menu')); ?> <?php p($l->t('Top menu')); ?>
</h2> </h2>
<div>
<div class="side-menu-setting-table"> <label for="side-menu-top-menu-apps">
<div class="side-menu-setting-row"> <?php p($l->t('Apps that not must be moved in the side menu')); ?>
<div class="side-menu-setting-label"> </label>
<?php p($l->t('Apps only visible in the top menu')); ?>
<p>
<em>
<?php p($l->t('If there is no selection then the global configuration is applied.')); ?>
</em>
</p>
</div>
<div class="side-menu-setting-form">
<p>
<a class="side-menu-toggler" data-target="#top-menu-apps" href="#_">
🖱️ <?php p($l->t('Show and hide the list of applications')); ?>
</a>
</p>
<div class="side-menu-setting" data-name="top-menu-apps" data-checkbox data-personal id="top-menu-apps" style="display: none">
<ul class="side-menu-setting-list">
<?php foreach ($_['apps'] as $app): ?>
<li class="side-menu-setting-list-item">
<input
type="checkbox"
name="top-menu-apps[]"
value="<?php echo $app['id'] ?>"
id="top-menu-app-<?php echo $app['id'] ?>"
<?php if (in_array($app['id'], $_['top-menu-apps'])): ?>checked<?php endif; ?>
/>
<label for="top-menu-app-<?php echo $app['id'] ?>">
<?php echo $app['name'] ?>
</label>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div> </div>
<div class="side-menu-setting-table"> <p>
<div class="side-menu-setting-row"> <em>
<div class="side-menu-setting-label"> <?php p($l->t('If there is no selection then the global configuration is applied.')); ?>
<?php p($l->t('Apps visible in the top and side menus')); ?> </em>
<p> </p>
<em>
<?php p($l->t('If there is no selection then the global configuration is applied.')); ?>
</em>
</p>
</div>
<div class="side-menu-setting-form">
<p>
<a class="side-menu-toggler" data-target="#top-side-menu-apps" href="#_">
🖱️ <?php p($l->t('Show and hide the list of applications')); ?>
</a>
</p>
<div class="side-menu-setting" data-name="top-side-menu-apps" data-checkbox data-personal id="top-side-menu-apps" style="display: none"> <p>
<ul class="side-menu-setting-list"> <a class="side-menu-toggler" data-target="#top-menu-apps" href="#_">
<?php foreach ($_['apps'] as $app): ?> 🖱️ <?php p($l->t('Show and hide the list of applications')); ?>
<li class="side-menu-setting-list-item"> </a>
<input </p>
type="checkbox"
name="top-side-menu-apps[]"
value="<?php echo $app['id'] ?>"
id="top-side-menu-app-<?php echo $app['id'] ?>"
<?php if (in_array($app['id'], $_['top-side-menu-apps'])): ?>checked<?php endif; ?>
/>
<label for="top-side-menu-app-<?php echo $app['id'] ?>"> <div class="side-menu-setting" data-name="top-menu-apps" data-checkbox data-personal id="top-menu-apps" style="display: none">
<?php echo $app['name'] ?> <?php foreach ($_['apps'] as $app): ?>
</label> <div>
</li> <input
<?php endforeach; ?> type="checkbox"
</ul> name="top-menu-apps[]"
</div> value="<?php echo $app['id'] ?>"
id="top-menu-app-<?php echo $app['id'] ?>"
<?php if (in_array($app['id'], $_['top-menu-apps'])): ?>checked<?php endif; ?>
/>
<label for="top-menu-app-<?php echo $app['id'] ?>">
<?php echo $app['name'] ?>
</label>
</div> </div>
</div> <?php endforeach; ?>
</div> </div>
</div> </div>
<?php endif ?> <?php endif ?>
<div class="section"> <div class="section">
<?php if (!$_['force']): ?> <?php if (!$_['force']): ?>
<button id="side-menu-save" class="btn btn-info"> <button id="side-menu-save" class="btn btn-primary"><?php p($l->t('Save')); ?></button>
<?php p($l->t('Save')); ?>
<progress max="100" value="0" id="side-menu-save-progress"></progress>
</button>
<span id="side-menu-message" class="msg"></span> <span id="side-menu-message" class="msg"></span>
-2
View File
File diff suppressed because one or more lines are too long