Skip to content

Commit

Permalink
fix(sidebar): reduce initial loading size of Talk files sidebar
Browse files Browse the repository at this point in the history
Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
  • Loading branch information
Antreesy committed Feb 9, 2024
1 parent 357aeb0 commit a7feca1
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 36 deletions.
96 changes: 96 additions & 0 deletions src/FilesSidebarTabLoader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!--
- @copyright Copyright (c) 2024 Maksim Sukharev <antreesy.web@gmail.com>
-
- @author Maksim Sukharev <antreesy.web@gmail.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/>.
-->
<template>
<div ref="talkChatPreload" class="talkChatTab">
<div class="emptycontent ui-not-ready-placeholder">
<div class="icon icon-loading" />
</div>
</div>
</template>

<script>
export default {
name: 'FilesSidebarTabLoader',

data() {
return {
sidebarState: OCA.Files.Sidebar.state,
}
},

computed: {
isChatTheActiveTab() {
// FIXME check for empty active tab is currently needed because the
// activeTab is not set when opening the sidebar from the "Details"
// action (which opens the first tab, which is the Chat tab).
return !this.sidebarState.activeTab || this.sidebarState.activeTab === 'chat'
},
},

watch: {
isChatTheActiveTab: {
immediate: true,
handler(value) {
if (value === true && OCA.Talk?.isFirstLoad === true) {
OCA.Talk.isFirstLoad = false
this.replaceAppInTab()
}
},
},
},

methods: {
async replaceAppInTab() {
try {
if (OCA.Files.Sidebar) {
const module = await import(/* webpackChunkName: "files-sidebar-main" */ './mainFilesSidebar.js')
module.mountSidebar(this.$refs.talkChatPreload)
}
} catch (error) {
console.error(error)
}
},
},
}
</script>

<style scoped>
.talkChatTab {
height: 100%;

display: flex;
flex-grow: 1;
flex-direction: column;
}

.emptycontent {
/* Override default top margin set in server and center vertically
* instead. */
margin-top: unset;

height: 100%;

display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
26 changes: 9 additions & 17 deletions src/mainFilesSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ import vOutsideEvents from 'vue-outside-events'
import VueShortKey from 'vue-shortkey'
import Vuex from 'vuex'

import { getRequestToken } from '@nextcloud/auth'
import { translate, translatePlural } from '@nextcloud/l10n'
import { generateFilePath } from '@nextcloud/router'

import FilesSidebarCallViewApp from './FilesSidebarCallViewApp.vue'
import FilesSidebarTabApp from './FilesSidebarTabApp.vue'

import './init.js'
import store from './store/index.js'
import FilesSidebarCallView from './views/FilesSidebarCallView.js'

// Leaflet icon patch
import 'leaflet/dist/leaflet.css'
Expand All @@ -48,17 +47,6 @@ import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility
// 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/')

Vue.prototype.t = translate
Vue.prototype.n = translatePlural
Vue.prototype.OC = OC
Expand Down Expand Up @@ -87,12 +75,16 @@ const newTab = () => new Vue({
render: h => h(FilesSidebarTabApp),
})

if (!window.OCA.Talk) {
window.OCA.Talk = {}
}
Object.assign(window.OCA.Talk, {
fileInfo: null,
newCallView,
newTab,
store,
})

export const mountSidebar = (mountEl) => {
if (OCA.Files?.Sidebar) {
OCA.Files.Sidebar.registerSecondaryView(new FilesSidebarCallView())
OCA.Talk.tabInstance = OCA.Talk.newTab()
OCA.Talk.tabInstance.$mount(mountEl)
}
}
70 changes: 52 additions & 18 deletions src/mainFilesSidebarLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,50 +20,80 @@
*
*/

import './init.js'
import FilesSidebarCallView from './views/FilesSidebarCallView.js'
import Vue from 'vue'

import { getRequestToken } from '@nextcloud/auth'
import { generateFilePath } from '@nextcloud/router'

import FilesSidebarTabLoader from './FilesSidebarTabLoader.vue'

// 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.OC = OC
Vue.prototype.OCA = OCA

const loaderTab = () => new Vue({
id: 'talk-chat-tab',
render: h => h(FilesSidebarTabLoader),
})

const isEnabled = function(fileInfo) {
if (fileInfo && !fileInfo.isDirectory()) {
return true
}

const token = OCA.Talk.store.getters.getToken()
const token = OCA.Talk.store?.getters.getToken()

// If the Talk tab can not be displayed then the current conversation is
// left; this must be done here because "setFileInfo" will not get
// called with the new file if the tab can not be displayed.
if (token) {
OCA.Talk.store.dispatch('leaveConversation', { token })
OCA.Talk.store?.dispatch('leaveConversation', { token })
}

OCA.Talk.store.dispatch('updateTokenAndFileIdForToken', {
OCA.Talk.store?.dispatch('updateTokenAndFileIdForToken', {
newToken: null,
newFileId: null,
})

return false
}

// It might be enough to keep the instance only in the Tab object itself,
// without using a shared variable that can be destroyed if a new tab is
// mounted and the previous one was not destroyed yet, as the tabs seem to
// always be properly destroyed. However, this is how it is done for tabs in
// server, so it is done here too just to be safe.
let tabInstance = null
if (!window.OCA.Talk) {
window.OCA.Talk = {}
}
Object.assign(window.OCA.Talk, {
fileInfo: null,
loaderTab,
isFirstLoad: true,
// It might be enough to keep the instance only in the Tab object itself,
// without using a shared variable that can be destroyed if a new tab is
// mounted and the previous one was not destroyed yet, as the tabs seem to
// always be properly destroyed. However, this is how it is done for tabs in
// server, so it is done here too just to be safe.
tabInstance: null,
})

window.addEventListener('DOMContentLoaded', () => {
if (OCA.Files && OCA.Files.Sidebar) {
OCA.Files.Sidebar.registerSecondaryView(new FilesSidebarCallView())
OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab({
id: 'chat',
name: t('spreed', 'Chat'),
icon: 'icon-talk',
enabled: isEnabled,

async mount(el, fileInfo, context) {
if (tabInstance) {
tabInstance.$destroy()
if (OCA.Talk.tabInstance) {
OCA.Talk.tabInstance.$destroy()
}

// Dirty hack to force the style on parent component
Expand All @@ -73,16 +103,20 @@ window.addEventListener('DOMContentLoaded', () => {
tabChat.style.padding = '0'

OCA.Talk.fileInfo = this.fileInfo
tabInstance = OCA.Talk.newTab()
tabInstance.$mount(el)
if (OCA.Talk.isFirstLoad === true) {
OCA.Talk.tabInstance = OCA.Talk.loaderTab()
} else {
OCA.Talk.tabInstance = OCA.Talk.newTab()
}
OCA.Talk.tabInstance.$mount(el)
},
update(fileInfo) {
OCA.Talk.fileInfo = fileInfo
},
destroy() {
OCA.Talk.fileInfo = null
tabInstance.$destroy()
tabInstance = null
OCA.Talk.tabInstance.$destroy()
OCA.Talk.tabInstance = null
},
}))
}
Expand Down
1 change: 0 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ module.exports = mergeWithRules({
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'),
Expand Down

0 comments on commit a7feca1

Please sign in to comment.