Compare commits

..

118 Commits

Author SHA1 Message Date
Simon Vieille 92e1857ae8 Merge pull request 'fix issue #96' (#97) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/97
2022-03-15 11:14:40 +01:00
Simon Vieille c0b1701744 release v2.3.4 2022-03-15 10:56:05 +01:00
Simon Vieille ee98a49366 fix blank line when settings are open 2022-03-15 10:51:40 +01:00
Simon Vieille b4951b6cf1 Merge pull request 'develop' (#94) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/94
2022-02-07 14:35:05 +01:00
Simon Vieille a67688e779 release v2.3.3 2022-02-07 14:30:08 +01:00
Simon Vieille 9afde0dc9d update changelog 2022-02-07 14:29:51 +01:00
Simon Vieille 0f73ad42c4 fix SQL Exception InvalidFieldNameException (#93) 2022-02-07 14:28:34 +01:00
Simon Vieille 007ac2bb8e hide the scrollbar when mouse is out (menu always displayed) 2022-02-07 14:21:29 +01:00
Simon Vieille 4e21020600 Merge pull request 'develop' (#92) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/92
2022-01-14 17:03:28 +01:00
Simon Vieille 8c5b0e9834 update ci/cd conf 2022-01-14 16:52:36 +01:00
Simon Vieille 59e3b6b85e update ci/cd conf 2022-01-14 16:50:15 +01:00
Simon Vieille a913bd5ba2 update ci/cd conf 2022-01-14 16:49:14 +01:00
Simon Vieille 2d32e542cb update ci/cd conf 2022-01-14 16:46:47 +01:00
Simon Vieille 5d03fbaa49 update ci/cd conf 2022-01-14 16:44:54 +01:00
Simon Vieille 22011cb681 Merge pull request 'update the ci/cd config and screenshots' (#91) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/91
2022-01-13 00:47:43 +01:00
Simon Vieille 015493fc08 update ci/cd conf 2022-01-13 00:16:56 +01:00
Simon Vieille 992e54ac30 update ci/cd conf 2022-01-13 00:15:20 +01:00
Simon Vieille 67dfb7e833 update screenshots 2022-01-12 14:54:41 +01:00
Simon Vieille 1e68d6877d Merge pull request 'Quick fix' (#90) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/90
2022-01-12 14:13:08 +01:00
Simon Vieille 2ae08f7b77 release v2.3.2 2022-01-12 14:12:17 +01:00
Simon Vieille 489321081a fix hidden menu 2022-01-12 14:11:38 +01:00
Simon Vieille 68123ed45c Merge pull request 'Quick fix (#88)' (#89) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/89
2022-01-12 13:32:29 +01:00
Simon Vieille 66a1528341 release v2.3.1 2022-01-12 13:30:43 +01:00
Simon Vieille 64b7f3f534 fix #88 2022-01-12 13:29:44 +01:00
Simon Vieille fef936bef0 Merge pull request 'Issues #82 #83' (#87) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/87
2022-01-12 12:53:54 +01:00
Simon Vieille 715dae6ab4 release v2.3.0 2022-01-12 12:51:29 +01:00
Simon Vieille e2a9fecac9 fix typo 2022-01-12 12:48:50 +01:00
Simon Vieille e2d17022f9 fix incorrect html label 2022-01-12 12:46:41 +01:00
Simon Vieille 29d79ad589 update changelog 2022-01-12 12:43:11 +01:00
Simon Vieille 5a4294fad4 Merge branch 'feature/issue82' into develop 2022-01-12 12:41:29 +01:00
Simon Vieille d34b41ba94 add option to keep an app in the top and side menu 2022-01-12 12:40:17 +01:00
Simon Vieille a6016552c9 update changelog and readme 2022-01-12 11:44:45 +01:00
Simon Vieille 50c65811a6 add auto-reload when settings are saved 2022-01-11 22:23:13 +01:00
Simon Vieille f64436f0a3 Merge branch 'feature/issue83' into develop 2022-01-11 20:20:51 +01:00
Simon Vieille 34b1c2809b fix issue with custom categories and add experimental notice 2022-01-11 20:20:44 +01:00
Simon Vieille 5d9dc804f8 add bigger select 2022-01-11 20:02:02 +01:00
Simon Vieille 30072500bc add a way to create custom categories and manage application categories 2022-01-11 19:59:51 +01:00
Simon Vieille 9871cb93d8 Merge pull request 'develop' (#86) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/86
2022-01-10 15:07:07 +01:00
Simon Vieille a9ca55390d release v2.2.0 2022-01-10 15:02:05 +01:00
Simon Vieille 7230863d0a update icons (#84) 2022-01-10 14:59:17 +01:00
Simon Vieille d9046a205f update dependencies 2022-01-09 22:26:46 +01:00
Simon Vieille 0923a9107c fix categories order 2022-01-09 22:17:01 +01:00
Simon Vieille 1cbdca87df generate default colors using theming colors 2022-01-09 16:43:12 +01:00
Simon Vieille 2e8bed4531 Merge pull request 'update changelog' (#81) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/81
2021-12-03 14:15:36 +01:00
Simon Vieille 506fa22f4b update changelog 2021-12-03 14:14:03 +01:00
Simon Vieille 134148c6b2 Merge pull request 'release v2.1.0 (NC23 is compatible)' (#80) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/80
2021-12-03 14:03:10 +01:00
Simon Vieille a97e94e2e5 release v2.1.0 (NC23 is compatible) 2021-12-03 13:47:52 +01:00
Simon Vieille 7f33f7523f Merge pull request 'Release 2.0.1' (#79) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/79
2021-11-14 20:07:41 +01:00
Simon Vieille b6fb1783ba release v2.0.1 2021-11-14 20:05:22 +01:00
Simon Vieille 1b0418a466 fix js error on the personal settings page (undefined sortable) 2021-11-14 20:04:58 +01:00
Simon Vieille d37773cf5f fix js error on the personal settings page (undefined sortable) 2021-11-14 20:04:36 +01:00
Simon Vieille 1aea6ee4f4 fix #78: top menu is broken - invisible apps are shown 2021-11-14 20:01:43 +01:00
Simon Vieille a6dd6854e4 fix issue #77 2021-11-14 19:37:14 +01:00
Simon Vieille 70caa80af6 Merge pull request 'update makefile for assets build' (#75) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/75
2021-11-14 17:33:55 +01:00
Simon Vieille 48f403882a update makefile for assets build 2021-11-14 17:32:54 +01:00
Simon Vieille 6296c1c807 Merge pull request 'Release v2.0.0' (#74) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/74
2021-11-14 17:22:49 +01:00
Simon Vieille 71b9bc4766 release v2.0.0 2021-11-14 17:17:46 +01:00
Simon Vieille 228f07ea25 Merge branch 'feature/removing-jquery' into develop 2021-11-14 17:03:04 +01:00
Simon Vieille fd2ae59d16 remove background and border from opener (#73) 2021-11-14 16:44:52 +01:00
Simon Vieille 9124de3c81 fix the code of conduct 2021-11-06 20:11:53 +01:00
Simon Vieille 5e308b610d update the build task to include vendor/ 2021-11-05 20:20:42 +01:00
Simon Vieille db2220e745 replace the sortable jquery plugin with html5sortable 2021-11-05 20:19:08 +01:00
Simon Vieille 1143843a5b fix ci/cd conf 2021-11-03 23:02:57 +01:00
Simon Vieille 74d26106dc Merge pull request 'add ci/cd conf' (#72) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/72
2021-11-03 20:04:03 +01:00
Simon Vieille 539a81c07e add ci/cd conf 2021-11-03 20:01:54 +01:00
Simon Vieille d978da2c72 Merge branch 'develop' into feature/removing-jquery 2021-11-03 19:52:55 +01:00
Simon Vieille 544ed1a1fa add ci/cd conf (drone) 2021-11-03 19:52:24 +01:00
Simon Vieille ff5ba04217 Merge pull request 'add ci/cd conf (drone)' (#71) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/71
2021-11-03 19:20:36 +01:00
Simon Vieille 56e87d470d add ci/cd conf (drone) 2021-11-03 19:17:29 +01:00
Simon Vieille 9173ca37c7 add ci/cd conf (drone) 2021-11-02 20:48:54 +01:00
Simon Vieille 240b564e22 Merge pull request 'update documentation' (#70) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/70
2021-10-31 19:44:17 +01:00
Simon Vieille 11ccdceb98 update documentation 2021-10-31 19:43:25 +01:00
Simon Vieille 0608011d80 Merge pull request 'update metroline conf file' (#69) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/69
2021-10-31 18:45:36 +01:00
Simon Vieille 3d3da18322 update metroline conf file 2021-10-31 18:44:30 +01:00
Simon Vieille 3a999b22b0 Merge branch 'develop' into feature/removing-jquery 2021-10-31 17:48:06 +01:00
Simon Vieille 1544b28b57 Merge pull request 'add ci configuration' (#68) from develop into master
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/68
2021-10-31 17:47:47 +01:00
Simon Vieille e72d0555db update metroline conf file 2021-10-31 17:44:21 +01:00
Simon Vieille 7866089532 add metroline conf file 2021-10-31 17:42:22 +01:00
Simon Vieille ed2531db55 add fetch to make request 2021-10-31 17:27:08 +01:00
Simon Vieille c53221d112 fix indentation 2021-10-31 17:02:09 +01:00
Simon Vieille 9a95151156 remove console log 2021-10-31 16:56:52 +01:00
Simon Vieille 80369a39e1 remove jquery excepted for sorting categories 2021-10-31 16:55:43 +01:00
Simon Vieille 7471e93847 fix null setting update 2021-10-31 16:55:04 +01:00
Simon Vieille d1faf881da add timeout 2021-10-31 16:54:16 +01:00
Simon Vieille 96ffdf93ea remove useless vars 2021-10-29 15:30:22 +02:00
Simon Vieille 6f0c4e98e0 fix top menu generation; fix issue #66 by removing usage of setInterval 2021-10-29 13:56:48 +02:00
Simon Vieille c2e6d24b95 remove ';' on endline 2021-10-29 11:27:45 +02:00
Simon Vieille 5d93d02960 refactoring of alwaysDisplayed function 2021-10-29 11:24:01 +02:00
Simon Vieille a074d747c1 remove most of jquery from top menu 2021-10-29 11:14:27 +02:00
Simon Vieille cc7c9f6ed5 remove most of jquery 2021-10-28 15:47:03 +02:00
Simon Vieille f26adb6ac1 remove jquery from components 2021-10-28 13:50:16 +02:00
Simon Vieille 1e64b34cff Merge branch 'develop' 2021-10-28 13:17:04 +02:00
Simon Vieille 3b6b8ad54a add missing svg 2021-10-28 13:16:55 +02:00
Simon Vieille cc71fda3b0 Merge branch 'develop' 2021-10-21 21:43:51 +02:00
Simon Vieille 64c4d7a1e1 release v1.28.0 2021-10-21 21:43:30 +02:00
Simon Vieille fd367fe2d4 Merge branch 'develop' 2021-10-21 21:37:40 +02:00
Simon Vieille 3975f3be28 fix #63: add a new side menu with categories 2021-10-21 21:37:32 +02:00
Simon Vieille 3f590a97bc Merge branch 'develop' 2021-10-21 20:06:41 +02:00
Simon Vieille 1896bb399d fix #62: hide app notification icon 2021-10-21 20:06:17 +02:00
Simon Vieille d77c2ef9ae release v1.27.1 2021-08-11 14:43:52 +02:00
Simon Vieille db0fa60ce8 fix German translation render 2021-08-11 14:43:04 +02:00
Simon Vieille aac9f2cb16 Merge branch 'develop' 2021-08-11 11:58:25 +02:00
Simon Vieille 33d7c6a7f0 release v1.27.0 2021-08-11 11:58:15 +02:00
Simon Vieille a72bb87aa2 hide personal settings access when settings are forced by the administrator 2021-08-11 11:57:43 +02:00
Simon Vieille 5e4a7bcae4 improved German translations 2021-08-11 11:57:01 +02:00
Simon Vieille f7d4a8284b Merge branch 'develop' 2021-08-02 21:49:02 +02:00
Simon Vieille b900ed7a4d release v1.26.0 2021-08-02 21:48:58 +02:00
Simon Vieille 4a10338588 Merge pull request 'Add Czech localization' (#61) from Pavelb/side_menu:develop into develop
Reviewed-on: https://gitnet.fr/deblan/side_menu/pulls/61
2021-08-02 21:35:34 +02:00
Pavelb 88ecd2ceaf Add Czech localization 2021-07-23 14:45:45 +02:00
Simon Vieille 04d161ad9b Merge branch 'develop' 2021-07-09 12:55:07 +02:00
Simon Vieille 1dcf1b7938 update changelog 2021-07-09 12:55:05 +02:00
Simon Vieille dab5566be4 Merge branch 'develop' 2021-07-09 12:54:32 +02:00
Simon Vieille 143ece3be8 update changelog 2021-07-09 12:54:28 +02:00
Simon Vieille d735e1cfa6 Merge branch 'develop' 2021-07-09 12:43:01 +02:00
Simon Vieille f86ec1de52 update changelog 2021-07-09 12:42:51 +02:00
Simon Vieille b780f53e0b add PHP version as dependency 2021-07-09 12:42:43 +02:00
Simon Vieille 96a4235a10 Merge branch 'develop' 2021-07-09 11:52:28 +02:00
Simon Vieille 86be38af6c add translations: zh_CN 2021-07-09 11:52:05 +02:00
49 changed files with 2338 additions and 2294 deletions
+54
View File
@@ -0,0 +1,54 @@
---
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
+200 -56
View File
@@ -1,190 +1,334 @@
## v1.25.0 ## [Unreleased]
## 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
### Added
- fix #63: add a new side menu with categories
## 1.27.2
### Fixed
- fix #62: hide app notification icon
## 1.27.1
### Fixed
- fix German translation render
## 1.27.0
### Added
- hide personal settings access when settings are forced by the administrator
### Fixed
- improve German translations
## 1.26.0
### Added
- add Czech translation
## 1.25.2
### Fixed
- fix CHANGELOG
## 1.25.1
### Added
- add PHP version as dependency
- add chinese translation
### Fixed
- fix CHANGELOG
## 1.25.0
### Added
- add compatibility with Nextcloud 22 - add compatibility with Nextcloud 22
- add CHANGELOG.md (fix #59) - add CHANGELOG.md (fix #59)
- update app icon - update app icon
## v1.24.0 ## 1.24.0
### Added
- add option to define the background opacity (fix #53) - add option to define the background opacity (fix #53)
- add missing translations - add missing translations
## v1.23.1 ## 1.23.1
### Fixed
- fix but wih dark mode opener option - fix but wih dark mode opener option
## v1.23.0 ## 1.23.0
### Added
- add support of dark Theme and Breeze Dark - add support of dark Theme and Breeze Dark
- add support of Nextcloud 21 - add support of Nextcloud 21
## v1.22.2 ## 1.22.2
### Fixed
- fix regression: apps does not open in new tab (fix #55) - fix regression: apps does not open in new tab (fix #55)
## v1.22.1 ## 1.22.1
### Fixed
- fix regression: apps does not open in new tab - fix regression: apps does not open in new tab
## v1.22.0 ## 1.22.0
### Added
- Add option to sort categories (fix #53) - Add option to sort categories (fix #53)
- Update admin UI - Update admin UI
## v1.21.0 ## 1.21.0
### Added
- [FEATURE] Logo in the menu links to main page of installation (#51) - [FEATURE] Logo in the menu links to main page of installation (#51)
## v1.20.1 ## 1.20.1
### Fixed
- Fix translations - Fix translations
## v1.20.0 ## 1.20.0
### Added
- [FEATURE] Ability to remove apps from the Big Menu (#49) - [FEATURE] Ability to remove apps from the Big Menu (#49)
## v1.19.1 ## 1.19.1
### Fixed
- fix #47: setting for list/grid view in files app flashes and dissapears - fix #47: setting for list/grid view in files app flashes and dissapears
## v1.19.0 ## 1.19.0
### Added
- add option: the menu is enabled by default for users (fix #46) - add option: the menu is enabled by default for users (fix #46)
## v1.18.0 ## 1.18.0
### Added
- add option to show link to settings (fix #44) - add option to show link to settings (fix #44)
- refactor menus using several components - refactor menus using several components
## v1.17.0 ## 1.17.0
### Added
- compliance with the app checker - compliance with the app checker
- add an action to export the configuration - add an action to export the configuration
- add an action to purge the cache - add an action to purge the cache
## v1.16.3 ## 1.16.3
### Fixed
- fix links that must be opened in new window (https://help.nextcloud.com/t/external-petit-probleme-concernant-lapplication-external-sites-ou-sites-externes/94884/11) - fix links that must be opened in new window (https://help.nextcloud.com/t/external-petit-probleme-concernant-lapplication-external-sites-ou-sites-externes/94884/11)
## v1.16.2 ## 1.16.2
### Fixed
- fix issue with personal settings when global settings are forced - fix issue with personal settings when global settings are forced
## v1.16.1 ## 1.16.1
### Fixed
- fix #42: add cache to manage failures to access apps.nextcloud.com - fix #42: add cache to manage failures to access apps.nextcloud.com
- fix #41: side menu was hover apps list - fix #41: side menu was hover apps list
## v1.16.0 ## 1.16.0
### Added
- add an option to force settings to users (fix #38) - add an option to force settings to users (fix #38)
## v1.15.0 ## 1.15.0
### Changed
- New name - New name
### Fixed
- Fix #36: always displayed is not expanding - Fix #36: always displayed is not expanding
## v1.14.0 ## 1.14.0
### Added
- add an api accessed by components - add an api accessed by components
- add a config proxy in controllers - add a config proxy in controllers
### Fixed
- fix translations - fix translations
## v1.13.0 ## 1.13.0
### Added
- add an option to display the avatar instead of the logo (fix #34) - add an option to display the avatar instead of the logo (fix #34)
## v1.12.3 ## 1.12.3
### Added
- add a delay before moving elements (fix #33) - add a delay before moving elements (fix #33)
## v1.12.2 ## 1.12.2
### Fixed
- fix #30: `Always displayed` menu can not be close using touchscreens - fix #30: `Always displayed` menu can not be close using touchscreens
## v1.12.1 ## 1.12.1
### Fixed
- fix typo - fix typo
- fix translations - fix translations
## v1.12.0 ## 1.12.0
### Fixed
- fix #30: administrators and users can select what apps must be opened in new tab - fix #30: administrators and users can select what apps must be opened in new tab
- fix typo - fix typo
## v1.11.0 ## 1.11.0
### Added
- add the option for opening apps in new tab (fix #29) - add the option for opening apps in new tab (fix #29)
### Fixed
- fix issue with the header of the always displayed menu - fix issue with the header of the always displayed menu
## v1.10.0 ## 1.10.0
### Added
- add images to select the display of the menu - add images to select the display of the menu
- add live preview - add live preview
- update translations - update translations
- update app info - update app info
## v1.9.3 ## 1.9.3
### Fixed
- fix regression with logo display - fix regression with logo display
## v1.9.2 ## 1.9.2
### Added
- add the option “always displayed” which fixes the position of the menu to the left and always displays the application icons (fix #21, fix #2) - add the option “always displayed” which fixes the position of the menu to the left and always displays the application icons (fix #21, fix #2)
## v1.8.6 ## 1.8.6
### Added
- add translations: `fr` and `de` - add translations: `fr` and `de`
- improve and publish the `Makefile` - improve and publish the `Makefile`
- update documentation - update documentation
## v1.8.5 ## 1.8.5
### Fixed
- fix #28: menu items invisible after 1.8.4 - fix #28: menu items invisible after 1.8.4
## v1.8.4 ## 1.8.4
### Fixed
- fix #27: disable side menu on public pages - broken in 1.8.3 - fix #27: disable side menu on public pages - broken in 1.8.3
## v1.8.3 ## 1.8.3
### Fixed
- fix alphabetic order of apps (#26) - fix alphabetic order of apps (#26)
## v1.8.2 ## 1.8.2
### Added
- add icon for closing the big menu (fix #25) - add icon for closing the big menu (fix #25)
### Fixed
- fix hidden icons in the top menu (fix #23) - fix hidden icons in the top menu (fix #23)
- fix missing apps (fix #24) - fix missing apps (fix #24)
## v1.8.1 ## 1.8.1
### Fixed
- fix issue with links - fix issue with links
- fix missing l10n files - fix missing l10n files
## v1.8.0 ## 1.8.0
### Added
- add a `big menu` display (fix #22) - add a `big menu` display (fix #22)
- add the possibility to choose what apps are displayed in the top menu (fix #22) - add the possibility to choose what apps are displayed in the top menu (fix #22)
- add icon color filter - add icon color filter
- add icon opacity filter - add icon opacity filter
## v1.8.0-rc2 ## 1.8.0-rc2
## v1.7.0 ## 1.7.0
### Added
- add a loader when the page is unloading - add a loader when the page is unloading
- add compatibility with Nextcloud 19 - add compatibility with Nextcloud 19
## v1.6.3 ## 1.6.3
### Fixed
- fix #20: add a shortcut to open and to hide the menu - fix #20: add a shortcut to open and to hide the menu
## v1.6.2 ## 1.6.2
### Fixed
- fix #19: add a cache to limit flashes - fix #19: add a cache to limit flashes
## v1.6.1 ## 1.6.1
### Fixed
- fix #19: add a hack to show external sites in the top menu with navigation - fix #19: add a hack to show external sites in the top menu with navigation
## v1.6.0 ## 1.6.0
- Refactoring of javascripts ### Added
- Add a page of personal settings - Add a page of personal settings
- Add an option to disable the side menu as user - Add an option to disable the side menu as user
- Refactoring of javascripts
## v1.5.0 ## 1.5.0
### Added
- add option to force light icons instead of dark icons
### Fixed
- fix #19: add option to keep external sites in the top menu - fix #19: add option to keep external sites in the top menu
- fix #16 #17: add dark icons and handle the svg filters - fix #16 #17: add dark icons and handle the svg filters
- add option to force light icons instead of dark icons
## v1.4.1 ## 1.4.1
### Added
- Rendering harmonization with browsers
### Fixed
- FIX #15: make menu start after icon - FIX #15: make menu start after icon
- Rendering harmonization with browsers
## v1.4.0 ## 1.4.0
### Fixed
- Fix #12: add an option to hide the opener and the panel when there is no application - Fix #12: add an option to hide the opener and the panel when there is no application
## v1.3.4 ## 1.3.4
### Fixed
- FIX #14: add option to show only the opener - FIX #14: add option to show only the opener
- FIX #13: add alternate hamburger icon - FIX #13: add alternate hamburger icon
- FIX #11: remove error in the console - FIX #11: remove error in the console
## v1.3.3 ## 1.3.3
- FIX #10: add options to select the size of the icons and the text, or hide them ### Added
- Add a second background color to create a background gradiant - Add a second background color to create a background gradiant
- Update documentation - Update documentation
### Fixed
- FIX #10: add options to select the size of the icons and the text, or hide them
## v1.3.2 ## 1.3.2
### Fixed
- FIX #9: opener icon not visible with multiple apps_paths - FIX #9: opener icon not visible with multiple apps_paths
## v1.3.1 ## 1.3.1
### Fixed
- FIX #3: Add an opition the choose the position of the opener (after or before the logo) - FIX #3: Add an opition the choose the position of the opener (after or before the logo)
- FIX #8: Remove extension of dynamic asset's routes (js, css) - FIX #8: Remove extension of dynamic asset's routes (js, css)
## v1.3.0 ## 1.3.0
- FIX #2: add option to open the menu by hovering over opener ### Added
- `main.js` is replaced by a controller and a template - `main.js` is replaced by a controller and a template
### Fixed
- FIX #2: add option to open the menu by hovering over opener
## v1.2.4 ## 1.2.4
### Fixed
- FIX #7: Opener icon not visible in Safari - FIX #7: Opener icon not visible in Safari
+3 -1025
View File
File diff suppressed because one or more lines are too long
+8 -4
View File
@@ -11,10 +11,14 @@ release: npm-build translations
exit 1 exit 1
fi fi
test -d releases/$$VERSION && rm -fr releases/$$VERSION if [ -z "$$RELEASE_DIRECTORY" ]; then
mkdir -p releases/$$VERSION/side_menu RELEASE_DIRECTORY=releases
cp -r README.md CHANGELOG.md appinfo css lib img l10n js src templates screenshots releases/$$VERSION/side_menu fi
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
+7 -1
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 define apps that must be displayed in the top menu. Fully customisable. You can also add and sort custom categories, define apps that must be displayed in the top menu, etc. 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,6 +10,7 @@ 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)
@@ -58,3 +59,8 @@ 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).
+3 -2
View File
@@ -26,7 +26,7 @@ If you like this application and if you want to support the development:
* [Donate with liberapay](https://liberapay.com/deblan) * [Donate with liberapay](https://liberapay.com/deblan)
* [Leave a comment](https://apps.nextcloud.com/apps/side_menu#comments) * [Leave a comment](https://apps.nextcloud.com/apps/side_menu#comments)
]]></description> ]]></description>
<version>1.25.0</version> <version>2.3.4</version>
<licence>agpl</licence> <licence>agpl</licence>
<author mail="contact@deblan.fr" homepage="https://www.deblan.io/">Simon Vieille</author> <author mail="contact@deblan.fr" homepage="https://www.deblan.io/">Simon Vieille</author>
<namespace>SideMenu</namespace> <namespace>SideMenu</namespace>
@@ -46,7 +46,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="18" max-version="22"/> <nextcloud min-version="19" max-version="23"/>
<php min-version="7.3"/>
</dependencies> </dependencies>
<settings> <settings>
<admin>OCA\SideMenu\Settings\Admin</admin> <admin>OCA\SideMenu\Settings\Admin</admin>
+12 -2
View File
@@ -20,7 +20,7 @@
margin: 10px 0 10px 0; margin: 10px 0 10px 0;
} }
#side-menu-section input[type="checkbox"] { #-dropside-menu-section input[type="checkbox"] {
vertical-align: middle; vertical-align: middle;
} }
@@ -81,6 +81,12 @@
cursor: pointer; cursor: pointer;
} }
.side-menu-setting-list-drop {
background: yellow;
border-color: yellow;
height: 34px;
}
.side-menu-setting.arrow { .side-menu-setting.arrow {
color: #ccc; color: #ccc;
padding-right: 5px; padding-right: 5px;
@@ -91,6 +97,10 @@
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;
@@ -109,7 +119,7 @@
.side-menu-setting-form { .side-menu-setting-form {
display: table-cell; display: table-cell;
width: 300px; min-width: 300px;
} }
.side-menu-setting-label-short { .side-menu-setting-label-short {
+46 -11
View File
@@ -34,7 +34,7 @@
} }
#header .side-menu-opener { #header .side-menu-opener {
margin-left: 5px; margin-left: 0px;
} }
.side-menu-settings { .side-menu-settings {
@@ -67,10 +67,19 @@
.side-menu-opener { .side-menu-opener {
background: var(--side-menu-opener, url('../img/side-menu-opener.svg')); background: var(--side-menu-opener, url('../img/side-menu-opener.svg'));
height: 40px; background-color: transparent !important;
width: 40px; height: 40px !important;
border-radius: 0; width: 40px !important;
border: 0; border-radius: 0 !important;
border: 0 !important;
padding-right: 12px !important;
padding-left: 12px !important;
margin-left: 5px !important;
margin-left: 3px !important;
}
.side-menu-opener:active {
background-color: var(--color-background-dark) !important;
} }
.side-menu-closer { .side-menu-closer {
@@ -105,6 +114,10 @@
margin-top: -3px; margin-top: -3px;
} }
.side-menu-app-icon .app-icon-notification {
display: none;
}
.side-menu-app a { .side-menu-app a {
line-height: 30px; line-height: 30px;
color: var(--side-menu-text-color, #fff); color: var(--side-menu-text-color, #fff);
@@ -135,7 +148,6 @@
max-width: 250px; max-width: 250px;
position: fixed; position: fixed;
padding-top: 2px; padding-top: 2px;
padding-left: 5px;
top: 0; top: 0;
} }
@@ -158,23 +170,23 @@
transition-property: width; transition-property: width;
} }
#side-menu.side-menu-big { #side-menu.side-menu-big, #side-menu.side-menu-with-categories {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
} }
.side-menu-big .side-menu-header { .side-menu-big .side-menu-header, .side-menu-with-categories .side-menu-header {
height: auto; height: auto;
} }
.side-menu-big .side-menu-apps-list { .side-menu-big .side-menu-apps-list, .side-menu-with-categories .side-menu-apps-list {
height: auto; height: auto;
position: static; position: static;
max-width: 100vw; max-width: 100vw;
overflow: auto; overflow: auto;
} }
.side-menu-big .side-menu-app a { .side-menu-big .side-menu-app a, .side-menu-with-categories .side-menu-app a {
padding: 7px 0 7px 7px; padding: 7px 0 7px 7px;
} }
@@ -213,7 +225,7 @@
stroke: var(--side-menu-text-color, #fff); stroke: var(--side-menu-text-color, #fff);
} }
.side-menu-big .side-menu-app-icon { .side-menu-with-categories .side-menu-app-icon, .side-menu-big .side-menu-app-icon {
vertical-align: middle; vertical-align: middle;
margin-top: -2px; margin-top: -2px;
} }
@@ -235,6 +247,11 @@
.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,
@@ -267,6 +284,24 @@
transform: translateX(calc(-100% + 50px)) !important; transform: translateX(calc(-100% + 50px)) !important;
} }
#side-menu.side-menu-with-categories {
max-width: 290px;
height: 100vh;
}
.side-menu-with-categories .side-menu-categories {
display: block;
padding: 0;
}
.side-menu-with-categories .side-menu-category {
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;
@@ -0,0 +1,224 @@
<?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>

After

Width:  |  Height:  |  Size: 7.3 KiB

+223
View File
@@ -0,0 +1,223 @@
<?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" />
<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>

After

Width:  |  Height:  |  Size: 7.3 KiB

+1 -6
View File
@@ -1,6 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 10.583 10.583"> <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>
<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: 498 B

After

Width:  |  Height:  |  Size: 495 B

+1 -173
View File
@@ -1,173 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <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>
<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: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

+1 -102
View File
@@ -1,102 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <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>
<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: 2.8 KiB

After

Width:  |  Height:  |  Size: 786 B

+1 -101
View File
@@ -1,101 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <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>
<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: 2.8 KiB

After

Width:  |  Height:  |  Size: 809 B

+1 -92
View File
@@ -1,92 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <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>
<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: 2.5 KiB

After

Width:  |  Height:  |  Size: 637 B

+1 -91
View File
@@ -1,91 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <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>
<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: 2.4 KiB

After

Width:  |  Height:  |  Size: 649 B

+1 -172
View File
@@ -1,172 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <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>
<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: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

+44 -11
View File
@@ -27,6 +27,8 @@ 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
{ {
@@ -40,12 +42,30 @@ 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;
} }
/** /**
@@ -67,6 +87,7 @@ 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');
@@ -74,11 +95,16 @@ 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');
@@ -90,23 +116,29 @@ 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', '#333333'); $backgroundColor = $this->config->getAppValue('dark-mode-background-color', $darkenPrimaryColor);
$backgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $backgroundColor); $backgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $darkenPrimaryColor);
$currentAppBackgroundColor = $this->config->getAppValue('dark-mode-current-app-background-color', '#444444'); $currentAppBackgroundColor = $this->config->getAppValue('dark-mode-current-app-background-color', $darkenPrimaryColor2);
$loaderColor = $this->config->getAppValue('dark-mode-loader-color', '#cccccc'); $loaderColor = $this->config->getAppValue('dark-mode-loader-color', $lightenPrimaryColor);
$textColor = $this->config->getAppValue('dark-mode-text-color', '#FFFFFF'); $textColor = $this->config->getAppValue('dark-mode-text-color', $textColor);
$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', '#333333'); $backgroundColor = $this->config->getAppValue('background-color', $darkenPrimaryColor);
$backgroundColorTo = $this->config->getAppValue('background-color-to', $backgroundColor); $backgroundColorTo = $this->config->getAppValue('background-color-to', $darkenPrimaryColor);
$currentAppBackgroundColor = $this->config->getAppValue('current-app-background-color', '#444444'); $currentAppBackgroundColor = $this->config->getAppValue('current-app-background-color', $darkenPrimaryColor2);
$loaderColor = $this->config->getAppValue('loader-color', '#0e75ac'); $loaderColor = $this->config->getAppValue('loader-color', $lightenPrimaryColor);
$textColor = $this->config->getAppValue('text-color', '#FFFFFF'); $textColor = $this->config->getAppValue('text-color', $textColor);
$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');
@@ -136,6 +168,7 @@ 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,
]; ];
} }
} }
+8
View File
@@ -94,6 +94,7 @@ 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');
@@ -103,11 +104,16 @@ 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', '[]');
@@ -152,10 +158,12 @@ class JsController extends Controller
'hide-when-no-apps' => $this->config->getAppValueBool('hide-when-no-apps', '0'), 'hide-when-no-apps' => $this->config->getAppValueBool('hide-when-no-apps', '0'),
'loader-enabled' => $this->config->getAppValueBool('loader-enabled', '1'), 'loader-enabled' => $this->config->getAppValueBool('loader-enabled', '1'),
'always-displayed' => $this->config->getAppValueBool('always-displayed', '0'), 'always-displayed' => $this->config->getAppValueBool('always-displayed', '0'),
'side-with-categories' => $this->config->getAppValueBool('side-with-categories', '0'),
'big-menu' => $this->config->getAppValueBool('big-menu', '0'), 'big-menu' => $this->config->getAppValueBool('big-menu', '0'),
'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,9 +187,18 @@ 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;
} }
+2 -1
View File
@@ -54,6 +54,7 @@ class PersonalSettingController extends Controller
/** /**
* @NoAdminRequired * @NoAdminRequired
* @NoCSRFRequired
* *
* @param mixed $name * @param mixed $name
* @param mixed $value * @param mixed $value
@@ -96,7 +97,7 @@ class PersonalSettingController extends Controller
} }
} }
if ('top-menu-apps' === $name) { if (in_array($name, ['top-menu-apps', 'top-side-menu-apps'])) {
$doSave = true; $doSave = true;
$data = json_decode($value, true); $data = json_decode($value, true);
+27 -1
View File
@@ -21,10 +21,27 @@ 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;
} }
/** /**
@@ -35,6 +52,9 @@ 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 = [];
@@ -74,6 +94,12 @@ 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;
}); });
+22 -2
View File
@@ -5,6 +5,7 @@ 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;
/** /**
@@ -34,16 +35,23 @@ 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;
} }
/** /**
@@ -56,8 +64,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();
@@ -74,6 +82,18 @@ 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
@@ -0,0 +1,34 @@
<?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
@@ -0,0 +1,48 @@
<?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;
}
}
+47 -12
View File
@@ -26,6 +26,9 @@ 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
{ {
@@ -54,18 +57,39 @@ 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;
} }
/** /**
@@ -73,35 +97,42 @@ class Admin implements ISettings
*/ */
public function getForm() public function getForm()
{ {
$backgroundColor = $this->config->getAppValue('background-color', '#333333'); $primaryColor = $this->theming->getColorPrimary();
$backgroundColorTo = $this->config->getAppValue('background-color-to', $backgroundColor); $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();
$darkModeBackgroundColor = $this->config->getAppValue('dark-mode-background-color', '#333333'); $backgroundColor = $this->config->getAppValue('background-color', $darkenPrimaryColor);
$darkModeBackgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $darkModeBackgroundColor); $backgroundColorTo = $this->config->getAppValue('background-color-to', $darkenPrimaryColor);
$darkModeBackgroundColor = $this->config->getAppValue('dark-mode-background-color', $darkenPrimaryColor);
$darkModeBackgroundColorTo = $this->config->getAppValue('dark-mode-background-color-to', $darkenPrimaryColor);
$parameters = [ $parameters = [
'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', '#444444'), 'current-app-background-color' => $this->config->getAppValue('current-app-background-color', $darkenPrimaryColor2),
'loader-color' => $this->config->getAppValue('loader-color', '#0e75ac'), 'loader-color' => $this->config->getAppValue('loader-color', $lightenPrimaryColor),
'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', '#FFFFFF'), 'text-color' => $this->config->getAppValue('text-color', $textColor),
'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', '#444444'), 'dark-mode-current-app-background-color' => $this->config->getAppValue('dark-mode-current-app-background-color', $darkenPrimaryColor2),
'dark-mode-loader-color' => $this->config->getAppValue('dark-mode-loader-color', '#cccccc'), 'dark-mode-loader-color' => $this->config->getAppValue('dark-mode-loader-color', $textColor),
'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', '#FFFFFF'), 'dark-mode-text-color' => $this->config->getAppValue('dark-mode-text-color', $textColor),
'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'),
'cache' => $this->config->getAppValue('cache', '0'), 'cache' => $this->config->getAppValue('cache', '0'),
'always-displayed' => $this->config->getAppValue('always-displayed', '0'), 'always-displayed' => $this->config->getAppValue('always-displayed', '0'),
'big-menu' => $this->config->getAppValue('big-menu', '0'), 'big-menu' => $this->config->getAppValue('big-menu', '0'),
'side-with-categories' => $this->config->getAppValue('side-with-categories', '0'),
'big-menu-hidden-apps' => $this->config->getAppValueArray('big-menu-hidden-apps', '[]'), 'big-menu-hidden-apps' => $this->config->getAppValueArray('big-menu-hidden-apps', '[]'),
'display-logo' => $this->config->getAppValue('display-logo', '1'), 'display-logo' => $this->config->getAppValue('display-logo', '1'),
'add-logo-link' => $this->config->getAppValue('add-logo-link', '1'), 'add-logo-link' => $this->config->getAppValue('add-logo-link', '1'),
@@ -116,11 +147,15 @@ 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', '[]'),
'apps' => $this->appRepository->getVisibleApps(), 'categories-custom' => $this->config->getAppValueArray('categories-custom', '[]'),
'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,6 +78,7 @@ 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(),
+20 -1
View File
@@ -19,6 +19,7 @@
namespace OCA\SideMenu\Settings; namespace OCA\SideMenu\Settings;
use OCA\SideMenu\AppInfo\Application; use OCA\SideMenu\AppInfo\Application;
use OCA\SideMenu\Service\ConfigProxy;
use OCP\IL10N; use OCP\IL10N;
use OCP\IURLGenerator; use OCP\IURLGenerator;
use OCP\Settings\IIconSection; use OCP\Settings\IIconSection;
@@ -35,10 +36,16 @@ class PersonalSection implements IIconSection
*/ */
private $url; private $url;
public function __construct(IURLGenerator $url, IL10N $l) /**
* @var ConfigProxy
*/
private $configProxy;
public function __construct(IURLGenerator $url, IL10N $l, ConfigProxy $configProxy)
{ {
$this->url = $url; $this->url = $url;
$this->l = $l; $this->l = $l;
$this->configProxy = $configProxy;
} }
/** /**
@@ -49,6 +56,10 @@ class PersonalSection implements IIconSection
*/ */
public function getID() public function getID()
{ {
if ($this->configProxy->getAppValueBool('force', '0')) {
return '';
}
return Application::APP_ID; return Application::APP_ID;
} }
@@ -60,6 +71,10 @@ class PersonalSection implements IIconSection
*/ */
public function getName() public function getName()
{ {
if ($this->configProxy->getAppValueBool('force', '0')) {
return '';
}
return $this->l->t(Application::APP_NAME); return $this->l->t(Application::APP_NAME);
} }
@@ -72,6 +87,10 @@ class PersonalSection implements IIconSection
*/ */
public function getPriority() public function getPriority()
{ {
if ($this->configProxy->getAppValueBool('force', '0')) {
return null;
}
return 70; return 70;
} }
+5 -5
View File
@@ -11,9 +11,9 @@
"stylelint:fix": "stylelint src --fix" "stylelint:fix": "stylelint src --fix"
}, },
"dependencies": { "dependencies": {
"@nextcloud/axios": "^1.3.2", "@nextcloud/axios": "^1.8.0",
"@nextcloud/vue": "^1.4.0", "@nextcloud/vue": "^1.5.0",
"axios": "^0.19.2", "axios": "^0.24.0",
"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": ">=10.0.0" "node": ">=16.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: 195 KiB

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

+182
View File
@@ -0,0 +1,182 @@
<!--
@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>
+4 -4
View File
@@ -18,11 +18,9 @@
import Vue from 'vue' import Vue from 'vue'
import SideMenu from './SideMenu.vue' import SideMenu from './SideMenu.vue'
import SideMenuBig from './SideMenuBig.vue' import SideMenuBig from './SideMenuBig.vue'
import SideMenuWithCategories from './SideMenuWithCategories.vue'
// Vue.prototype.t = t
Vue.prototype.OC = OC Vue.prototype.OC = OC
// Vue.prototype.OC = OCP
const mountSideMenuComponent = () => { const mountSideMenuComponent = () => {
const sideMenuContainer = document.querySelector('#side-menu') const sideMenuContainer = document.querySelector('#side-menu')
@@ -32,6 +30,8 @@ const mountSideMenuComponent = () => {
if (sideMenuContainer.getAttribute('data-bigmenu')) { if (sideMenuContainer.getAttribute('data-bigmenu')) {
component = SideMenuBig component = SideMenuBig
} else if(sideMenuContainer.getAttribute('data-sidewithcategories')) {
component = SideMenuWithCategories
} else { } else {
component = SideMenu component = SideMenu
} }
@@ -41,7 +41,7 @@ const mountSideMenuComponent = () => {
sideMenu.$mount('#side-menu') sideMenu.$mount('#side-menu')
$('body').trigger('side-menu.ready') document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.ready'))
} else { } else {
window.setTimeout(mountSideMenuComponent, 50) window.setTimeout(mountSideMenuComponent, 50)
} }
+6 -4
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-hidden') && !menuIsHidden) { if (!parent.classList.contains('app-top-side-menu') && !parent.classList.contains('app-hidden') && !menuIsHidden) {
continue continue
} }
@@ -122,13 +122,15 @@ export default {
name: trim(element.querySelector('span').innerHTML), name: trim(element.querySelector('span').innerHTML),
icon: svg, icon: svg,
active: element.classList.contains('active') active: element.classList.contains('active')
}); })
} }
} }
(function(apps) { (function(apps) {
window.setTimeout(function() { window.setTimeout(function() {
jQuery('body').trigger('side-menu.apps', [apps]) document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
detail: {apps: apps},
}))
}, 1000) }, 1000)
})(this.apps) })(this.apps)
}, },
@@ -147,7 +149,7 @@ export default {
that.logo = config['logo'] that.logo = config['logo']
that.logoLink = config['logo-link'] that.logoLink = config['logo-link']
that.settings = config['settings'] that.settings = config['settings']
}); })
}, },
}, },
mounted() { mounted() {
+5 -3
View File
@@ -97,8 +97,10 @@ export default {
} }
} }
jQuery('body').trigger('side-menu.apps', [apps]) document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
}); detail: {apps: apps},
}))
})
}, },
retrieveActiveApp() { retrieveActiveApp() {
@@ -116,7 +118,7 @@ export default {
that.targetBlankApps = config['target-blank-apps'] that.targetBlankApps = config['target-blank-apps']
that.settings = config['settings'] that.settings = config['settings']
}); })
}, },
}, },
mounted() { mounted() {
+128
View File
@@ -0,0 +1,128 @@
<!--
@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 id="side-menu" class="side-menu-with-categories">
<div class="side-menu-header">
<SettingsButton
v-if="settings"
v-bind:href="settings.href"
v-bind:label="settings.name"
v-bind:avatar="settings.avatar"
/>
<OpenerButton />
</div>
<div class="side-menu-categories-wrapper">
<div class="side-menu-categories">
<Loader v-if="!items.length" />
<div class="side-menu-category" v-for="category in items">
<h2 class="side-menu-category-title" v-if="category.name != ''" v-html="category.name"></h2>
<ul class="side-menu-apps-list">
<SideMenuBigApp
v-for="(app, appId) in category.apps"
v-bind:classes="{'side-menu-app': true, 'active': activeApp === appId}"
v-bind:icon="app.icon"
v-bind:label="app.name"
v-bind:href="app.href"
v-bind:target="targetBlankApps.indexOf(appId) !== -1 ? '_blank' : undefined"
/>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
import trim from 'trim'
import axios from 'axios'
import OpenerButton from './OpenerButton'
import CloserButton from './CloserButton'
import SettingsButton from './SettingsButton'
import Loader from './Loader'
import SideMenuBigApp from './SideMenuBigApp'
export default {
name: 'SideMenuWithCategories',
components: {
SettingsButton,
OpenerButton,
CloserButton,
Loader,
SideMenuBigApp,
},
data() {
return {
items: [],
activeApp: null,
targetBlank: false,
targetBlankApps: [],
settings: null,
}
},
methods: {
retrieveApps() {
this.apps = []
let that = this
axios
.get(OC.generateUrl('/apps/side_menu/nav/items'))
.then(function(response) {
that.items = response.data.items
let apps = []
for (let category of that.items) {
for (let a in category.apps) {
apps.push(category.apps[a])
}
}
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
detail: {apps: apps},
}))
})
},
retrieveActiveApp() {
let activeAppLink = document.querySelector('#appmenu a.active')
this.activeApp = activeAppLink ? activeAppLink.parentNode.getAttribute('data-id') : null
},
retrieveConfig() {
let that = this
axios
.get(OC.generateUrl('/apps/side_menu/js/config'))
.then(function(response) {
const config = response.data
that.targetBlankApps = config['target-blank-apps']
that.settings = config['settings']
})
},
},
mounted() {
this.retrieveConfig()
this.retrieveApps()
this.retrieveActiveApp()
}
}
</script>
+151 -73
View File
@@ -15,15 +15,32 @@
* 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 = []
$.post(url, {name: name, value: value}, callbacks.success) formData.push('name=' + encodeURIComponent(name))
.fail(callbacks.error) formData.push('value=' + encodeURIComponent(value))
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) => {
@@ -31,23 +48,29 @@ const appConfig = (name, value, callbacks) => {
} }
const saveSettings = (key) => { const saveSettings = (key) => {
const element = elements.get(key) const element = elements[key]
if (!element) {
return
}
let value let value
let name let name
if (jQuery(element).is('[data-checkbox]')) { if (element.hasAttribute('data-checkbox')) {
name = jQuery(element).attr('data-name') name = element.getAttribute('data-name')
const inputs = jQuery('input[name="' + name + '[]"]:checked')
value = [] value = []
inputs.each((i, v) => { const inputs = document.querySelectorAll('input[name="' + name + '[]"]:checked')
value.push(v.value)
}) for (let input of inputs) {
value.push(input.value)
}
value = JSON.stringify(value) value = JSON.stringify(value)
} else { } else {
name = jQuery(element).attr('name') name = element.getAttribute('name')
value = jQuery(element).val() value = element.value
} }
const size = elements.length const size = elements.length
@@ -64,9 +87,10 @@ const saveSettings = (key) => {
) )
if (key < size - 1) { if (key < size - 1) {
saveSettings(++key) saveSettings(key + 1)
} else { } else {
OC.msg.finishedSuccess(selector, t('side_menu', 'Saved')) OC.msg.finishedSuccess(selector, t('side_menu', 'Saved! Page is reloading...'))
location.reload()
} }
}, },
error: () => { error: () => {
@@ -74,7 +98,7 @@ const saveSettings = (key) => {
} }
} }
if (jQuery(element).is('[data-personal]')) { if (element.hasAttribute('data-personal')) {
userConfig(name, value, callbacks) userConfig(name, value, callbacks)
} else { } else {
appConfig(name, value, callbacks) appConfig(name, value, callbacks)
@@ -82,83 +106,137 @@ const saveSettings = (key) => {
} }
const elementToggler = (element) => { const elementToggler = (element) => {
jQuery(element).toggle() let display = 'none'
if (window.getComputedStyle(element).display === 'none') {
display = 'block'
}
element.style.display = display
} }
jQuery(document).ready(() => { const updateAppsCategoriesCustom = () => {
elements = jQuery('.side-menu-setting') let values = {}
jQuery('#side-menu-save').on('click', (event) => { for (let item of document.querySelectorAll('.apps-categories-custom')) {
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', () => {
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-setting-live').on('change', (event) => { const displays = document.querySelectorAll('.side-menu-display')
var target = jQuery(event.target)
var name = target.attr('name')
var value = target.val()
if ('background-color-opacity' === name) { for (let display of displays) {
return $('#side-menu-background-color, #side-menu-background-color-to').trigger('change'); display.addEventListener('click', (event) => {
} else if ('dark-mode-background-color-opacity' === name) { const target = event.target
return $('#side-menu-dark-mode-background-color, #side-menu-dark-mode-background-color-to').trigger('change');
}
if (name === 'opener') { for (let d of displays) {
var url = OC.generateUrl(`/apps/side_menu/img/${value}.svg`).replace('/index.php', '') d.classList.toggle('is-active', d === display)
}
value = `url(${url})`; document.querySelector('#side-menu-always-displayed').value = target.getAttribute('data-alwaysdiplayed')
} document.querySelector('#side-menu-big-menu').value = target.getAttribute('data-bigmenu')
document.querySelector('#side-menu-side-with-categories').value = target.getAttribute('data-sidewithcategories')
})
}
if (name === 'icon-invert-filter' || name === 'icon-opacity') { for (let item of document.querySelectorAll('.apps-categories-custom')) {
value/=100; item.addEventListener('change', (event) => {
} updateAppsCategoriesCustom()
})
}
if (['dark-mode-background-color', 'dark-mode-background-color-to'].indexOf(name) > -1) { for (let item of document.querySelectorAll('.side-menu-setting-live')) {
var opacity = parseInt($('#side-menu-dark-mode-background-color-opacity').val() * 255 / 100); item.addEventListener('change', (event) => {
const target = event.target
const name = target.getAttribute('name')
value = [value, opacity.toString(16)].join(''); let value = target.value
} else if (['background-color', 'background-color-to'].indexOf(name) > -1) { let id = null
var opacity = parseInt($('#side-menu-background-color-opacity').val() * 255 / 100);
value = [value, opacity.toString(16)].join(''); 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'
}
document.documentElement.style.setProperty('--side-menu-' + name, value) 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'
}) })
jQuery('.side-menu-toggler').on('click', (event) => { try {
var target = jQuery(event.target) sortable('#categories-list .side-menu-setting-list')[0].addEventListener('sortstop', (e) => {
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 = []
jQuery('#categories-list .side-menu-setting-list-item').each(function() { for (let item of document.querySelectorAll('#categories-list .side-menu-setting-list-item')) {
value.push(jQuery(this).attr('data-id')) console.log(item.getAttribute('data-id'))
}); value.push(item.getAttribute('data-id'))
}
value = JSON.stringify(value) document.querySelector('input[name="categories-order"]').value = JSON.stringify(value)
})
jQuery('input[name="categories-order"]').val(value) } catch (e) {
} }
}); })
});
+84
View File
@@ -0,0 +1,84 @@
"Custom menu": "Uživatelsky určená nabídka"
"Enable the custom menu": "Zapnout uživatelsky určenou nabídku"
"No": "Ne"
"Yes": "Ano"
"Menu": "Nabídka"
'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.': 'Pro otevření/skrytí postranní nabídky použijte zkratku <span class="keyboard-key">Ctrl</span>+<span class="keyboard-key">o</span>. Pro pohyb po použijte klávesu <span class="keyboard-key">tab</span>.'
"Top menu": "Hlavní nabídka"
"Apps that not must be moved in the side menu": "Aplikace, které nepřesouvat do postranní nabídky"
"If there is no selection then the global configuration is applied.": "Pokud neexistuje žádný výběr, je uplatněno globální nastavení."
"Experimental": "Experimentální"
"Save": "Uložit"
"You like this app and you want to support me?": "Líbí se vám tato aplikace a chcete podpořit její vývoj?"
"Buy me a coffee ☕": "Kupte mi kafe ☕"
"Hidden": "Skryté"
"Small": "Malé"
"Normal": "Normální"
"Big": "Velké"
"Colors": "Barvy"
"Background color": "Barva pozadí"
"Background color of current app": "Barva pozadí stávající aplikace"
"Text color": "Barva textu"
"Loader": "Nástroj pro načítání"
"Icon": "Ikona"
"Same color": "Stejná barva"
"Opposite color": "Doplňková barva"
"Transparent": "Průhledné"
"Opaque": "Neprůhledné"
"Opener": "Tlačítko pro otevření"
"Default": "Výchozí"
"Default (dark)": "Výchozí (tmavé)"
"Hamburger": "Hamburger"
"Hamburger (dark)": "Hamburger (tmavé)"
"Hamburger 2": "Hamburger 2"
"Hamburger 2 (dark)": "Hamburger 2 (tmavé)"
"Before the logo": "Před logem"
"After the logo": "Za logem"
"Position": "Pozice"
"Show only the opener (hidden logo)": "Zobrazovat pouze otevírací tlačítko (logo skryto)"
"Do not display the side menu and the opener if there is no application (eg: public pages).": "Nezobrazovat postranní nabídku a její otevírací tlačítko pokud nejsou dostupné žádné aplikace (např. na veřejných stránkách)."
"Panel": "Panel"
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Otevřít nabídku při najetím ukazatelem na tlačítko nabídky (automaticky vypnuto pro dotykové obrazovky)."
"Display the big menu": "Zobrazit velkou nabídku"
"This menu is not compatible with AppOrder.": "Nabídka není kompatibilní s jinou aplikací (doplňkem) „Pořadí aplikací“."
"Display the logo": "Zobrazit logo"
"This feature is not compatible with the <code>big menu</code> display.": "Tato funkce není kompatibilní se zobrazením <code>velké nabídky</code>."
"Icons and texts": "Ikony a texty"
"Loader enabled": "Načítání zapnuto"
"Tips": "Tipy"
"Always displayed": "Vždy zobrazeno"
"The logo will be hidden when the menu is always displayed.": "Pokud je nabídka zobrazena trvale, logo bude skryto."
"This is the automatic behavior when the menu is always displayed.": "Toto je automatické chování, kdy je nabídka vždy zobrazena."
"Not compatible with touch screens.": "Nekompatibilní s dotykovými obrazovkami."
"Big menu": "Velká nabídka"
"Live preview": "Živý náhled"
"Open apps in new tab": "Otevírat aplikace v novém panelu"
"Use the global setting": "Použít globální nastavení"
"Use my selection": "Použít můj výběr"
"Show and hide the list of applications": "Zobrazit/skrýt seznam aplikací"
"Use the avatar instead of the logo": "Použít namísto loga profilový obrázek uživatele"
"You do not have permission to change the settings.": "Nemáte oprávnění měnit nastavení."
"Force this configuration to users": "Vynutit uplatnění těchto nastavení uživatelům"
"Export the configuration": "Exportovat nastavení"
"Purge the cache": "Vyprázdnit mezipaměť"
"Show the link to settings": "Zobrazit odkaz na nastavení"
"The menu is enabled by default for users": "Nabídka je ve výchozím stavu zapnutá pro uživatele"
"Except when the configuration is forced.": "S výjimkou, kdy je nastavení vynuceno."
"Apps that should not be displayed in the menu": "Aplikace, které by neměly být v nabídce zobrazeny"
"This feature is only compatible with the <code>big menu</code> display.": "Tato funkce je kompatibilní pouze s <code>velkou nabídkou</ code>."
"The logo is a link to the default app": "Logo je odkaz na výchozí aplikaci"
"Others": "Ostatní"
"Categories": "Kategorie"
"Customize sorting": "Přizpůsobit si řazení"
"Order by": "Řadit podle"
"Name": "Název"
"Customed": "Přizpůsobeno"
"Show and hide the list of categories": "Zobrazit/skrýt seznam kategorií"
"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"
"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"
+36 -31
View File
@@ -1,31 +1,31 @@
"Custom menu": "Benutzerdefiniertes Menü" "Custom menu": "Benutzerdefiniertes Menü"
"Enable the custom menu": "Aktiviere das Benutzerdefiniertes Menü" "Enable the custom menu": "Benutzerdefiniertes Menü aktivieren"
"No": "Nein" "No": "Nein"
"Yes": "Ja" "Yes": "Ja"
"Menu": "Menü" "Menu": "Menü"
'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.': 'Verwende die Tastenkombination <span class="keyboard-key">Strg</span>+<span class="keyboard-key">o</span>, um das Seitenmenü ein- und auszublenden. Verwende <span class="keyboard-key">tab</span> zum Navigieren.' '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.': 'Verwende die Tastenkombination <span class="keyboard-key">Strg</span>+<span class="keyboard-key">o</span>, um das Seitenmenü ein- und auszublenden. Verwende <span class="keyboard-key">tab</span> zum Navigieren.'
"Top menu": "Hauptmenü" "Top menu": "Obere Navigationsleiste"
"Apps that not must be moved in the side menu": "Apps, die nicht ins Seitenmenü verschoben werden müssen" "Apps that not must be moved in the side menu": "Anwendungen, die nicht ins Seitenmenü verschoben werden sollen"
"If there is no selection then the global configuration is applied.": "Wenn keine Auswahl vorhanden ist, wird die globale Konfiguration angewendet." "If there is no selection then the global configuration is applied.": "Wenn keine Auswahl vorhanden ist, wird die globale Konfiguration angewendet."
"Experimental": "Experimentell" "Experimental": "Experimentell"
"Save": "Speichern" "Save": "Speichern"
"You like this app and you want to support me?": "Du magst diese App und möchtest mich unterstützen?" "You like this app and you want to support me?": "Du magst diese Anwendung und möchtest mich unterstützen?"
"Buy me a coffee ☕": "Gib mir einen Kaffee ☕" "Buy me a coffee ☕": "Gib mir einen Kaffee aus ☕"
"Hidden": "Versteckt" "Hidden": "Ausblenden"
"Small": "Klein" "Small": "Klein"
"Normal": "Normal" "Normal": "Normal"
"Big": "Groß" "Big": "Groß"
"Colors": "Farben" "Colors": "Farben"
"Background color": "Hintergrundfarbe" "Background color": "Hintergrundfarbe"
"Background color of current app": "Hintergrundfarbe der aktuellen App" "Background color of current app": "Hintergrundfarbe der aktuellen Anwendung"
"Text color": "Textfarbe" "Text color": "Textfarbe"
"Loader": "Ladestandanzeige" "Loader": "Ladestandanzeige"
"Icon": "Symbol" "Icon": "Symbol"
"Same color": "Selbe Farbe" "Same color": "Selbe Farbe"
"Opposite color": "Gegenfarbe" "Opposite color": "Gegenfarbe"
"Transparent": "Transparent" "Transparent": "Transparent"
"Opaque": "Undurchsichtig" "Opaque": "Nicht transparent"
"Opener": "Öffner" "Opener": "Menü-Symbol"
"Default": "Standard" "Default": "Standard"
"Default (dark)": "Standard (dunkel)" "Default (dark)": "Standard (dunkel)"
"Hamburger": "Hamburger" "Hamburger": "Hamburger"
@@ -35,44 +35,49 @@
"Before the logo": "Vor dem Logo" "Before the logo": "Vor dem Logo"
"After the logo": "Nach dem Logo" "After the logo": "Nach dem Logo"
"Position": "Position" "Position": "Position"
"Show only the opener (hidden logo)": "Nur den Öffner anzeigen (verstecktes Logo)" "Show only the opener (hidden logo)": "Nur das Menü-Symbol anzeigen (Logo wird ausgeblendet)"
"Do not display the side menu and the opener if there is no application (eg: public pages).": "Zeige das Seitenmenü und den Öffner nicht an, wenn keine Anwendung vorhanden ist (z.B. bei öffentlichen Seiten)." "Do not display the side menu and the opener if there is no application (eg: public pages).": "Zeige das Seitenmenü und das Menü-Symbol nicht an, wenn keine Anwendung vorhanden ist (z.B. bei öffentlichen Seiten)."
"Panel": "Panel" "Panel": "Panel"
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Öffne das Menü, wenn die Maus über den Öffner bewegt wird (auf Touchscreens automatisch deaktiviert)." "Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Öffne das Menü, wenn die Maus über das Menü-Symbol bewegt wird (auf Touchscreens automatisch deaktiviert)."
"Display the big menu": "Großes Menü anzeigen" "Display the big menu": "Großes Menü anzeigen"
"The big menu is not compatible with AppOrder.": "Das große Menü ist nicht mit AppOrder kompatibel." "This menu is not compatible with AppOrder.": "Dieses Menü ist nicht mit <code>AppOrder</code> kompatibel."
"Display the logo": "Logo anzeigen" "Display the logo": "Logo anzeigen"
"This feature is not compatible with the <code>big menu</code> display.": "Diese Funktion ist nicht mit <code>großes Menü</code> kompatibel." "This feature is not compatible with the <code>big menu</code> display.": "Diese Funktion ist nicht mit dem <code>großen Menü</code> kompatibel."
"Icons and texts": "Symbole und Texte" "Icons and texts": "Symbole und Texte"
"Loader enabled": "Loader aktiviert" "Loader enabled": "Ladestandanzeige aktiviert"
"Tips": "Tipps" "Tips": "Tipps"
"Always displayed": "Wird immer angezeigt" "Always displayed": "Immer anzeigen"
"The logo will be hidden when the menu is always displayed.": "Das Logo wird ausgeblendet, wenn das Menü immer angezeigt wird." "The logo will be hidden when the menu is always displayed.": "Das Logo wird ausgeblendet, wenn das Menü immer angezeigt wird."
"This is the automatic behavior when the menu is always displayed.": "Dies ist das automatische Verhalten, wenn das Menü immer angezeigt wird." "This is the automatic behavior when the menu is always displayed.": "Dies ist das automatische Verhalten, wenn das Menü immer angezeigt wird."
"Not compatible with touch screens.": "Nicht kompatibel mit Touchscreens." "Not compatible with touch screens.": "Nicht kompatibel mit Touchscreens."
"Big menu": "Großes Menü" "Big menu": "Großes Menü"
"Live preview": "Live Vorschau" "Live preview": "Live-Vorschau"
"Open apps in new tab": "Öffne Apps in einem neuen Tab" "Open apps in new tab": "Öffne Anwendungen in einem neuen Tab"
"Use the global setting": "Verwende die globale Einstellung" "Use the global setting": "Verwende die globale Einstellung"
"Use my selection": "Verwende meine Auswahl" "Use my selection": "Verwende meine Auswahl"
"Show and hide the list of applications": "Ein- und Ausblenden der Anwendungsliste" "Show and hide the list of applications": "Ein- und Ausblenden der Anwendungsliste"
"Use the avatar instead of the logo": "Verwenden Sie den Avatar anstelle des Logos" "Use the avatar instead of the logo": "Avatar anstelle des Logos anzeigen"
"You do not have permission to change the settings.": "Sie haben keine Berechtigung zum Ändern der Einstellungen." "You do not have permission to change the settings.": "Du hast keine Berechtigung, die Einstellungen dieser Anwendung zu ändern."
"Force this configuration to users": "Erzwingen Sie diese Konfiguration für Benutzer" "Force this configuration to users": "Konfiguration für alle Benutzer erzwingen"
"Export the configuration": "Exportieren Sie die Konfiguration" "Export the configuration": "Konfiguration exportieren"
"Purge the cache": "Leeren Sie den Cache" "Purge the cache": "Cache leeren"
"Show the link to settings": "Zeigen Sie den Link zu den Einstellungen an" "Show the link to settings": "Link zu den Einstellungen anzeigen"
"The menu is enabled by default for users": "Das Menü ist standardmäßig für Benutzer aktiviert" "The menu is enabled by default for users": "Das Menü ist standardmäßig für alle Benutzer aktiviert"
"Except when the configuration is forced.": "Außer wenn die Konfiguration erzwungen wird." "Except when the configuration is forced.": "Gilt nicht, wenn die Konfiguration erzwungen wird."
"Apps that should not be displayed in the menu": "Apps, die nicht im Menü angezeigt werden sollen" "Apps that should not be displayed in the menu": "Anwendungen, die nicht im Menü angezeigt werden sollen"
"This feature is only compatible with the <code>big menu</code> display.": "Kompatibel mit der Anzeige <code> Großes Menü </ code>." "This feature is only compatible with the <code>big menu</code> display.": "Kompatibel mit dem <code>großen Menü</code>."
"The logo is a link to the default app": "Das Logo ist ein Link zur Standard-App" "The logo is a link to the default app": "Das Logo ist ein Link zur Standard-App"
"Others": "Andere" "Others": "Andere"
"Categories": "Kategorien" "Categories": "Kategorien"
"Customize sorting": "Sortierung anpassen" "Customize sorting": "Sortierung anpassen"
"Order by": "Sortieren nach" "Order by": "Sortieren nach"
"Name": "Name" "Name": "Name"
"Customed": "Kundenspezifisch" "Customed": "Benutzerdefiniert"
"Show and hide the list of categories": "Liste der Kategorien ein- und ausblenden" "Show and hide the list of categories": "Liste der Kategorien ein- und ausblenden"
"This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "Diese Parameter werden verwendet, wenn Dark Theme oder Breeze Dark Theme aktiviert sind." "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": "Dunkle Modusfarben" "Dark mode colors": "Farben für den dunklen Modus"
"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"
+6 -1
View File
@@ -40,7 +40,7 @@
"Panel": "Panneau" "Panel": "Panneau"
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Ouvrir le menu au passage de la souris (automatiquement désactivé sur les écrans tactiles)" "Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Ouvrir le menu au passage de la souris (automatiquement désactivé sur les écrans tactiles)"
"Display the big menu": "Afficher le menu large" "Display the big menu": "Afficher le menu large"
"The big menu is not compatible with AppOrder.": "Le menu large n'est pas compatible avec l'application AppOrder" "This menu is not compatible with AppOrder.": "Ce menu n'est pas compatible avec l'application AppOrder"
"Display the logo": "Afficher le logo" "Display the logo": "Afficher le logo"
"This feature is not compatible with the <code>big menu</code> display.": "Cette fonctionnalité n'est pas compatible avec l'affichage du menu large." "This feature is not compatible with the <code>big menu</code> display.": "Cette fonctionnalité n'est pas compatible avec l'affichage du menu large."
"Icons and texts": "Icônes et textes" "Icons and texts": "Icônes et textes"
@@ -76,3 +76,8 @@
"Show and hide the list of categories": "Afficher et masquer la liste des catégories" "Show and hide the list of categories": "Afficher et masquer la liste des catégories"
"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"
"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"
+83
View File
@@ -0,0 +1,83 @@
"Custom menu": "自定义菜单"
"Enable the custom menu": "激活自定义菜单"
"No": "取消"
"Yes": "确定"
"Menu": "菜单"
"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.": "使用快捷键 <span class=\"keyboard-key\">Ctrl<\/span>+<span class=\"keyboard-key\">o<\/span> 打开或隐藏侧边栏菜单。使用<span class=\"keyboard-key\">tab<\/span> 来导航。"
"Top menu": "顶部菜单"
"Apps that not must be moved in the side menu": "禁止在侧边栏菜单移动的应用"
"If there is no selection then the global configuration is applied.": "如不选择,将应用全局设定。"
"Experimental": "实验性"
"Save": "保存"
"You like this app and you want to support me?": "喜欢本应用并支持我一下?"
"Buy me a coffee ☕": "赏一杯咖啡 ☕ 给我"
"Hidden": "隐藏"
"Small": "小型"
"Normal": "标准"
"Big": "大型"
"Colors": "颜色"
"Background color": "背景颜色"
"Background color of current app": "当前应用的背景色"
"Text color": "文字颜色"
"Loader": "菜单指示器"
"Icon": "图标"
"Same color": "相同颜色"
"Opposite color": "相反颜色"
"Transparent": "透明"
"Opaque": "不透明"
"Opener": "容器"
"Default": "默认"
"Default (dark)": "默认(深色)"
"Hamburger": "Hamburger"
"Hamburger (dark)": "Hamburger (深色)"
"Hamburger 2": "Hamburger 2"
"Hamburger 2 (dark)": "Hamburger 2 (深色)"
"Before the logo": "在logo前"
"After the logo": "在logo后"
"Position": "位置"
"Show only the opener (hidden logo)": "只显示容器 (隐藏logo)"
"Do not display the side menu and the opener if there is no application (eg: public pages).": "N如果没有应用,不显示侧边栏菜单和容器 (例如 : 公共页面)。"
"Panel": "面板"
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "鼠标悬停时打开菜单 (触摸屏时将自动禁用)"
"Display the big menu": "显示大型菜单"
"This menu is not compatible with AppOrder.": "型菜单与应用顺序不兼容"
"Display the logo": "显示logo"
"This feature is not compatible with the <code>big menu<\/code> display.": "此功能与显示<code>大型菜单<\/code>不兼容。"
"Icons and texts": "图标与文字"
"Loader enabled": "菜单指示器已激活"
"Tips": "技巧"
"Always displayed": "一直显示"
"The logo will be hidden when the menu is always displayed.": "一直显示菜单时logo将被隐藏。"
"This is the automatic behavior when the menu is always displayed.": "一直显示菜单时的自动动作。"
"Not compatible with touch screens.": "与触屏不兼容。"
"Big menu": "大型菜单"
"Live preview": "实时预览"
"Open apps in new tab": "在新标签中打开应用"
"Use the global setting": "使用全局设定"
"Use my selection": "使用自定义设定"
"Show and hide the list of applications": "显示或隐藏应用列表"
"Use the avatar instead of the logo": "使用头像代替logo"
"You do not have permission to change the settings.": "没有更改设置的权限。"
"Force this configuration to users": "强制用户使用此设置"
"Export the configuration": "导出设置"
"Purge the cache": "清除缓存"
"Show the link to settings": "显示设置链接"
"The menu is enabled by default for users": "用户的默认菜单已激活"
"Except when the configuration is forced.": "除非设置被强制使用。"
"Apps that should not be displayed in the menu": "禁止在菜单中显示的应用"
"This feature is only compatible with the <code>big menu<\/code> display.": "此功能只和<code>大型菜单<\/code>兼容。"
"The logo is a link to the default app": "logo链接到默认应用"
"Others": "其他"
"Categories": "类别"
"Customize sorting": "自定义顺序"
"Order by": "排序规则"
"Name": "名称"
"Customed": "自定义"
"Show and hide the list of categories": "显示或隐藏类别列表"
"This parameters are used when Dark theme or Breeze Dark Theme are enabled.": "此参数将应用于暗黑主题激活时。"
"Dark mode colors": "暗黑模式颜色"
"With categories": "有类别"
"Custom categories": "自定义类别"
"Customize application categories": "自定义应用程序类别"
"Apps only visible in the top menu": "应用程序仅在顶部菜单中可见"
"Apps visible in the top and side menus": "顶部和侧边菜单中可见的应用程序"
+1 -1
View File
@@ -8,7 +8,7 @@
<?php endforeach; ?> <?php endforeach; ?>
} }
<?php if (empty($_['top-menu-apps'])): ?> <?php if (empty($_['top-menu-apps']) && empty($_['top-side-menu-apps'])): ?>
#appmenu { #appmenu {
display: none; display: none;
} }
+29 -17
View File
@@ -1,21 +1,19 @@
var alwaysDisplayed = function() { const alwaysDisplayed = function() {
var elements = document.querySelectorAll('*'); const elements = querySelectorAll('*')
var fixedElements = [] const fixedElements = []
for (var i in elements) {
var element = elements[i]
for (var element of elements) {
if (typeof element !== 'object') { if (typeof element !== 'object') {
continue continue
} }
var position = window.getComputedStyle(element, null).getPropertyValue('position'); const position = window.getComputedStyle(element, null).getPropertyValue('position')
if (position !== 'fixed') { if (position !== 'fixed') {
continue continue
} }
var id = element.getAttribute('id') const id = element.getAttribute('id')
if (id === 'header' || id === 'side-menu' || id === 'side-menu-loader') { if (id === 'header' || id === 'side-menu' || id === 'side-menu-loader') {
continue continue
@@ -25,7 +23,21 @@ var alwaysDisplayed = function() {
continue continue
} }
if (jQuery(element).parents('#side-menu').length) { let elementIsInSideMenu = false
let parent = element.parentNode
while (parent && !elementIsInSideMenu) {
try {
if (parent.getAttribute('id') === 'side-menu') {
elementIsInSideMenu = true
}
} catch (e) {
}
parent = parent.parentNode
}
if (elementIsInSideMenu) {
continue continue
} }
@@ -33,19 +45,19 @@ var alwaysDisplayed = function() {
} }
for (var i in fixedElements) { for (var i in fixedElements) {
var element = fixedElements[i] const element = fixedElements[i]
var computedStyle = window.getComputedStyle(element, null) const computedStyle = window.getComputedStyle(element, null)
var left = computedStyle.getPropertyValue('left') const left = computedStyle.getPropertyValue('left')
var right = computedStyle.getPropertyValue('right') const right = computedStyle.getPropertyValue('right')
if (right !== '0px') { if (right !== '0px') {
var intValue = parseInt(left.replace('px', '')) const intValue = parseInt(left.replace('px', '')) + 50
element.style.setProperty('transform', 'translateX(' + (intValue + 50) + 'px)') element.style.setProperty('transform', 'translateX(' + intValue.toString() + 'px)')
} }
} }
} }
let content = document.getElementById('content') const content = querySelector('#content')
if (content && content.classList.contains('app-settings')) { if (content && content.classList.contains('app-settings')) {
let loaded = false let loaded = false
@@ -56,7 +68,7 @@ if (content && content.classList.contains('app-settings')) {
} }
const observer = new MutationObserver(() => { const observer = new MutationObserver(() => {
if (loaded) { if (loaded) {
return; return
} }
const element = content.querySelector('#app-category-your-apps') || content.querySelector('#app-navigation ul') const element = content.querySelector('#app-category-your-apps') || content.querySelector('#app-navigation ul')
+8 -9
View File
@@ -1,15 +1,14 @@
var pageLoader = jQuery('<div id="side-menu-loader">') let pageLoader = createElement('div', {id: 'side-menu-loader'})
var pageLoaderBar = jQuery('<div id="side-menu-loader-bar">') let pageLoaderBar = createElement('div', {id: 'side-menu-loader-bar'})
body.append(pageLoader) pageLoader.appendChild(pageLoaderBar)
pageLoader.append(pageLoaderBar) querySelector('body').appendChild(pageLoader)
var pageLoaderValue = 0 let pageLoaderValue = 0
$(window).on('beforeunload', function() {
setInterval(function() {
pageLoaderBar.width(pageLoaderValue.toString() + '%')
window.addEventListener('beforeunload', () => {
setInterval(() => {
pageLoaderBar.style.width = pageLoaderValue.toString() + '%'
pageLoaderValue = Math.min(pageLoaderValue + .2, 100) pageLoaderValue = Math.min(pageLoaderValue + .2, 100)
}, 25) }, 25)
}) })
+144 -100
View File
@@ -1,60 +1,91 @@
var menuCache = null let menuCache = null
var updateTopMenu = function() { const breakpointMobileWidth = 1024
var breakpointMobileWidth = 1024 const usePercentualAppMenuLimit = 0.8
var menu = jQuery('#appmenu') const minAppsDesktop = 8
var apps = menu.find('li')
var minAppsDesktop = 8
var usePercentualAppMenuLimit = 0.8
var isMobile = jQuery(window).width() < breakpointMobileWidth
var lastShownApp = null
var appShown = []
var moreApps = jQuery('#more-apps')
var navigation = jQuery('#navigation')
var navigationApps = jQuery('#apps ul')
var appCount = null
var currentMenuCache = menu.html() + menu.next().html() const handleMenuClick = (e, icon) => {
let element = e.target
if (currentMenuCache === menuCache) { while (element.tagName !== 'LI') {
element = element.parentNode
}
const a = querySelector('a', element)
if (a.getAttribute('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey) {
for (let tag of ['svg', 'div']) {
let el = querySelector(tag, element)
if (el) {
el.remove()
}
}
const loader = createElement('div', {'class': icon})
a.insertBefore(loader, querySelector('span', a))
}
}
const updateTopMenu = function() {
const isMobile = window.innerWidth < breakpointMobileWidth
const menu = querySelector('#appmenu')
const moreApps = querySelector('#more-apps')
const navigation = querySelector('#navigation')
const navigationApps = querySelector('#apps ul')
let apps = querySelectorAll('li', menu)
let lastShownApp = null
let appShown = []
if ((menu.innerHTML + menu.nextSibling.innerHTML) === menuCache) {
return return
} }
navigationApps.html('') navigationAppsHtml = ''
apps.each(function(i, app) { for (let app of apps) {
var dataId = app.getAttribute('data-id') const dataId = app.getAttribute('data-id')
if (dataId === null) { if (dataId === null) {
return continue
} }
if (topMenuApps.indexOf(dataId) === -1) { if (topMenuApps.indexOf(dataId) === -1 && topSideMenuApps.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) {
jQuery(app).children('a').attr('target', '_blank'); querySelector('a', app).setAttribute('target', '_blank')
} }
})
var rightHeaderWidth = jQuery('.header-right').outerWidth()
var headerWidth = jQuery('header').outerWidth()
var availableWidth = headerWidth - jQuery('#nextcloud').outerWidth()
- jQuery('#header .side-menu-opener').outerWidth()
- (rightHeaderWidth > 230 ? rightHeaderWidth : 230)
if (!isMobile) {
availableWidth = availableWidth * usePercentualAppMenuLimit
} }
appCount = Math.floor(availableWidth / jQuery('#appmenu li').width()) navigationApps.innerHTML = navigationAppsHtml
const rightHeaderWidth = querySelector('.header-right').offsetWidth
const headerWidth = querySelector('header').offsetWidth
let availableWidth = headerWidth
availableWidth -= nextcloud.offsetWidth
availableWidth -= querySelector('#header .side-menu-opener').offsetWidth
availableWidth -= rightHeaderWidth > 230 ? rightHeaderWidth : 230
availableWidth *= isMobile ? usePercentualAppMenuLimit : 1
let appCount = Math.floor(availableWidth / querySelector('#appmenu li:not(.hidden)').offsetWidth)
if (isMobile && appCount > minAppsDesktop) { if (isMobile && appCount > minAppsDesktop) {
appCount = minAppsDesktop appCount = minAppsDesktop
@@ -62,111 +93,124 @@ var updateTopMenu = function() {
appCount = minAppsDesktop appCount = minAppsDesktop
} }
if (appCount === 0) { menu.style.opacity = 1
menu.addClass('hidden')
}
menu.removeClass('hidden')
menu.css('opacity', 1)
if (appShown.length - 1 - appCount >= 1) { if (appShown.length - 1 - appCount >= 1) {
appCount-- appCount--
} }
moreApps.find('a').removeClass('active') for (let item of querySelectorAll('a', moreApps)) {
item.classList.remove('active')
}
var k = 0 let k = 0
var notInHeader = 0 let notInHeader = 0
var name
jQuery(appShown).each(function(i, app) { for (let app of appShown) {
app = jQuery(app) const name = app.getAttribute('data-id')
name = app.data('id') const li = querySelector('#apps li[data-id=' + name + '].app-external-site')
if (k < appCount && appCount > 0) { if (k < appCount && appCount > 0) {
app.removeClass('hidden') app.classList.remove('hidden')
lastShownApp = app li.classList.add('in-header')
jQuery('#apps li[data-id=' + name + '].app-external-site').addClass('in-header') lastShownApp = app
} else { } else {
app.addClass('hidden') app.classList.add('hidden')
li.classList.remove('in-header')
notInHeader++ notInHeader++
jQuery('#apps li[data-id=' + name + '].app-external-site').removeClass('in-header') const a = querySelector('a', app)
if (appCount > 0 && app.children('a').hasClass('active')) { if (appCount > 0 && a.classList.contains('active')) {
lastShownApp.addClass('hidden') lastShownApp.classList.add('hidden')
app.removeClass('hidden') app.classList.remove('hidden')
notInHeader++ notInHeader++
jQuery('#apps li[data-id=' + name + '].app-external-site') li.classList.add('in-header')
.removeClass('in-header')
.addClass('in-header')
} }
} }
k++ k++
}) }
// Hack for https://github.com/nextcloud/server/blob/23b0b63c213f5b31eecae817ffd4a9e26f6624d0/core/src/components/MainMenu.js#L74-L96 // Hack for:
menu.undelegate('li:not(#more-apps) > a', 'click') // - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
menu.delegate('li:not(#more-apps) > a', 'click', function(e) { // - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
var a = $(e.target) jQuery(menu).undelegate('li:not(#more-apps) > a', 'click')
jQuery(navigation).undelegate('a', 'click')
if (!a.is('a')) { const confs = [
a = a.closest('a') {
items: querySelectorAll('#navigation li'),
icon: 'icon-loading-small'
},
{
items: querySelectorAll('li:not(#more-apps)', menu),
icon: OCA.Theming && OCA.Theming.inverted ? 'icon-loading-small' : 'icon-loading-small-dark'
},
]
for (let conf of confs) {
for (let item of conf.items) {
item.addEventListener('click', (e) => {
handleMenuClick(e, conf.icon)
})
} }
}
if (a.attr('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey && a.parent('#more-apps').length === 0) { for (let app of querySelectorAll('#apps li.app-external-site')) {
a.find('svg').remove() const appId = app.getAttribute('data-id')
a.find('div').remove()
a.prepend(jQuery('<div/>').addClass(
OCA.Theming && OCA.Theming.inverted
? 'icon-loading-small'
: 'icon-loading-small-dark'
))
window.location.href = a.attr('href') if (app.classList.contains('in-header')) {
} for (let defs of querySelectorAll('svg defs', app)) {
}) defs.remove()
}
jQuery('#apps li.app-external-site').each(function(i, app) {
app = jQuery(app)
var appId = app.attr('data-id')
if (app.hasClass('in-header')) {
app.find('svg').find('defs').remove()
} else { } else {
var svg = app.find('svg'); const svg = querySelector('svg', app)
if (svg.find('defs').length > 0) { if (querySelectorAll('svg defs', app).length > 0) {
return; continue
} }
var defs = ` const defs = `
<defs> <defs>
<filter id="invertMenuMore-${appId}"> <filter id="invertMenuMore-${appId}">
<feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix> <feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix>
</filter> </filter>
</defs>` </defs>`
svg.prepend(defs) svg.innerHTML = defs + svg.innerHTML
svg.find('image').attr('filter', `url(#invertMenuMore-${appId})`)
var html = svg.get(0).innerHTML.replace(/fecolormatrix/g, 'feColorMatrix'); for (let image of querySelectorAll('image', svg)) {
image.setAttribute('filter', `url(#invertMenuMore-${appId})`)
}
svg.html(html) svg.innerHTML = svg.innerHTML.replace(/fecolormatrix/g, 'feColorMatrix')
} }
})
if (notInHeader === 0) {
moreApps.hide()
navigation.hide()
} else {
moreApps.show()
} }
menuCache = menu.html() + menu.next().html() if (notInHeader === 0) {
moreApps.style.display = 'none'
navigation.style.display = 'none'
} else {
moreApps.style.display = 'flex'
}
menuCache = menu.innerHTML + menu.nextSibling.innerHTML
} }
setInterval(updateTopMenu, 50) for (let i = 0; i < 3000; i+= 100) {
setTimeout(updateTopMenu, i)
}
let resizeTimeout = null;
window.addEventListener('resize', () => {
if (resizeTimeout !== null) {
clearTimeout(resizeTimeout)
}
resizeTimeout = setTimeout(updateTopMenu, 100)
})
+135 -65
View File
@@ -1,59 +1,110 @@
(function() { <?php
var sideMenuContainer = jQuery('<div id="side-menu-container">')
var sideMenuOpener = jQuery('<button class="side-menu-opener"></button>')
var sideMenu = jQuery('<div id="side-menu">')
var body = jQuery('body')
var html = jQuery('html')
var isTouchDevice = window.matchMedia("(pointer: coarse)").matches
<?php if ($_['big-menu']): ?> $display = 'default';
sideMenu.attr('data-bigmenu', '1')
if ($_['always-displayed']) {
$display = 'always-displayed';
} elseif ($_['big-menu']) {
$display = 'big-menu';
} elseif ($_['side-with-categories']) {
$display = 'side-with-categories';
}
?>
(function() {
const querySelector = function(selector, element) {
if (element) {
return element.querySelector(selector)
}
return document.querySelector(selector)
}
const querySelectorAll = function(selector, element) {
if (element) {
return element.querySelectorAll(selector)
}
return document.querySelectorAll(selector)
}
const createElement = function(tagName, attributes) {
const element = document.createElement(tagName)
if (typeof attributes === 'object') {
for (let i in attributes) {
element.setAttribute(i, attributes[i])
}
}
return element
}
const sideMenuContainer = createElement('div', {id: 'side-menu-container'})
const sideMenuOpener = createElement('button', {'class': 'side-menu-opener'})
const sideMenu = createElement('div', {id: 'side-menu'})
const body = querySelector('body')
const html = querySelector('html')
const nextcloud = querySelector('#nextcloud')
const isTouchDevice = window.matchMedia("(pointer: coarse)").matches
const targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>
<?php if ($display === 'big-menu'): ?>
sideMenu.setAttribute('data-bigmenu', '1')
<?php elseif ($display === 'side-with-categories'): ?>
sideMenu.setAttribute('data-sidewithcategories', '1')
<?php endif; ?> <?php endif; ?>
var targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>; querySelector('body').addEventListener('side-menu.apps', (e) => {
const apps = e.detail.apps;
body.on('side-menu.apps', function(e, apps) {
<?php if ($_['hide-when-no-apps']): ?> <?php if ($_['hide-when-no-apps']): ?>
sideMenu = jQuery('#side-menu') const sideMenu = querySelector('#side-menu')
if (apps.length === 0) { if (apps.length === 0) {
sideMenu.removeClass('open') sideMenu.classList.remove('open')
sideMenu.addClass('hide') sideMenu.classList.add('hide')
sideMenuOpener.addClass('hide') sideMenuOpener.classList.add('hide')
} else { } else {
sideMenu.removeClass('hide') sideMenu.classList.remove('hide')
sideMenuOpener.removeClass('hide') sideMenuOpener.classList.remove('hide')
} }
<?php if ($_['always-displayed'] && !$_['big-menu']): ?> <?php if ($display === 'always-displayed'): ?>
if (apps.length === 0) { if (apps.length === 0) {
html.removeClass('side-menu-always-displayed'); html.classList.remove('side-menu-always-displayed')
} else { } else {
html.addClass('side-menu-always-displayed'); html.classList.add('side-menu-always-displayed')
} }
<?php endif; ?> <?php endif; ?>
<?php else: ?> <?php else: ?>
<?php if ($_['always-displayed'] && !$_['big-menu']): ?> <?php if ($display === 'always-displayed'): ?>
if (apps.length === 0) { if (apps.length === 0) {
html.removeClass('side-menu-always-displayed'); html.classList.remove('side-menu-always-displayed')
} else { } else {
html.addClass('side-menu-always-displayed'); html.classList.add('side-menu-always-displayed')
} }
<?php endif; ?> <?php endif; ?>
<?php endif; ?> <?php endif; ?>
}) })
body.on('side-menu.ready', function() { body.addEventListener('side-menu.ready', () => {
sideMenu = jQuery('#side-menu') const sideMenu = querySelector('#side-menu')
const headerMenuOpener = querySelector('#header .side-menu-opener')
const sideMenuOpener = querySelectorAll('#side-menu .side-menu-opener')
var headerMenuOpener = jQuery('#header .side-menu-opener') sideMenuFocus = () => {
var sideMenuOpener = jQuery('#side-menu .side-menu-opener') let a = querySelector('.side-menu-app.active a', sideMenu)
sideMenuFocus = function() { if (!a) {
var a = sideMenu.find('.side-menu-app.active a') return
}
if (a.length === 0) { if (a.length === 0) {
a = sideMenu.find('.side-menu-app:first-child a') a = querySelector('.side-menu-app:first-child a', sideMenu)
} }
if (a.length > 0) { if (a.length > 0) {
@@ -61,84 +112,103 @@
} }
} }
<?php if ($_['opener-hover'] || ($_['always-displayed'] && !$_['big-menu'])): ?> <?php if ($_['opener-hover']): ?>
var sideMenuMouseLeave = function() { const sideMenuMouseLeave = () => {
sideMenu sideMenu.classList.remove('open')
.removeClass('open') sideMenu.removeEventListener('mouseleave', sideMenuMouseLeave)
.off('mouseleave', sideMenuMouseLeave)
} }
var sideMenuMouseEnter = function() { const sideMenuMouseEnter = () => {
sideMenu.on('mouseleave', sideMenuMouseLeave) sideMenu.addEventListener('mouseleave', sideMenuMouseLeave)
} }
var sideMenuOpenerMouseEnter = function() { const sideMenuOpenerMouseEnter = () => {
sideMenu sideMenu.classList.add('open')
.addClass('open') sideMenu.addEventListener('mouseenter', sideMenuMouseEnter)
.on('mouseenter', sideMenuMouseEnter)
sideMenuFocus() sideMenuFocus()
} }
if (!isTouchDevice) { if (!isTouchDevice) {
<?php if ($_['opener-hover']): ?> <?php if ($_['opener-hover']): ?>
headerMenuOpener.on('mouseenter', sideMenuOpenerMouseEnter) headerMenuOpener.addEventListener('mouseenter', sideMenuOpenerMouseEnter)
sideMenu.addClass('hide-opener') sideMenu.classList.add('hide-opener')
<?php endif ?> <?php endif ?>
sideMenu.on('mouseleave', sideMenuMouseLeave) sideMenu.addEventListener('mouseleave', sideMenuMouseLeave)
sideMenu.on('mouseenter', sideMenuOpenerMouseEnter) sideMenu.addEventListener('mouseenter', sideMenuOpenerMouseEnter)
} }
<?php endif; ?> <?php endif; ?>
headerMenuOpener.on('click', function() { headerMenuOpener.addEventListener('click', () => {
sideMenu.addClass('open') sideMenu.classList.add('open')
sideMenu.find('.side-menu-app.active a').focus()
const a = querySelector('.side-menu-app.active a', sideMenu)
if (a !== null) {
a.focus()
}
}) })
<?php if ($_['always-displayed'] && !$_['big-menu']): ?> for (let opener of sideMenuOpener) {
sideMenuOpener.on('click', function() { opener.addEventListener('click', () => {
sideMenu.toggleClass('open') <?php if ($display === 'always-displayed'): ?>
sideMenu.classList.toggle('open')
<?php else: ?>
sideMenu.classList.remove('open')
<?php endif; ?>
}) })
<?php else: ?> }
sideMenuOpener.on('click', function() {
sideMenu.removeClass('open')
})
<?php endif; ?>
jQuery(document).keydown(function(e) { document.addEventListener('keydown', (e) => {
var key = e.key || e.keyCode var key = e.key || e.keyCode
if ((key === 'o' || key === 79) && e.ctrlKey === true) { if ((key === 'o' || key === 79) && e.ctrlKey === true) {
e.preventDefault() e.preventDefault()
sideMenu.toggleClass('open') sideMenu.classList.toggle('open')
sideMenuFocus() sideMenuFocus()
} }
}) })
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.append(sideMenuContainer) body.appendChild(sideMenuContainer)
sideMenuContainer.append(sideMenu) sideMenuContainer.appendChild(sideMenu)
<?php if ($_['loader-enabled'] === true): ?> <?php if ($_['loader-enabled'] === true): ?>
<?php require_once __DIR__.'/_loaderEnabled.js'; ?> <?php require_once __DIR__.'/_loaderEnabled.js'; ?>
<?php endif; ?> <?php endif; ?>
<?php if ($_['opener-position'] === 'before'): ?> <?php if ($_['opener-position'] === 'before'): ?>
sideMenuOpener.insertBefore('#nextcloud') nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud)
<?php else: ?> <?php else: ?>
sideMenuOpener.insertAfter('#nextcloud') nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud.nextSibling)
<?php endif; ?> <?php endif; ?>
<?php if (!empty($_['top-menu-apps'])): ?> <?php if (!empty($_['top-menu-apps']) || !empty($_['top-side-menu-apps'])): ?>
var topMenuApps = <?php echo json_encode($_['top-menu-apps']); ?>; const topMenuApps = <?php echo json_encode($_['top-menu-apps']), "\n"; ?>
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; ?>
<?php if ($_['always-displayed'] && !$_['big-menu']): ?> <?php if ($display === 'always-displayed'): ?>
<?php require_once __DIR__.'/_alwaysDisplayed.js'; ?> <?php require_once __DIR__.'/_alwaysDisplayed.js'; ?>
<?php endif; ?> <?php endif; ?>
})(); })();
+141 -22
View File
@@ -20,6 +20,7 @@ use OCP\IURLGenerator;
use OCP\IConfig; use OCP\IConfig;
use OCA\SideMenu\AppInfo\Application; use OCA\SideMenu\AppInfo\Application;
vendor_script('side_menu', 'html5sortable.min');
script('side_menu', 'admin'); script('side_menu', 'admin');
style('side_menu', 'admin'); style('side_menu', 'admin');
@@ -39,7 +40,6 @@ $choicesSizes = [
]; ];
?> ?>
<div id="side-menu-section"> <div id="side-menu-section">
<div class="section"> <div class="section">
<h2> <h2>
@@ -217,7 +217,7 @@ $choicesSizes = [
</h2> </h2>
<p> <p>
<?php p($l->t('This parameters are used when Dark theme or Breeze Dark Theme are enabled.')); ?> <?php echo $l->t('This parameters are used when Dark theme or Breeze Dark Theme are enabled.'); ?>
</p> </p>
<div class="side-menu-setting-table"> <div class="side-menu-setting-table">
@@ -441,64 +441,95 @@ $choicesSizes = [
<?php p($l->t('Panel')); ?> <?php p($l->t('Panel')); ?>
</h2> </h2>
<?php
$displays = [
'default' => !$_['always-displayed'] && !$_['big-menu'] && !$_['side-with-categories'],
'always-displayed' => $_['always-displayed'] && !$_['big-menu'] && !$_['side-with-categories'],
'side-with-categories' => $_['side-with-categories'] && !$_['always-displayed'] && !$_['big-menu'],
'big-menu' => $_['big-menu'] && !$_['always-displayed'] && !$_['side-with-categories'],
];
?>
<div> <div>
<label> <label>
<?php p($l->t('Default')); ?> <?php p($l->t('Default')); ?>
</label> </label>
</div> </div>
<?php
$displays = [
'default' => !$_['always-displayed'] && !$_['big-menu'],
'always-displayed' => $_['always-displayed'] && !$_['big-menu'],
'big-menu' => $_['big-menu'],
];
?>
<p> <p>
<img <img
class="side-menu-display <?php echo $displays['default'] ? 'is-active' : '' ?>" class="side-menu-display <?php echo $displays['default'] ? 'is-active' : '' ?>"
data-alwaysdiplayed="0" data-alwaysdiplayed="0"
data-bigmenu="0" data-bigmenu="0"
data-sidewithcategories="0"
src="<?php print_unescaped(image_path('side_menu', 'admin/layout-default.svg')); ?>" alt="<?php p($l->t('Default')); ?>"> src="<?php print_unescaped(image_path('side_menu', 'admin/layout-default.svg')); ?>" alt="<?php p($l->t('Default')); ?>">
</p> </p>
<div>
<label>
<?php p($l->t('With categories')); ?>
</label>
</div>
<p><em><?php echo $l->t('This menu is not compatible with AppOrder.'); ?></em></p>
<p>
<img
class="side-menu-display <?php echo $displays['side-with-categories'] ? 'is-active' : '' ?>"
data-alwaysdiplayed="0"
data-bigmenu="0"
data-sidewithcategories="1"
src="<?php print_unescaped(image_path('side_menu', 'admin/layout-side-with-categories.svg')); ?>" alt="<?php p($l->t('With categories')); ?>">
</p>
<div> <div>
<label for="side-menu-opener"> <label for="side-menu-opener">
<?php p($l->t('Big menu')); ?> <?php p($l->t('Big menu')); ?>
</label> </label>
</div> </div>
<p><em><?php echo $l->t('This menu is not compatible with AppOrder.'); ?></em></p>
<p><em><?php p($l->t('The big menu is not compatible with AppOrder.')); ?></em></p>
<p> <p>
<img <img
class="side-menu-display <?php echo $displays['big-menu'] ? 'is-active' : '' ?>" class="side-menu-display <?php echo $displays['big-menu'] ? 'is-active' : '' ?>"
data-alwaysdiplayed="0" data-alwaysdiplayed="0"
data-bigmenu="1" data-bigmenu="1"
data-sidewithcategories="0"
src="<?php print_unescaped(image_path('side_menu', 'admin/layout-big-menu.svg')); ?>" alt="<?php p($l->t('Big menu')); ?>"> src="<?php print_unescaped(image_path('side_menu', 'admin/layout-big-menu.svg')); ?>" alt="<?php p($l->t('Big menu')); ?>">
</p> </p>
<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>
<p> <p>
<img <img
class="side-menu-display <?php echo $displays['always-displayed'] ? 'is-active' : '' ?>" class="side-menu-display <?php echo $displays['always-displayed'] ? 'is-active' : '' ?>"
data-alwaysdiplayed="1" data-alwaysdiplayed="1"
data-bigmenu="0" data-bigmenu="0"
data-sidewithcategories="0"
src="<?php print_unescaped(image_path('side_menu', 'admin/layout-always-displayed.svg')); ?>" alt="<?php p($l->t('Always displayed')); ?>"> src="<?php print_unescaped(image_path('side_menu', 'admin/layout-always-displayed.svg')); ?>" alt="<?php p($l->t('Always displayed')); ?>">
</p> </p>
<input type="hidden" class="side-menu-setting" name="always-displayed" id="side-menu-always-displayed" value="<?php echo (int) $_['always-displayed'] ?>"> <input
<input type="hidden" class="side-menu-setting" name="big-menu" id="side-menu-big-menu" value="<?php echo (int) $_['big-menu'] ?>"> type="hidden"
class="side-menu-setting"
name="always-displayed"
id="side-menu-always-displayed"
value="<?php echo (int) $_['always-displayed'] ?>"
>
<input
type="hidden"
class="side-menu-setting"
name="big-menu"
id="side-menu-big-menu"
value="<?php echo (int) $_['big-menu'] ?>"
>
<input
type="hidden"
class="side-menu-setting"
name="side-with-categories"
id="side-menu-side-with-categories"
value="<?php echo (int) $_['side-with-categories'] ?>"
>
<br> <br>
@@ -699,7 +730,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 that not must be moved in the side menu')); ?> <?php p($l->t('Apps only visible in the top 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="#_">
@@ -728,6 +759,39 @@ $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>
@@ -758,6 +822,61 @@ $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')); ?>
<small><span class="warning"><?php p($l->t('Experimental')); ?></span></small>
</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')); ?>
@@ -767,7 +886,7 @@ $choicesSizes = [
🖱️ <?php p($l->t('Show and hide the list of categories')); ?> 🖱️ <?php p($l->t('Show and hide the list of categories')); ?>
</a> </a>
<div class="side-menu-setting" data-name="categories" id="categories-list" style="display: none"> <div id="categories-list" style="display: none">
<ul class="side-menu-setting-list"> <ul class="side-menu-setting-list">
<?php foreach ($_['categories'] as $key => $label): ?> <?php foreach ($_['categories'] as $key => $label): ?>
<li data-id="<?php echo $key; ?>" class="side-menu-setting-list-item"> <li data-id="<?php echo $key; ?>" class="side-menu-setting-list-item">
+139 -93
View File
@@ -16,6 +16,7 @@
* 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');
@@ -25,8 +26,6 @@ $choicesYesNo = [
]; ];
?> ?>
<div id="side-menu-section"> <div id="side-menu-section">
<?php if ($_['force']): ?> <?php if ($_['force']): ?>
<div class="section"> <div class="section">
@@ -44,71 +43,73 @@ $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> <div class="side-menu-setting-table">
<select id="side-menu-enabled" name="enabled" class="side-menu-setting" data-personal> <div class="side-menu-setting-row">
<?php foreach ($choicesYesNo as $label => $value): ?> <div class="side-menu-setting-label">
<option value="<?php echo $value ?>" <?php if ($value === $_['enabled']): ?>selected<?php endif; ?>> <?php p($l->t('Enable the custom menu')); ?>
<?php echo $l->t($label); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="side-menu-target-blank">
<?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>
<?php endforeach; ?> <div class="side-menu-setting-form">
<select id="side-menu-enabled" name="enabled" class="side-menu-setting" data-personal>
<?php foreach ($choicesYesNo as $label => $value): ?>
<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 class="side-menu-setting-table">
<div class="side-menu-setting-row">
<div class="side-menu-setting-label">
<?php p($l->t('Open apps in new tab')); ?>
</div>
<div class="side-menu-setting-form">
<?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>
@@ -116,40 +117,85 @@ $choicesYesNo = [
<h2> <h2>
<?php p($l->t('Top menu')); ?> <?php p($l->t('Top menu')); ?>
</h2> </h2>
<div>
<label for="side-menu-top-menu-apps"> <div class="side-menu-setting-table">
<?php p($l->t('Apps that not must be moved in the side menu')); ?> <div class="side-menu-setting-row">
</label> <div class="side-menu-setting-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>
<p> <div class="side-menu-setting-table">
<em> <div class="side-menu-setting-row">
<?php p($l->t('If there is no selection then the global configuration is applied.')); ?> <div class="side-menu-setting-label">
</em> <?php p($l->t('Apps visible in the top and side menus')); ?>
</p> <p>
<em>
<p> <?php p($l->t('If there is no selection then the global configuration is applied.')); ?>
<a class="side-menu-toggler" data-target="#top-menu-apps" href="#_"> </em>
🖱️ <?php p($l->t('Show and hide the list of applications')); ?> </p>
</a>
</p>
<div class="side-menu-setting" data-name="top-menu-apps" data-checkbox data-personal id="top-menu-apps" style="display: none">
<?php foreach ($_['apps'] as $app): ?>
<div>
<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>
</div> </div>
<?php endforeach; ?> <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">
<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 $app['name'] ?>
</label>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div> </div>
</div> </div>
<?php endif ?> <?php endif ?>
+2
View File
File diff suppressed because one or more lines are too long