diff --git a/apps/files/src/components/AllFilesList.vue b/apps/files/src/components/AllFilesList.vue
index 0874d58ee1b..232d7c3ad4f 100644
--- a/apps/files/src/components/AllFilesList.vue
+++ b/apps/files/src/components/AllFilesList.vue
@@ -29,14 +29,7 @@
                 class="uk-margin-small-left"
               />
             </div>
-            <div>
-              <oc-button v-if="$_isUserShare(item)" class="file-row-share-indicator uk-text-middle" :aria-label="$_shareUserIconLabel(item)" @click="$_openSideBar(item, 'files-sharing')" variation="raw">
-                <oc-icon name="group" class="uk-text-middle" size="small" :variation="$_shareUserIconVariation(item)"/>
-              </oc-button>
-              <oc-button v-if="$_isLinkShare(item)" class="file-row-share-indicator uk-text-middle" :aria-label="$_shareLinkIconLabel(item)" @click="$_openSideBar(item, 'file-link')" variation="raw">
-                <oc-icon name="link" class="uk-text-middle" size="small" :variation="$_shareLinkIconVariation(item)"/>
-              </oc-button>
-            </div>
+            <StatusIndicators :item="item" :currentFolderPath="currentFolder.path" @click="$_openSideBar" />
             <div class="uk-text-meta uk-text-nowrap uk-width-small" :class="{ 'uk-visible@s' : !_sidebarOpen, 'uk-hidden'  : _sidebarOpen }">
               {{ item.size | fileSize }}
             </div>
@@ -75,18 +68,16 @@
 <script>
 import FileList from './FileList.vue'
 import { mapGetters, mapActions, mapState } from 'vuex'
-import { shareTypes } from '../helpers/shareTypes'
-import { getParentPaths } from '../helpers/path'
 
 import Mixins from '../mixins'
 import FileActions from '../fileactions'
-import intersection from 'lodash/intersection'
 
