mirror of https://github.com/nextcloud/server.git
Cleanup ie and old edge properties
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>pull/26358/head
parent
d5edcf8c95
commit
bd303388e3
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copyright 2021 John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OC\Core\Controller;
|
||||||
|
|
||||||
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Response;
|
||||||
|
use OCP\AppFramework\Http\TemplateResponse;
|
||||||
|
use OCP\IRequest;
|
||||||
|
use OCP\Util;
|
||||||
|
|
||||||
|
class UnsupportedBrowserController extends Controller {
|
||||||
|
public function __construct(IRequest $request) {
|
||||||
|
parent::__construct('core', $request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @PublicPage
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function index(): Response {
|
||||||
|
Util::addScript('core', 'unsupported-browser');
|
||||||
|
Util::addStyle('core', 'icons');
|
||||||
|
return new TemplateResponse('core', 'unsupportedbrowser', [], TemplateResponse::RENDER_AS_ERROR);
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* @copyright Copyright (c) 2016 John Molakvoæ <skjnldsv@protonmail.com>
|
|
||||||
*
|
|
||||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
|
||||||
*
|
|
||||||
* @license AGPL-3.0-or-later
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
|
|
||||||
|
|
||||||
if (!Element.prototype.matches) {
|
|
||||||
Element.prototype.matches
|
|
||||||
= Element.prototype.msMatchesSelector
|
|
||||||
|| Element.prototype.webkitMatchesSelector
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Element.prototype.closest) {
|
|
||||||
Element.prototype.closest = function(s) {
|
|
||||||
let el = this
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (el.matches(s)) return el
|
|
||||||
el = el.parentElement || el.parentNode
|
|
||||||
} while (el !== null && el.nodeType === 1)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @copyright 2021 John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @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 { getUserAgentRegExp } from 'browserslist-useragent-regexp'
|
||||||
|
// eslint-disable-next-line node/no-extraneous-import
|
||||||
|
import browserslist from 'browserslist'
|
||||||
|
import browserslistConfig from '@nextcloud/browserslist-config'
|
||||||
|
|
||||||
|
// Generate a regex that matches user agents to detect incompatible browsers
|
||||||
|
export const supportedBrowsersRegExp = getUserAgentRegExp({ allowHigherVersions: true, browsers: browserslistConfig })
|
||||||
|
export const supportedBrowsers = browserslist(browserslistConfig)
|
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @copyright 2021 John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @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 { generateUrl } from '@nextcloud/router'
|
||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
import { browserStorageKey } from './utils/RedirectUnsupportedBrowsers.js'
|
||||||
|
import browserStorage from './services/BrowserStorageService.js'
|
||||||
|
import UnsupportedBrowser from './views/UnsupportedBrowser.vue'
|
||||||
|
|
||||||
|
// If the ignore token is set, redirect
|
||||||
|
if (browserStorage.getItem(browserStorageKey) === 'true') {
|
||||||
|
window.location = generateUrl('/')
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Vue({
|
||||||
|
el: '#unsupported-browser',
|
||||||
|
// eslint-disable-next-line vue/match-component-file-name
|
||||||
|
name: 'UnsupportedBrowserRoot',
|
||||||
|
render: h => h(UnsupportedBrowser),
|
||||||
|
})
|
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* @copyright 2021 John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @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 { generateUrl } from '@nextcloud/router'
|
||||||
|
|
||||||
|
import { supportedBrowsersRegExp } from '../services/BrowsersListService.js'
|
||||||
|
import browserStorage from '../services/BrowserStorageService.js'
|
||||||
|
import logger from '../services/LoggerService.js'
|
||||||
|
|
||||||
|
const redirectPath = '/unsupported'
|
||||||
|
export const browserStorageKey = 'unsupported-browser-ignore'
|
||||||
|
|
||||||
|
const isBrowserOverridden = browserStorage.getItem(browserStorageKey) === 'true'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the current browser user agent against our official browserslist config
|
||||||
|
* and redirect if unsupported
|
||||||
|
*/
|
||||||
|
export const testSupportedBrowser = function() {
|
||||||
|
if (supportedBrowsersRegExp.test(navigator.userAgent)) {
|
||||||
|
logger.debug('this browser is officially supported ! 🚀')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If incompatible BUT ignored, let's keep going
|
||||||
|
if (isBrowserOverridden) {
|
||||||
|
logger.debug('this browser is NOT supported but has been manually overridden ! ⚠️')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If incompatible, NOT overridden AND NOT already on the warning page,
|
||||||
|
// redirect to the unsupported warning page
|
||||||
|
if (window.location.pathname.indexOf(redirectPath) === -1) {
|
||||||
|
window.location = generateUrl(redirectPath)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,191 @@
|
|||||||
|
<!--
|
||||||
|
- @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
-
|
||||||
|
- @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
|
-
|
||||||
|
- @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 class="content-unsupported-browser guest-box">
|
||||||
|
<NcEmptyContent>
|
||||||
|
{{ t('core', 'This browser is not supported') }}
|
||||||
|
<template #icon>
|
||||||
|
<Web />
|
||||||
|
</template>
|
||||||
|
<template #action>
|
||||||
|
<div>
|
||||||
|
<h2>
|
||||||
|
{{ t('core', 'Please upgrade to a more recent browser') }}
|
||||||
|
</h2>
|
||||||
|
<NcButton class="content-unsupported-browser__continue" type="primary" @click="forceBrowsing">
|
||||||
|
{{ t('core', 'Continue with this outdated browser') }}
|
||||||
|
</NcButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="content-unsupported-browser__list">
|
||||||
|
<h3>{{ t('core', 'Supported versions') }}</h3>
|
||||||
|
<li v-for="browser in formattedBrowsersList" :key="browser">
|
||||||
|
{{ browser }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</NcEmptyContent>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { generateUrl } from '@nextcloud/router'
|
||||||
|
import { translate as t, translatePlural as n } from '@nextcloud/l10n'
|
||||||
|
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||||
|
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent'
|
||||||
|
import Web from 'vue-material-design-icons/Web'
|
||||||
|
|
||||||
|
import { browserStorageKey } from '../utils/RedirectUnsupportedBrowsers.js'
|
||||||
|
import { supportedBrowsers } from '../services/BrowsersListService.js'
|
||||||
|
import browserStorage from '../services/BrowserStorageService.js'
|
||||||
|
import logger from '../services/LoggerService.js'
|
||||||
|
|
||||||
|
logger.debug('Supported browsers', { supportedBrowsers })
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'UnsupportedBrowser',
|
||||||
|
components: {
|
||||||
|
Web,
|
||||||
|
NcButton,
|
||||||
|
NcEmptyContent,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
agents: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
isMobile() {
|
||||||
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter out or include mobile/desktop browsers depending
|
||||||
|
* on the current user platform/device
|
||||||
|
*/
|
||||||
|
filteredSupportedBrowsers() {
|
||||||
|
return supportedBrowsers.filter(browser => {
|
||||||
|
if (!browser) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isMobile) {
|
||||||
|
return this.isMobileBrowser(browser)
|
||||||
|
}
|
||||||
|
return !this.isMobileBrowser(browser)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
formattedBrowsersList() {
|
||||||
|
const list = {}
|
||||||
|
|
||||||
|
// supportedBrowsers is generated by webpack at compilation time
|
||||||
|
this.filteredSupportedBrowsers.forEach(browser => {
|
||||||
|
const [id, version] = browser.split(' ')
|
||||||
|
if (!list[id] || list[id] < parseFloat(version, 10)) {
|
||||||
|
list[id] = parseFloat(version, 10)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return Object.keys(list).map(id => {
|
||||||
|
if (!this.agents[id]?.browser) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = list[id]
|
||||||
|
const name = this.agents[id]?.browser
|
||||||
|
return this.t('core', '{name} version {version} and above', {
|
||||||
|
name, version,
|
||||||
|
})
|
||||||
|
}).filter(entry => entry !== null)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
async beforeMount() {
|
||||||
|
// Dynamic load big list of user agents
|
||||||
|
// eslint-disable-next-line node/no-extraneous-import
|
||||||
|
const { agents } = await import('caniuse-lite')
|
||||||
|
this.agents = agents
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
t,
|
||||||
|
n,
|
||||||
|
|
||||||
|
// Set the flag allowing this browser and redirect to home
|
||||||
|
forceBrowsing() {
|
||||||
|
browserStorage.setItem(browserStorageKey, true)
|
||||||
|
window.location = generateUrl('/')
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect if the browserslist browser is a mobile one
|
||||||
|
* https://github.com/browserslist/browserslist#query-composition
|
||||||
|
*
|
||||||
|
* @param {string} browser a valid browserlist browser. e.g `and_chr 90`
|
||||||
|
*/
|
||||||
|
isMobileBrowser(browser) {
|
||||||
|
browser = browser.toLowerCase()
|
||||||
|
return browser.includes('and_')
|
||||||
|
|| browser.includes('android')
|
||||||
|
|| browser.includes('ios_')
|
||||||
|
|| browser.includes('mobile')
|
||||||
|
|| browser.includes('_mob')
|
||||||
|
|| browser.includes('samsung')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.content-unsupported-browser {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 400px;
|
||||||
|
max-width: 90vw;
|
||||||
|
margin: auto;
|
||||||
|
padding: 30px;
|
||||||
|
|
||||||
|
.empty-content {
|
||||||
|
margin: 0;
|
||||||
|
&::v-deep .empty-content__icon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__continue {
|
||||||
|
display: block;
|
||||||
|
margin: 20px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__list {
|
||||||
|
margin-top: 60px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
li {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1 @@
|
|||||||
|
<div id="unsupported-browser"></div>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue