Some time ago I created an unpublished app that allows a user to use a simple form to write a specific file to a folder by using the sidebar. Simplified here’s what it does:

  • Registers a new tab view in the sidebar if selected item is a directory
  • Shows a form to enter some information in the tab view
  • Sends the information to a Nextcloud REST endpoint
  • Backend saves a specific file to the folder with the user input properly formatted for an external script
  • However, I’ve been adapting a lot of code from the versions app back then.

    Now I’d like to update the app, because some JS APIs broke over time. But I’d like to do so in a future-proof way. Actually, I’d like to mount a Vue component into a tab view. Is that even possible? Is there any app that does that already?

    For example registerTabView is now deprecated. But no-where it says how to register your tab view instead. Core apps still seem to be using it on master . How’s the way forward? Where do I find references to the future of interacting with the filelist?

    Also, @skjnldsv , you’ve been editing the sidebar class recently and added the warning or moved it over to a new version ( https://github.com/nextcloud/server/blame/cb2695df8d47f9d5b08a7d6f1a9dbc55f63b6e59/apps/files/js/filelist.js#L3700 ). Hope I’m allowe to ping you. Can you help? :wink:

    See some example: https://github.com/nextcloud/server/blob/6fcd075730dbd63d5dbb69da0ca5983b51a7240e/apps/files_sharing/src/files_sharing_tab.js
    https://github.com/nextcloud/server/blob/4485cb30a1bd4b86492203b20c43e0c8fdd47f71/apps/files_sharing/src/views/SharingTab.vue

    Your tab needs to provide a Name and an id
    github.com

    nextcloud/server/blob/4485cb30a1bd4b86492203b20c43e0c8fdd47f71/apps/files_sharing/src/views/SharingTab.vue#L139

  • required: true,
  • data() {
  • return {
  • error: '',
  • expirationInterval: null,
  • icon: 'icon-share',
  • loading: true,
  • name: t('files_sharing', 'Sharing'),
  • // reshare Share object
  • reshare: null,
  • sharedWithMe: {},
  • shares: [],
  • linkShares: [],
  • sections: OCA.Sharing.ShareTabSections.getSections(),
  • computed: {
  • nextcloud/server/blob/4485cb30a1bd4b86492203b20c43e0c8fdd47f71/apps/files_sharing/src/views/SharingTab.vue#L157

  • computed: {
  • * Needed to differenciate the tabs
  • * pulled from the AppSidebarTab component
  • * @returns {string}
  • id() {
  • return 'sharing'
  • * Returns the current active tab
  • * needed because AppSidebarTab also uses $parent.activeTab
  • * @returns {string}
  • activeTab() {
  • return this.$parent.activeTab
  • nextcloud/server/blob/f217b11443bb1b4679b92320fdf66d5dd3d081c8/apps/files/src/views/Sidebar.vue#L61-L71

  • <template v-for="tab in tabs" v-else-if="fileInfo">
  • <component
  • :is="tabComponent(tab).is"
  • v-if="canDisplay(tab)"
  • :id="tab.id"
  • :key="tab.id"
  • :component="tabComponent(tab).component"
  • :name="tab.name"
  • :dav-path="davPath"
  • :file-info="fileInfo" />
  • </template>
  • Hey! This was such a helpful pointer, thanks a lot! :heart_eyes:

    The tricky part was to set up webpack, because the structure is a bit different in the server repository than it would be for a simple app, but it’s do-able.

    It feels like a lot less code to interface with the sidebar component than it used to be…

    That’s really helpful! :slight_smile:

    One more question that came up just now: How do I implement the previous canDisplay method?

    It seems like there’s a isEnabled method that is being called on the component, but if I pass it as a prop to the component for me it’s not being executed. How does this work? :thinking:

    nextcloud/server/blob/b186852f9d387ac3517ae62804d5b81f178376c9/apps/files/src/models/Tab.js#L30-L38

  • * Create a new tab instance
  • * @param {string} id the unique id of this tab
  • * @param {Object} component the vue component
  • * @param {Function} [enabled] function that returns if the tab should be shown or not
  • * @param {boolean} [legacy] is this a legacy tab
  • constructor(id, component, enabled = () => true, legacy) {
  • @skjnldsv Cool, thanks, I wasn’t realizing that this would be done through the constructor. I’ll check it out. My issue is more that it requires async operations for this app (to load app settings). So I’ll probably stick with the current solution: Having the tab be always enabled and then show a helpful message when the app is not active in that folder.

    Quick question at the end: Will this change be breaking? So I need to refactor the Vue component again? :sweat_smile:

    – Thomas

    te-online:

    Quick question at the end: Will this change be breaking? So I need to refactor the Vue component again?

    Yes, but the change is very simple.
    You can check it out Move Files Sidebar to proper javascript standard · nextcloud/server@843d799 · GitHub
    Feat/files sidebar cleanup standards by skjnldsv · Pull Request #23164 · nextcloud/server · GitHub

    github.com/nextcloud/server

    Long time needed! Before it gets too messy, let's do this! - This move the Vu