-const userShareTypes = [shareTypes.user, shareTypes.group, shareTypes.guest, shareTypes.remote]
+const StatusIndicators = () => import('./FilesLists/StatusIndicators/StatusIndicators.vue')
 
 export default {
   components: {
-    FileList
+    FileList,
+    StatusIndicators
   },
   mixins: [
     Mixins,
@@ -110,46 +101,6 @@ export default {
       this.$emit('sideBarOpen', item, sideBarName)
     },
 
-    $_isDirectUserShare (item) {
-      return (intersection(userShareTypes, item.shareTypes).length > 0)
-    },
-
-    $_isIndirectUserShare (item) {
-      return (item.isReceivedShare() || intersection(userShareTypes, this.$_shareTypesIndirect).length > 0)
-    },
-
-    $_isDirectLinkShare (item) {
-      return (item.shareTypes.indexOf(shareTypes.link) >= 0)
-    },
-
-    $_isIndirectLinkShare (item) {
-      return (this.$_shareTypesIndirect.indexOf(shareTypes.link) >= 0)
-    },
-
-    $_isUserShare (item) {
-      return this.$_isDirectUserShare(item) || this.$_isIndirectUserShare(item)
-    },
-
-    $_isLinkShare (item) {
-      return this.$_isDirectLinkShare(item) || this.$_isIndirectLinkShare(item)
-    },
-
-    $_shareUserIconVariation (item) {
-      return this.$_isDirectUserShare(item) ? 'active' : 'passive'
-    },
-
-    $_shareLinkIconVariation (item) {
-      return this.$_isDirectLinkShare(item) ? 'active' : 'passive'
-    },
-
-    $_shareUserIconLabel (item) {
-      return this.$_isDirectUserShare(item) ? this.$gettext('Directly shared with collaborators') : this.$gettext('Shared with collaborators through one of the parent folders')
-    },
-
-    $_shareLinkIconLabel (item) {
-      return this.$_isDirectLinkShare(item) ? this.$gettext('Directly shared with links') : this.$gettext('Shared with links through one of the parent folders')
-    },
-
     $_ocFilesFolder_getFolder () {
       this.setFilterTerm('')
       let absolutePath
@@ -223,31 +174,6 @@ export default {
       return this.$route.params.item
     },
 
-    $_shareTypesIndirect () {
-      const parentPaths = getParentPaths(this.currentFolder.path, true)
-      if (parentPaths.length === 0) {
-        return []
-      }
-
-      // remove root entry
-      parentPaths.pop()
-
-      const shareTypes = {}
-      parentPaths.forEach((parentPath) => {
-        // TODO: optimize for performance by skipping once we got all known types
-        const shares = this.sharesTree[parentPath]
-        if (shares) {
-          shares.forEach((share) => {
-            // note: no distinction between incoming and outgoing shares as we display the same
-            // indirect indicator for them
-            shareTypes[share.info.share_type] = true
-          })
-        }
-      })
-
-      return Object.keys(shareTypes).map(shareType => parseInt(shareType, 10))
-    },
-
     quotaVisible () {
       return (
         !this.publicPage() &&
diff --git a/apps/files/src/components/FilesLists/StatusIndicators/DefaultIndicators.vue b/apps/files/src/components/FilesLists/StatusIndicators/DefaultIndicators.vue
new file mode 100644
index 00000000000..3e2970150dc
--- /dev/null
+++ b/apps/files/src/components/FilesLists/StatusIndicators/DefaultIndicators.vue
@@ -0,0 +1,142 @@
+<template>
+  <div>
+    <oc-button
+      v-for="(indicator, index) in indicators"
+      :key="index"
+      class="file-row-share-indicator uk-text-middle"
+      :class="{ 'uk-margin-xsmall-left' : index > 0 }"
+      :aria-label="indicator.label"
+      @click="indicator.handler(item, indicator.id)"
+      variation="raw"
+    >
+      <oc-icon
+        :name="indicator.icon"
+        class="uk-text-middle"
+        size="small"
+        :variation="indicator.status"
+      />
+    </oc-button>
+  </div>
+</template>
+
+<script>
+import intersection from 'lodash/intersection'
+import { shareTypes } from '../../../helpers/shareTypes'
+import { getParentPaths } from '../../../helpers/path'
+
+const userShareTypes = [shareTypes.user, shareTypes.group, shareTypes.guest, shareTypes.remote]
+
+export default {
+  name: 'StatusIndicators',
+
+  props: {
+    item: {
+      type: Object,
+      required: true
+    },
+    currentFolderPath: {
+      type: String,
+      required: true
+    }
+  },
+
+  computed: {
+    indicators () {
+      const indicators = []
+
+      if (this.isUserShare(this.item)) {
+        indicators.push({
+          id: 'files-sharing',
+          label: this.shareUserIconLabel(this.item),
+          icon: 'group',
+          status: this.shareUserIconVariation(this.item),
+          handler: this.indicatorHandler
+        })
+      }
+
+      if (this.isLinkShare(this.item)) {
+        indicators.push({
+          id: 'file-link',
+          label: this.shareLinkIconLabel(this.item),
+          icon: 'link',
+          status: this.shareLinkIconVariation(this.item),
+          handler: this.indicatorHandler
+        })
+      }
+
+      return indicators
+    },
+
+    shareTypesIndirect () {
+      const parentPaths = getParentPaths(this.currentFolderPath, true)
+      if (parentPaths.length === 0) {
+        return []
+      }
+
+      // remove root entry
+      parentPaths.pop()
+
+      const shareTypes = {}
+      parentPaths.forEach((parentPath) => {
+        // TODO: optimize for performance by skipping once we got all known types
+        const shares = this.sharesTree[parentPath]
+        if (shares) {
+          shares.forEach((share) => {
+            // note: no distinction between incoming and outgoing shares as we display the same
+            // indirect indicator for them
+            shareTypes[share.info.share_type] = true
+          })
+        }
+      })
+
+      return Object.keys(shareTypes).map(shareType => parseInt(shareType, 10))
+    }
+  },
+
+  methods: {
+    isDirectUserShare (item) {
+      return (intersection(userShareTypes, item.shareTypes).length > 0)
+    },
+
+    isIndirectUserShare (item) {
+      return (item.isReceivedShare() || intersection(userShareTypes, this.shareTypesIndirect).length > 0)
+    },
+
+    isDirectLinkShare (item) {
+      return (item.shareTypes.indexOf(shareTypes.link) >= 0)
+    },
+
+    isIndirectLinkShare () {
+      return (this.shareTypesIndirect.indexOf(shareTypes.link) >= 0)
+    },
+
+    isUserShare (item) {
+      return this.isDirectUserShare(item) || this.isIndirectUserShare(item)
+    },
+
+    isLinkShare (item) {
+      return this.isDirectLinkShare(item) || this.isIndirectLinkShare(item)
+    },
+
+    shareUserIconVariation (item) {
+      return this.isDirectUserShare(item) ? 'active' : 'passive'
+    },
+
+    shareLinkIconVariation (item) {
+      return this.isDirectLinkShare(item) ? 'active' : 'passive'
+    },
+
+    shareUserIconLabel (item) {
+      return this.isDirectUserShare(item) ? this.$gettext('Directly shared with collaborators') : this.$gettext('Shared with collaborators through one of the parent folders')
+    },
+
+    shareLinkIconLabel (item) {
+      return this.isDirectLinkShare(item) ? this.$gettext('Directly shared with links') : this.$gettext('Shared with links through one of the parent folders')
+    },
+
+    indicatorHandler (item, sideBarName) {
+      this.$emit('click', item, sideBarName)
+    }
+  }
+}
+</script>
diff --git a/apps/files/src/components/FilesLists/StatusIndicators/StatusIndicators.vue b/apps/files/src/components/FilesLists/StatusIndicators/StatusIndicators.vue
new file mode 100644
index 00000000000..6571c5aacbc
--- /dev/null
+++ b/apps/files/src/components/FilesLists/StatusIndicators/StatusIndicators.vue
@@ -0,0 +1,64 @@
+<template>
+  <div class="uk-flex uk-flex-middle">
+    <DefaultIndicators
+      v-if="displayDefaultIndicators"
+      :item="item"
+      :currentFolderPath="currentFolderPath"
+      :class="{ 'uk-margin-xsmall-right' : customIndicators }"
+      @click="openSidebar"
+    />
+    <template v-if="customIndicators">
+      <component
+        v-for="(indicator, index) in customIndicators"
+        :is="indicator"
+        :key="index"
+        :item="item"
+        :currentFolderPath="currentFolderPath"
+      />
+    </template>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+
+const DefaultIndicators = () => import('./DefaultIndicators.vue')
+
+export default {
+  name: 'StatusIndicators',
+
+  components: {
+    DefaultIndicators
+  },
+
+  props: {
+    item: {
+      type: Object,
+      required: true
+    },
+    currentFolderPath: {
+      type: String,
+      required: true
+    }
+  },
+
+  computed: {
+    ...mapGetters(['configuration', 'customFilesListIndicators']),
+
+    displayDefaultIndicators () {
+      return !this.configuration.theme.filesList.hideDefaultStatusIndicators
+    },
+
+    customIndicators () {
+      return this.customFilesListIndicators
+    }
+  },
+
+  methods: {
+    // TODO: Adjust to send the event via store
+    openSidebar (item, indicatorId) {
+      this.$emit('click', item, indicatorId)
+    }
+  }
+}
+</script>
diff --git a/changelog/unreleased/2895 b/changelog/unreleased/2895
new file mode 100644
index 00000000000..9d88279153f
--- /dev/null
+++ b/changelog/unreleased/2895
@@ -0,0 +1,8 @@
+Enhancement: Add status indicator extension point
+
+We've added the ability for the extension to inject custom status indicator into files list.
+New indicators will then appear next to the default one.
+We've also added ability to disable default indicators.
+
+https://github.com/owncloud/phoenix/issues/2895
+https://github.com/owncloud/phoenix/pull/2928
diff --git a/src/store/apps.js b/src/store/apps.js
index 311dc34e86f..ddba6dba3df 100644
--- a/src/store/apps.js
+++ b/src/store/apps.js
@@ -8,6 +8,7 @@ const state = {
   extensions: {},
   newFileHandlers: [],
   fileSideBars: [],
+  customFilesListIndicators: [],
   meta: {}
 }
 
@@ -118,6 +119,15 @@ const mutations = {
       })
       state.fileSideBars = list
     }
+
+    if (appInfo.filesListIndicators) {
+      const indicators = state.customFilesListIndicators
+      appInfo.filesListIndicators.forEach(indicator => {
+        indicators.push(indicator)
+      })
+      state.customFilesListIndicators = indicators
+    }
+
     if (!appInfo.id) return
     // name: use id as fallback display name
     // icon: use empty box as fallback icon
@@ -164,7 +174,8 @@ const getters = {
   },
   fileSideBars: state => {
     return state.fileSideBars
-  }
+  },
+  customFilesListIndicators: state => state.customFilesListIndicators
 }
 
 export default {
diff --git a/src/store/config.js b/src/store/config.js
index 0ded00196cd..d9f6c8ccb50 100644
--- a/src/store/config.js
+++ b/src/store/config.js
@@ -23,6 +23,9 @@ const state = {
     },
     logo: {
       favicon: ''
+    },
+    filesList: {
+      hideDefaultStatusIndicators: false
     }
   }
 }
diff --git a/themes/owncloud.json b/themes/owncloud.json
index 37193e6592d..e097e5a49cf 100644
--- a/themes/owncloud.json
+++ b/themes/owncloud.json
@@ -5,5 +5,8 @@
   },
   "logo": {
     "favicon": "themes/owncloud/favicon.jpg"
+  },
+  "filesList": {
+    "hideDefaultStatusIndicators": false
   }
 }