summaryrefslogtreecommitdiffstats
path: root/core/src/init.js
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2019-05-10 13:38:11 +0200
committerChristoph Wurst <christoph@winzerhof-wurst.at>2019-05-10 13:47:21 +0200
commit51d49c3134c9acf7e2daba5bcc8c87e14a7548f1 (patch)
tree2c74c588fbcfeb1bb3766ad4a97ab9e4e21dfdc1 /core/src/init.js
parent855486d7c14ac41c3b952591cc4acbaed996c45a (diff)
downloadnextcloud-server-51d49c3134c9acf7e2daba5bcc8c87e14a7548f1.tar.gz
nextcloud-server-51d49c3134c9acf7e2daba5bcc8c87e14a7548f1.zip
Move initCore to the bundle
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'core/src/init.js')
-rw-r--r--core/src/init.js307
1 files changed, 307 insertions, 0 deletions
diff --git a/core/src/init.js b/core/src/init.js
new file mode 100644
index 00000000000..ebf99ffd640
--- /dev/null
+++ b/core/src/init.js
@@ -0,0 +1,307 @@
+/*
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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/>.
+ */
+
+import _ from 'underscore'
+import $ from 'jquery'
+import moment from 'moment'
+
+import {initSessionHeartBeat} from './session-heartbeat'
+import OC from './OC/index'
+import {setUp as setUpContactsMenu} from './components/ContactsMenu'
+import {setUp as setUpMainMenu} from './components/MainMenu'
+import {setUp as setUpUserMenu} from './components/UserMenu'
+import PasswordConfirmation from './OC/password-confirmation'
+
+const resizeMenu = () => {
+ const appList = $('#appmenu li')
+ const rightHeaderWidth = $('.header-right').outerWidth()
+ const headerWidth = $('header').outerWidth()
+ const usePercentualAppMenuLimit = 0.33
+ const minAppsDesktop = 8
+ let availableWidth = headerWidth - $('#nextcloud').outerWidth() - (rightHeaderWidth > 210 ? rightHeaderWidth : 210)
+ const isMobile = $(window).width() < 768
+ if (!isMobile) {
+ availableWidth = availableWidth * usePercentualAppMenuLimit
+ }
+ let appCount = Math.floor((availableWidth / $(appList).width()))
+ if (isMobile && appCount > minAppsDesktop) {
+ appCount = minAppsDesktop
+ }
+ if (!isMobile && appCount < minAppsDesktop) {
+ appCount = minAppsDesktop
+ }
+
+ // show at least 2 apps in the popover
+ if (appList.length - 1 - appCount >= 1) {
+ appCount--
+ }
+
+ $('#more-apps a').removeClass('active')
+ let lastShownApp
+ for (let k = 0; k < appList.length - 1; k++) {
+ const name = $(appList[k]).data('id')
+ if (k < appCount) {
+ $(appList[k]).removeClass('hidden')
+ $('#apps li[data-id=' + name + ']').addClass('in-header')
+ lastShownApp = appList[k]
+ } else {
+ $(appList[k]).addClass('hidden')
+ $('#apps li[data-id=' + name + ']').removeClass('in-header')
+ // move active app to last position if it is active
+ if (appCount > 0 && $(appList[k]).children('a').hasClass('active')) {
+ $(lastShownApp).addClass('hidden')
+ $('#apps li[data-id=' + $(lastShownApp).data('id') + ']').removeClass('in-header')
+ $(appList[k]).removeClass('hidden')
+ $('#apps li[data-id=' + name + ']').addClass('in-header')
+ }
+ }
+ }
+
+ // show/hide more apps icon
+ if ($('#apps li:not(.in-header)').length === 0) {
+ $('#more-apps').hide()
+ $('#navigation').hide()
+ } else {
+ $('#more-apps').show()
+ }
+}
+
+const initLiveTimestamps = () => {
+ // Update live timestamps every 30 seconds
+ setInterval(() => {
+ $('.live-relative-timestamp').each(function () {
+ $(this).text(OC.Util.relativeModifiedDate(parseInt($(this).attr('data-timestamp'), 10)))
+ })
+ }, 30 * 1000)
+}
+
+/**
+ * Initializes core
+ */
+export const initCore = () => {
+ /**
+ * Set users locale to moment.js as soon as possible
+ */
+ moment.locale(OC.getLocale())
+
+ const userAgent = window.navigator.userAgent
+ const msie = userAgent.indexOf('MSIE ')
+ const trident = userAgent.indexOf('Trident/')
+ const edge = userAgent.indexOf('Edge/')
+
+ if (msie > 0 || trident > 0) {
+ // (IE 10 or older) || IE 11
+ $('html').addClass('ie')
+ } else if (edge > 0) {
+ // for edge
+ $('html').addClass('edge')
+ }
+
+ // css variables fallback for IE
+ if (msie > 0 || trident > 0 || edge > 0) {
+ console.info('Legacy browser detected, applying css vars polyfill')
+ cssVars({
+ watch: true,
+ // set edge < 16 as incompatible
+ onlyLegacy: !(/Edge\/([0-9]{2})\./i.test(navigator.userAgent)
+ && parseInt(/Edge\/([0-9]{2})\./i.exec(navigator.userAgent)[1]) < 16)
+ })
+ }
+
+ $(window).on('unload.main', () => OC._unloadCalled = true)
+ $(window).on('beforeunload.main', () => {
+ // super-trick thanks to http://stackoverflow.com/a/4651049
+ // in case another handler displays a confirmation dialog (ex: navigating away
+ // during an upload), there are two possible outcomes: user clicked "ok" or
+ // "cancel"
+
+ // first timeout handler is called after unload dialog is closed
+ setTimeout(() => {
+ OC._userIsNavigatingAway = true
+
+ // second timeout event is only called if user cancelled (Chrome),
+ // but in other browsers it might still be triggered, so need to
+ // set a higher delay...
+ setTimeout(() => {
+ if (!OC._unloadCalled) {
+ OC._userIsNavigatingAway = false
+ }
+ }, 10000)
+ }, 1)
+ })
+ $(document).on('ajaxError.main', function (event, request, settings) {
+ if (settings && settings.allowAuthErrors) {
+ return
+ }
+ OC._processAjaxError(request)
+ })
+
+ initSessionHeartBeat();
+
+ OC.registerMenu($('#expand'), $('#expanddiv'), false, true)
+
+ // toggle for menus
+ $(document).on('mouseup.closemenus', event => {
+ const $el = $(event.target)
+ if ($el.closest('.menu').length || $el.closest('.menutoggle').length) {
+ // don't close when clicking on the menu directly or a menu toggle
+ return false
+ }
+
+ OC.hideMenus()
+ })
+
+ setUpMainMenu()
+ setUpUserMenu()
+ setUpContactsMenu()
+
+ // move triangle of apps dropdown to align with app name triangle
+ // 2 is the additional offset between the triangles
+ if ($('#navigation').length) {
+ $('#header #nextcloud + .menutoggle').on('click', () => {
+ $('#menu-css-helper').remove()
+ const caretPosition = $('.header-appname + .icon-caret').offset().left - 2
+ if (caretPosition > 255) {
+ // if the app name is longer than the menu, just put the triangle in the middle
+ return
+ } else {
+ $('head').append('<style id="menu-css-helper">#navigation:after { left: ' + caretPosition + 'px }</style>')
+ }
+ })
+ $('#header #appmenu .menutoggle').on('click', () => {
+ $('#appmenu').toggleClass('menu-open')
+ if ($('#appmenu').is(':visible')) {
+ $('#menu-css-helper').remove()
+ }
+ })
+ }
+
+ $(window).resize(resizeMenu)
+ setTimeout(resizeMenu, 0)
+
+ // just add snapper for logged in users
+ // and if the app doesn't handle the nav slider itself
+ if ($('#app-navigation').length && !$('html').hasClass('lte9')
+ && !$('#app-content').hasClass('no-snapper')) {
+
+ // App sidebar on mobile
+ const snapper = new Snap({
+ element: document.getElementById('app-content'),
+ disable: 'right',
+ maxPosition: 300, // $navigation-width
+ minDragDistance: 100
+ })
+
+ $('#app-content').prepend('<div id="app-navigation-toggle" class="icon-menu" style="display:none" tabindex="0"></div>')
+
+ const toggleSnapperOnButton = () => {
+ if (snapper.state().state === 'left') {
+ snapper.close()
+ } else {
+ snapper.open('left')
+ }
+ }
+
+ $('#app-navigation-toggle').click(toggleSnapperOnButton)
+ $('#app-navigation-toggle').keypress(e => {
+ if (e.which === 13) {
+ toggleSnapperOnButton()
+ }
+ })
+
+ // close sidebar when switching navigation entry
+ const $appNavigation = $('#app-navigation')
+ $appNavigation.delegate('a, :button', 'click', event => {
+ const $target = $(event.target)
+ // don't hide navigation when changing settings or adding things
+ if ($target.is('.app-navigation-noclose') ||
+ $target.closest('.app-navigation-noclose').length) {
+ return
+ }
+ if ($target.is('.app-navigation-entry-utils-menu-button') ||
+ $target.closest('.app-navigation-entry-utils-menu-button').length) {
+ return
+ }
+ if ($target.is('.add-new') ||
+ $target.closest('.add-new').length) {
+ return
+ }
+ if ($target.is('#app-settings') ||
+ $target.closest('#app-settings').length) {
+ return
+ }
+ snapper.close()
+ })
+
+ let navigationBarSlideGestureEnabled = false
+ let navigationBarSlideGestureAllowed = true
+ let navigationBarSlideGestureEnablePending = false
+
+ OC.allowNavigationBarSlideGesture = () => {
+ navigationBarSlideGestureAllowed = true
+
+ if (navigationBarSlideGestureEnablePending) {
+ snapper.enable()
+
+ navigationBarSlideGestureEnabled = true
+ navigationBarSlideGestureEnablePending = false
+ }
+ }
+
+ OC.disallowNavigationBarSlideGesture = () => {
+ navigationBarSlideGestureAllowed = false
+
+ if (navigationBarSlideGestureEnabled) {
+ const endCurrentDrag = true
+ snapper.disable(endCurrentDrag)
+
+ navigationBarSlideGestureEnabled = false
+ navigationBarSlideGestureEnablePending = true
+ }
+ }
+
+ const toggleSnapperOnSize = () => {
+ if ($(window).width() > 768) {
+ snapper.close()
+ snapper.disable()
+
+ navigationBarSlideGestureEnabled = false
+ navigationBarSlideGestureEnablePending = false
+ } else if (navigationBarSlideGestureAllowed) {
+ snapper.enable()
+
+ navigationBarSlideGestureEnabled = true
+ navigationBarSlideGestureEnablePending = false
+ } else {
+ navigationBarSlideGestureEnablePending = true
+ }
+ }
+
+ $(window).resize(_.debounce(toggleSnapperOnSize, 250))
+
+ // initial call
+ toggleSnapperOnSize()
+
+ }
+
+ initLiveTimestamps()
+ PasswordConfirmation.init()
+}