Browse Source

Merge pull request #9050 from nextcloud/feat/noid/prepare-for-desktop

Prepare for desktop build
pull/9118/head
Joas Schilling 3 years ago
committed by GitHub
parent
commit
6bd3a5e73e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      .eslintrc.js
  2. 8
      src/App.vue
  3. 33
      src/env.d.ts
  4. 22
      src/main.js
  5. 22
      src/mixins/sessionIssueHandler.js
  6. 30
      src/router/router.js
  7. 1
      src/test-setup.js
  8. 14
      src/utils/signaling.js
  9. 82
      webpack.common.config.js
  10. 100
      webpack.config.js

7
.eslintrc.js

@ -2,6 +2,13 @@ module.exports = {
extends: [
'@nextcloud',
],
globals: {
// @nextcloud/webpack-vue-config globals
appName: 'readonly',
appVersion: 'readonly',
// Desktop build globals
IS_DESKTOP: 'readonly',
},
rules: {
'import/newline-after-import': 1,
'import/no-named-as-default-member': 0,

8
src/App.vue

@ -430,8 +430,10 @@ export default {
},
async mounted() {
// see browserCheck mixin
this.checkBrowser()
if (!IS_DESKTOP) {
// see browserCheck mixin
this.checkBrowser()
}
// Check sidebar status in previous sessions
if (BrowserStorage.getItem('sidebarOpen') === 'false') {
this.$store.dispatch('hideSidebar')
@ -562,7 +564,7 @@ export default {
}
// When a conversation is opened directly, the "Talk - " part is
// missing from the title
if (this.defaultPageTitle.indexOf(t('spreed', 'Talk') + ' - ') !== 0) {
if (!IS_DESKTOP && this.defaultPageTitle.indexOf(t('spreed', 'Talk') + ' - ') !== 0) {
this.defaultPageTitle = t('spreed', 'Talk') + ' - ' + this.defaultPageTitle
}
}

33
src/env.d.ts

@ -0,0 +1,33 @@
/*
* @copyright Copyright (c) 2023 Grigorii Shartsev <grigorii.shartsev@nextcloud.com>
*
* @author Grigorii Shartsev <grigorii.shartsev@nextcloud.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/>.
*/
declare global {
// @nextcloud/webpack-vue-config build globals
const appName: string
const appVersion: string
/**
* Build constant to divide build for web app and desktop client
*/
const IS_DESKTOP: false
}
export {}

22
src/main.js

@ -52,16 +52,18 @@ import 'leaflet/dist/leaflet.css'
// eslint-disable-next-line
import 'leaflet-defaulticon-compatibility'
// CSP config for webpack dynamic chunk loading
// eslint-disable-next-line
__webpack_nonce__ = btoa(getRequestToken())
// Correct the root of the app for chunk loading
// OC.linkTo matches the apps folders
// OC.generateUrl ensure the index.php (or not)
// We do not want the index.php since we're loading files
// eslint-disable-next-line
__webpack_public_path__ = generateFilePath('spreed', '', 'js/')
if (!IS_DESKTOP) {
// CSP config for webpack dynamic chunk loading
// eslint-disable-next-line
__webpack_nonce__ = btoa(getRequestToken())
// Correct the root of the app for chunk loading
// OC.linkTo matches the apps folders
// OC.generateUrl ensure the index.php (or not)
// We do not want the index.php since we're loading files
// eslint-disable-next-line
__webpack_public_path__ = generateFilePath('spreed', '', 'js/')
}
Vue.prototype.t = translate
Vue.prototype.n = translatePlural

22
src/mixins/sessionIssueHandler.js

@ -48,21 +48,27 @@ const sessionIssueHandler = {
SessionStorage.removeItem('joined_conversation')
// Need to delay until next tick, otherwise the PreventUnload is still being triggered
// Putting the window in front with the warning and irritating the user
this.$nextTick(() => {
// FIXME: can't use router push as it somehow doesn't clean up
// fully and leads the other instance where "Join here" was clicked
// to redirect to "not found"
window.location = url
})
if (!IS_DESKTOP) {
this.$nextTick(() => {
// FIXME: can't use router push as it somehow doesn't clean up
// fully and leads the other instance where "Join here" was clicked
// to redirect to "not found"
window.location = generateUrl(url)
})
} else {
// TODO: DESKTOP: to not hard-code the address?
window.location = `/talk_window/#${url}`
}
},
duplicateSessionTriggered() {
this.redirectTo(generateUrl('/apps/spreed/duplicate-session'))
// TODO: DESKTOP: should close the duplicated window instead of redirect
this.redirectTo('/apps/spreed/duplicate-session')
},
deletedSessionTriggered() {
// workaround: force page refresh to kill stray WebRTC connections
this.redirectTo(generateUrl('/apps/spreed/not-found'))
this.redirectTo('/apps/spreed/not-found')
},
},
}

30
src/router/router.js

@ -33,21 +33,33 @@ import WelcomeView from '../views/WelcomeView.vue'
Vue.use(Router)
const webRootWithIndexPHP = getRootUrl() + '/index.php'
const doesURLContainIndexPHP = window.location.pathname.startsWith(webRootWithIndexPHP)
const base = generateUrl('/', {}, {
noRewrite: doesURLContainIndexPHP,
})
export default new Router({
mode: 'history',
/**
* Generate base url for Talk Web app based on server's root
*
* @return {string} Vue Router base url
*/
function generateTalkWebBasePath() {
// if index.php is in the url AND we got this far, then it's working:
// let's keep using index.php in the url
base,
const webRootWithIndexPHP = getRootUrl() + '/index.php'
const doesURLContainIndexPHP = window.location.pathname.startsWith(webRootWithIndexPHP)
return generateUrl('/', {}, {
noRewrite: doesURLContainIndexPHP,
})
}
export default new Router({
// On desktop (Electron) app is open via file:// protocol - History API is not available and no base path
mode: !IS_DESKTOP ? 'history' : 'hash',
base: !IS_DESKTOP ? generateTalkWebBasePath() : '',
linkActiveClass: 'active',
routes: [
{
path: '/apps/spreed',
// On desktop add index path as root page
alias: IS_DESKTOP ? '/' : undefined,
name: 'root',
component: WelcomeView,
props: true,

1
src/test-setup.js

@ -77,6 +77,7 @@ global.OCP = {
disableKeyboardShortcuts: () => false,
},
}
global.IS_DESKTOP = false
// Work around missing "URL.createObjectURL" (which is used in the code but not
// relevant for the tests) in jsdom: https://github.com/jsdom/jsdom/issues/1721

14
src/utils/signaling.js

@ -282,10 +282,16 @@ Signaling.Base.prototype.joinCall = function(token, flags, silent) {
}.bind(this))
.catch(function() {
reject(new Error())
// Server maintenance, lobby kicked in, or room not found.
// We first redirect to the conversation again and that
// will then show the proper error message to the user.
window.location = generateUrl('call/' + token)
if (!IS_DESKTOP) {
// Server maintenance, lobby kicked in, or room not found.
// We first redirect to the conversation again and that
// will then show the proper error message to the user.
window.location = generateUrl('call/' + token)
} else {
// TODO: Is it true, reload is equal to generateUrl('call/' + token) here?
// Or can we always just reload the page?
window.location.reload()
}
})
})
}

82
webpack.common.config.js

@ -0,0 +1,82 @@
/*
* @copyright Copyright (c) 2022 Grigorii Shartsev <grigorii.shartsev@nextcloud.com>
*
* @author Grigorii Shartsev <grigorii.shartsev@nextcloud.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/>.
*/
const BabelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
const nextcloudWebpackRules = require('@nextcloud/webpack-vue-config/rules')
// Edit JS rule
nextcloudWebpackRules.RULE_JS.exclude = BabelLoaderExcludeNodeModulesExcept([
'@nextcloud/event-bus',
'ansi-regex',
'color.js',
'fast-xml-parser',
'hot-patcher',
'nextcloud-vue-collections',
'semver',
'strip-ansi',
'tributejs',
'vue-resize',
'webdav',
])
module.exports = {
module: {
rules: [
// Reuse @nextcloud/webpack-vue-config/rules
...Object.values(nextcloudWebpackRules),
{
/**
* webrtc-adapter main module does no longer provide
* "module.exports", which is expected by some elements using it
* (like "attachmediastream"), so it needs to be added back with
* a plugin.
*/
test: /node_modules[\\/]webrtc-adapter[\\/].*\.js$/,
loader: 'babel-loader',
options: {
plugins: ['add-module-exports'],
presets: [
/**
* From "add-module-exports" documentation:
* "webpack doesn't perform commonjs transformation for
* codesplitting. Need to set commonjs conversion."
*/
['@babel/env', { modules: 'commonjs' }],
],
},
},
{
test: /\.wasm$/i,
type: 'asset/resource',
},
{
test: /\.tflite$/i,
type: 'asset/resource',
},
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' },
},
],
},
}

100
webpack.config.js

@ -1,82 +1,40 @@
const path = require('path')
const webpackConfig = require('@nextcloud/webpack-vue-config')
const webpackRules = require('@nextcloud/webpack-vue-config/rules')
const BabelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
const path = require('node:path')
webpackConfig.entry = {
'admin-settings': path.join(__dirname, 'src', 'mainAdminSettings.js'),
collections: path.join(__dirname, 'src', 'collections.js'),
main: path.join(__dirname, 'src', 'main.js'),
recording: path.join(__dirname, 'src', 'mainRecording.js'),
'files-sidebar': [
path.join(__dirname, 'src', 'mainFilesSidebar.js'),
path.join(__dirname, 'src', 'mainFilesSidebarLoader.js'),
],
'public-share-auth-sidebar': path.join(__dirname, 'src', 'mainPublicShareAuthSidebar.js'),
'public-share-sidebar': path.join(__dirname, 'src', 'mainPublicShareSidebar.js'),
flow: path.join(__dirname, 'src', 'flow.js'),
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
deck: path.join(__dirname, 'src', 'deck.js'),
maps: path.join(__dirname, 'src', 'maps.js'),
}
const webpack = require('webpack')
const { merge } = require('webpack-merge')
webpackConfig.output.assetModuleFilename = '[name][ext]?v=[contenthash]'
const nextcloudWebpackConfig = require('@nextcloud/webpack-vue-config')
// Edit JS rule
webpackRules.RULE_JS.exclude = BabelLoaderExcludeNodeModulesExcept([
'@nextcloud/event-bus',
'ansi-regex',
'color.js',
'fast-xml-parser',
'hot-patcher',
'nextcloud-vue-collections',
'semver',
'strip-ansi',
'tributejs',
'vue-resize',
'webdav',
])
const commonWebpackConfig = require('./webpack.common.config.js')
// Replaces rules array
webpackConfig.module.rules = Object.values(webpackRules)
// Rules from @nextcloud/webpack-vue-config/rules already added by commonWebpackConfig
nextcloudWebpackConfig.module.rules = []
webpackConfig.module.rules.push({
/**
* webrtc-adapter main module does no longer provide
* "module.exports", which is expected by some elements using it
* (like "attachmediastream"), so it needs to be added back with
* a plugin.
*/
test: /node_modules\/webrtc-adapter\/.*\.js$/,
loader: 'babel-loader',
options: {
plugins: ['add-module-exports'],
presets: [
/**
* From "add-module-exports" documentation:
* "webpack doesn't perform commonjs transformation for
* codesplitting. Need to set commonjs conversion."
*/
['@babel/env', { modules: 'commonjs' }],
module.exports = merge(nextcloudWebpackConfig, commonWebpackConfig, {
entry: {
'admin-settings': path.join(__dirname, 'src', 'mainAdminSettings.js'),
collections: path.join(__dirname, 'src', 'collections.js'),
main: path.join(__dirname, 'src', 'main.js'),
recording: path.join(__dirname, 'src', 'mainRecording.js'),
'files-sidebar': [
path.join(__dirname, 'src', 'mainFilesSidebar.js'),
path.join(__dirname, 'src', 'mainFilesSidebarLoader.js'),
],
'public-share-auth-sidebar': path.join(__dirname, 'src', 'mainPublicShareAuthSidebar.js'),
'public-share-sidebar': path.join(__dirname, 'src', 'mainPublicShareSidebar.js'),
flow: path.join(__dirname, 'src', 'flow.js'),
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
deck: path.join(__dirname, 'src', 'deck.js'),
maps: path.join(__dirname, 'src', 'maps.js'),
},
})
webpackConfig.module.rules.push({
test: /\.wasm$/i,
type: 'asset/resource',
})
output: {
assetModuleFilename: '[name][ext]?v=[contenthash]',
},
webpackConfig.module.rules.push({
test: /\.tflite$/i,
type: 'asset/resource',
})
plugins: [
new webpack.DefinePlugin({ IS_DESKTOP: false }),
],
webpackConfig.module.rules.push({
test: /\.worker\.js$/,
use: { loader: 'worker-loader' },
cache: true,
})
webpackConfig.cache = true
module.exports = webpackConfig
Loading…
Cancel
Save