diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
new file mode 100644
index 0000000000000000000000000000000000000000..76629cb790f33d6c978fac8fc789b38f9447f86a
--- /dev/null
+++ b/apps/files/css/detailsView.css
@@ -0,0 +1,55 @@
+#app-sidebar .detailFileInfoContainer {
+	min-height: 50px;
+	padding: 15px;
+}
+
+#app-sidebar .detailFileInfoContainer > div {
+	clear: both;
+}
+
+#app-sidebar .mainFileInfoView {
+	margin-right: 20px; /* accomodate for close icon */
+}
+
+#app-sidebar .thumbnail {
+	width: 50px;
+	height: 50px;
+	float: left;
+	margin-right: 10px;
+	background-size: 50px;
+}
+
+#app-sidebar .ellipsis {
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	overflow: hidden;
+}
+
+#app-sidebar .fileName {
+	font-size: 16px;
+	padding-top: 3px;
+}
+
+#app-sidebar .file-details {
+	margin-top: 3px;
+	-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+	opacity: .5;
+}
+#app-sidebar .action-favorite {
+	vertical-align: text-bottom;
+	padding: 10px;
+	margin: -10px;
+}
+
+#app-sidebar .detailList {
+	float: left;
+}
+
+#app-sidebar .close {
+	position: absolute;
+	top: 0;
+	right: 0;
+	padding: 15px;
+	-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+	opacity: .5;
+}
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index f2f2c5ac3bcb5e37f5ec44499874e6b831986633..7e3318a962bfcf038882cb75c8010b627b40fdae 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -103,6 +103,10 @@
 	min-height: 100%;
 }
 
+.app-files #app-content {
+	overflow-x: hidden;
+}
+
 /* icons for sidebar */
 .nav-icon-files {
 	background-image: url('../img/folder.svg');
@@ -143,6 +147,7 @@
 #filestable tbody tr:active {
 	background-color: rgb(240,240,240);
 }
+#filestable tbody tr.highlighted,
 #filestable tbody tr.selected {
 	background-color: rgb(230,230,230);
 }
diff --git a/apps/files/index.php b/apps/files/index.php
index 4f103f975cbc87448266a4f4d1f37fffe9320388..dca3e5ae74d8308f7e32e3f8589be9e0297535fd 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -50,6 +50,12 @@ OCP\Util::addscript('files', 'search');
 \OCP\Util::addScript('files', 'tagsplugin');
 \OCP\Util::addScript('files', 'favoritesplugin');
 
+\OCP\Util::addScript('files', 'detailfileinfoview');
+\OCP\Util::addScript('files', 'detailtabview');
+\OCP\Util::addScript('files', 'mainfileinfodetailview');
+\OCP\Util::addScript('files', 'detailsview');
+\OCP\Util::addStyle('files', 'detailsView');
+
 \OC_Util::addVendorScript('core', 'handlebars/handlebars');
 
 OCP\App::setActiveNavigationEntry('files_index');
diff --git a/apps/files/js/detailfileinfoview.js b/apps/files/js/detailfileinfoview.js
new file mode 100644
index 0000000000000000000000000000000000000000..9a88b5e2d8a034c6b0a88ae63134a9a302e621b1
--- /dev/null
+++ b/apps/files/js/detailfileinfoview.js
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+	/**
+	 * @class OCA.Files.DetailFileInfoView
+	 * @classdesc
+	 *
+	 * Displays a block of details about the file info.
+	 *
+	 */
+	var DetailFileInfoView = function() {
+		this.initialize();
+	};
+	/**
+	 * @memberof OCA.Files
+	 */
+	DetailFileInfoView.prototype = {
+		/**
+		 * jQuery element
+		 */
+		$el: null,
+
+		_template: null,
+
+		/**
+		 * Currently displayed file info
+		 *
+		 * @type OCA.Files.FileInfo
+		 */
+		_fileInfo: null,
+
+		/**
+		 * Initialize the details view
+		 */
+		initialize: function() {
+			this.$el = $('<div class="detailFileInfoView"></div>');
+		},
+
+		/**
+		 * returns the jQuery object for HTML output
+		 *
+		 * @returns {jQuery}
+		 */
+		get$: function() {
+			return this.$el;
+		},
+
+		/**
+		 * Destroy / uninitialize this instance.
+		 */
+		destroy: function() {
+			if (this.$el) {
+				this.$el.remove();
+			}
+		},
+
+		/**
+		 * Renders this details view
+		 *
+		 * @abstract
+		 */
+		render: function() {
+			// to be implemented in subclass
+		},
+
+		/**
+		 * Sets the file info to be displayed in the view
+		 *
+		 * @param {OCA.Files.FileInfo} fileInfo file info to set
+		 */
+		setFileInfo: function(fileInfo) {
+			this._fileInfo = fileInfo;
+			this.render();
+		},
+
+		/**
+		 * Returns the file info.
+		 *
+		 * @return {OCA.Files.FileInfo} file info
+		 */
+		getFileInfo: function() {
+			return this._fileInfo;
+		}
+	};
+
+	OCA.Files.DetailFileInfoView = DetailFileInfoView;
+})();
+
diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js
new file mode 100644
index 0000000000000000000000000000000000000000..7b7bd013f9e63bffcc609002ddf22df4a0ff76a7
--- /dev/null
+++ b/apps/files/js/detailsview.js
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+
+	var TEMPLATE =
+		'<div>' +
+		'    <div class="detailFileInfoContainer">' +
+		'    </div>' +
+		'    <div>' +
+		'        <ul class="tabHeaders">' +
+		'        </ul>' +
+		'        <div class="tabsContainer">' +
+		'        </div>' +
+		'    </div>' +
+		'    <a class="close icon-close" href="#" alt="{{closeLabel}}"></a>' +
+		'</div>';
+
+	var TEMPLATE_TAB_HEADER =
+		'<li class="tabHeader {{#if selected}}selected{{/if}}" data-tabid="{{tabId}}" data-tabindex="{{tabIndex}}"><a href="#">{{label}}</a></li>';
+
+	/**
+	 * @class OCA.Files.DetailsView
+	 * @classdesc
+	 *
+	 * The details view show details about a selected file.
+	 *
+	 */
+	var DetailsView = function() {
+		this.initialize();
+	};
+
+	/**
+	 * @memberof OCA.Files
+	 */
+	DetailsView.prototype = {
+
+		/**
+		 * jQuery element
+		 */
+		$el: null,
+
+		_template: null,
+		_templateTabHeader: null,
+
+		/**
+		 * Currently displayed file info
+		 *
+		 * @type OCA.Files.FileInfo
+		 */
+		_fileInfo: null,
+
+		/**
+		 * List of detail tab views
+		 *
+		 * @type Array<OCA.Files.DetailTabView>
+		 */
+		_tabViews: [],
+
+		/**
+		 * List of detail file info views
+		 *
+		 * @type Array<OCA.Files.DetailFileInfoView>
+		 */
+		_detailFileInfoViews: [],
+
+		/**
+		 * Id of the currently selected tab
+		 *
+		 * @type string
+		 */
+		_currentTabId: null,
+
+		/**
+		 * Initialize the details view
+		 */
+		initialize: function() {
+			this.$el = $('<div id="app-sidebar"></div>');
+			this.fileInfo = null;
+			this._tabViews = [];
+			this._detailFileInfoViews = [];
+
+			this.$el.on('click', 'a.close', function(event) {
+				OC.Apps.hideAppSidebar();
+				event.preventDefault();
+			});
+
+			this.$el.on('click', '.tabHeaders .tabHeader', _.bind(this._onClickTab, this));
+
+			// uncomment to add some dummy tabs for testing
+			//this._addTestTabs();
+		},
+
+		/**
+		 * Destroy / uninitialize this instance.
+		 */
+		destroy: function() {
+			if (this.$el) {
+				this.$el.remove();
+			}
+		},
+
+		_onClickTab: function(e) {
+			var $target = $(e.target);
+			if (!$target.hasClass('tabHeader')) {
+				$target = $target.closest('.tabHeader');
+			}
+			var tabIndex = $target.attr('data-tabindex');
+			var targetTab;
+			if (_.isUndefined(tabIndex)) {
+				return;
+			}
+
+			this.$el.find('.tabsContainer .tab').addClass('hidden');
+			targetTab = this._tabViews[tabIndex];
+			targetTab.$el.removeClass('hidden');
+
+			this.$el.find('.tabHeaders li').removeClass('selected');
+			$target.addClass('selected');
+
+			e.preventDefault();
+		},
+
+		_addTestTabs: function() {
+			for (var j = 0; j < 2; j++) {
+				var testView = new OCA.Files.DetailTabView('testtab' + j);
+				testView.index = j;
+				testView.getLabel = function() { return 'Test tab ' + this.index; };
+				testView.render = function() {
+					this.$el.empty();
+					for (var i = 0; i < 100; i++) {
+						this.$el.append('<div>Test tab ' + this.index + ' row ' + i + '</div>');
+					}
+				};
+				this._tabViews.push(testView);
+			}
+		},
+
+		/**
+		 * Renders this details view
+		 */
+		render: function() {
+			var self = this;
+			this.$el.empty();
+
+			if (!this._template) {
+				this._template = Handlebars.compile(TEMPLATE);
+			}
+
+			if (!this._templateTabHeader) {
+				this._templateTabHeader = Handlebars.compile(TEMPLATE_TAB_HEADER);
+			}
+
+			var $el = $(this._template({
+				closeLabel: t('files', 'Close')
+			}));
+			var $tabsContainer = $el.find('.tabsContainer');
+			var $tabHeadsContainer = $el.find('.tabHeaders');
+			var $detailsContainer = $el.find('.detailFileInfoContainer');
+
+			// render details
+			_.each(this._detailFileInfoViews, function(detailView) {
+				$detailsContainer.append(detailView.get$());
+			});
+
+			if (this._tabViews.length > 0) {
+				if (!this._currentTab) {
+					this._currentTab = this._tabViews[0].getId();
+				}
+
+				// render tabs
+				_.each(this._tabViews, function(tabView, i) {
+					// hidden by default
+					var $el = tabView.get$();
+					var isCurrent = (tabView.getId() === self._currentTab);
+					if (!isCurrent) {
+						$el.addClass('hidden');
+					}
+					$tabsContainer.append($el);
+
+					$tabHeadsContainer.append(self._templateTabHeader({
+						tabId: tabView.getId(),
+						tabIndex: i,
+						label: tabView.getLabel(),
+						selected: isCurrent
+					}));
+				});
+			}
+
+			// TODO: select current tab
+
+			this.$el.append($el);
+		},
+
+		/**
+		 * Sets the file info to be displayed in the view
+		 *
+		 * @param {OCA.Files.FileInfo} fileInfo file info to set
+		 */
+		setFileInfo: function(fileInfo) {
+			this._fileInfo = fileInfo;
+
+			this.render();
+
+			// notify all panels
+			_.each(this._tabViews, function(tabView) {
+				tabView.setFileInfo(fileInfo);
+			});
+			_.each(this._detailFileInfoViews, function(detailView) {
+				detailView.setFileInfo(fileInfo);
+			});
+		},
+
+		/**
+		 * Returns the file info.
+		 *
+		 * @return {OCA.Files.FileInfo} file info
+		 */
+		getFileInfo: function() {
+			return this._fileInfo;
+		},
+
+		/**
+		 * Adds a tab in the tab view
+		 *
+		 * @param {OCA.Files.DetailTabView} tab view
+		 */
+		addTabView: function(tabView) {
+			this._tabViews.push(tabView);
+		},
+
+		/**
+		 * Adds a detail view for file info.
+		 *
+		 * @param {OCA.Files.DetailFileInfoView} detail view
+		 */
+		addDetailView: function(detailView) {
+			this._detailFileInfoViews.push(detailView);
+		}
+	};
+
+	OCA.Files.DetailsView = DetailsView;
+})();
+
diff --git a/apps/files/js/detailtabview.js b/apps/files/js/detailtabview.js
new file mode 100644
index 0000000000000000000000000000000000000000..b9b1dda2ccc1b6070fcf2c8f4ea04658ffbe52b0
--- /dev/null
+++ b/apps/files/js/detailtabview.js
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+
+	/**
+	 * @class OCA.Files.DetailTabView
+	 * @classdesc
+	 *
+	 * Base class for tab views to display file information.
+	 *
+	 */
+	var DetailTabView = function(id) {
+		this.initialize(id);
+	};
+
+	/**
+	 * @memberof OCA.Files
+	 */
+	DetailTabView.prototype = {
+		/**
+		 * jQuery element
+		 */
+		$el: null,
+
+		/**
+		 * Tab id
+		 */
+		_id: null,
+
+		/**
+		 * Tab label
+		 */
+		_label: null,
+
+		_template: null,
+
+		/**
+		 * Currently displayed file info
+		 *
+		 * @type OCA.Files.FileInfo
+		 */
+		_fileInfo: null,
+
+		/**
+		 * Initialize the details view
+		 *
+		 * @param {string} id tab id
+		 */
+		initialize: function(id) {
+			if (!id) {
+				throw 'Argument "id" is required';
+			}
+			this._id = id;
+			this.$el = $('<div class="tab"></div>');
+			this.$el.attr('data-tabid', id);
+		},
+
+		/**
+		 * Destroy / uninitialize this instance.
+		 */
+		destroy: function() {
+			if (this.$el) {
+				this.$el.remove();
+			}
+		},
+
+		/**
+		 * Returns the tab element id
+		 *
+		 * @return {string} tab id
+		 */
+		getId: function() {
+			return this._id;
+		},
+
+		/**
+		 * Returns the tab label
+		 *
+		 * @return {String} label
+		 */
+		getLabel: function() {
+			return 'Tab ' + this._id;
+		},
+
+		/**
+		 * returns the jQuery object for HTML output
+		 *
+		 * @returns {jQuery}
+		 */
+		get$: function() {
+			return this.$el;
+		},
+
+		/**
+		 * Renders this details view
+		 *
+		 * @abstract
+		 */
+		render: function() {
+			// to be implemented in subclass
+			// FIXME: code is only for testing
+			this.$el.empty();
+			this.$el.append('<div>Hello ' + this._id + '</div>');
+		},
+
+		/**
+		 * Sets the file info to be displayed in the view
+		 *
+		 * @param {OCA.Files.FileInfo} fileInfo file info to set
+		 */
+		setFileInfo: function(fileInfo) {
+			this._fileInfo = fileInfo;
+			this.render();
+		},
+
+		/**
+		 * Returns the file info.
+		 *
+		 * @return {OCA.Files.FileInfo} file info
+		 */
+		getFileInfo: function() {
+			return this._fileInfo;
+		}
+	};
+
+	OCA.Files.DetailTabView = DetailTabView;
+})();
+
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index c56c786929a1a79bfac2c5d778d1c9b136c099e6..f5629ecd2c3cadec4d3b5bcf5d971395446ba13c 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -23,6 +23,7 @@
 	 * @param [options.scrollContainer] scrollable container, defaults to $(window)
 	 * @param [options.dragOptions] drag options, disabled by default
 	 * @param [options.folderDropOptions] folder drop options, disabled by default
+	 * @param [options.detailsViewEnabled=true] whether to enable details view
 	 */
 	var FileList = function($el, options) {
 		this.initialize($el, options);
@@ -64,6 +65,11 @@
 		 */
 		fileSummary: null,
 
+		/**
+		 * @type OCA.Files.DetailsView
+		 */
+		_detailsView: null,
+
 		/**
 		 * Whether the file list was initialized already.
 		 * @type boolean
@@ -205,6 +211,13 @@
 			}
 			this.breadcrumb = new OCA.Files.BreadCrumb(breadcrumbOptions);
 
+			if (_.isUndefined(options.detailsViewEnabled) || options.detailsViewEnabled) {
+				this._detailsView = new OCA.Files.DetailsView();
+				this._detailsView.addDetailView(new OCA.Files.MainFileInfoDetailView());
+				this._detailsView.$el.insertBefore(this.$el);
+				this._detailsView.$el.addClass('disappear');
+			}
+
 			this.$el.find('#controls').prepend(this.breadcrumb.$el);
 
 			this.$el.find('thead th .columntitle').click(_.bind(this._onClickHeader, this));
@@ -216,6 +229,13 @@
 
 			this.updateSearch();
 
+			this.$el.on('click', function(event) {
+				var $target = $(event.target);
+				// click outside file row ?
+				if (!$target.closest('tbody').length && !$target.closest('#app-sidebar').length) {
+					self._updateDetailsView(null);
+				}
+			});
 			this.$fileList.on('click','td.filename>a.name', _.bind(this._onClickFile, this));
 			this.$fileList.on('change', 'td.filename>.selectCheckBox', _.bind(this._onClickFileCheckbox, this));
 			this.$el.on('urlChanged', _.bind(this._onUrlChanged, this));
@@ -262,6 +282,37 @@
 			this.fileActions.on('setDefault', this._onFileActionsUpdated);
 		},
 
+		/**
+		 * Update the details view to display the given file
+		 *
+		 * @param {OCA.Files.FileInfo} fileInfo file info to display
+		 */
+		_updateDetailsView: function(fileInfo) {
+			if (!this._detailsView) {
+				return;
+			}
+
+			var self = this;
+			var oldFileInfo = this._detailsView.getFileInfo();
+			if (oldFileInfo) {
+				// TODO: use more efficient way, maybe track the highlight
+				this.$fileList.children().filterAttr('data-id', '' + oldFileInfo.id).removeClass('highlighted');
+			}
+
+			if (!fileInfo) {
+				OC.Apps.hideAppSidebar();
+				this._detailsView.setFileInfo(null);
+				return;
+			}
+
+			this.$fileList.children().filterAttr('data-id', '' + fileInfo.id).addClass('highlighted');
+			this._detailsView.setFileInfo(_.extend({
+				path: this.getCurrentDirectory()
+			}, fileInfo));
+			this._detailsView.$el.scrollTop(0);
+			_.defer(OC.Apps.showAppSidebar);
+		},
+
 		/**
 		 * Event handler for when the window size changed
 		 */
@@ -315,6 +366,12 @@
 				delete this._selectedFiles[$tr.data('id')];
 				this._selectionSummary.remove(data);
 			}
+			if (this._selectionSummary.getTotal() === 1) {
+				this._updateDetailsView(_.values(this._selectedFiles)[0]);
+			} else {
+				// show nothing when multiple files are selected
+				this._updateDetailsView(null);
+			}
 			this.$el.find('.select-all').prop('checked', this._selectionSummary.getTotal() === this.files.length);
 		},
 
@@ -350,27 +407,34 @@
 				this._selectFileEl($tr, !$checkbox.prop('checked'));
 				this.updateSelectionSummary();
 			} else {
-				var filename = $tr.attr('data-file');
-				var renaming = $tr.data('renaming');
-				if (!renaming) {
-					this.fileActions.currentFile = $tr.find('td');
-					var mime = this.fileActions.getCurrentMimeType();
-					var type = this.fileActions.getCurrentType();
-					var permissions = this.fileActions.getCurrentPermissions();
-					var action = this.fileActions.getDefault(mime,type, permissions);
-					if (action) {
-						event.preventDefault();
-						// also set on global object for legacy apps
-						window.FileActions.currentFile = this.fileActions.currentFile;
-						action(filename, {
-							$file: $tr,
-							fileList: this,
-							fileActions: this.fileActions,
-							dir: $tr.attr('data-path') || this.getCurrentDirectory()
-						});
+				// clicked directly on the name
+				if (!this._detailsView || $(event.target).is('.nametext') || $(event.target).closest('.nametext').length) {
+					var filename = $tr.attr('data-file');
+					var renaming = $tr.data('renaming');
+					if (!renaming) {
+						this.fileActions.currentFile = $tr.find('td');
+						var mime = this.fileActions.getCurrentMimeType();
+						var type = this.fileActions.getCurrentType();
+						var permissions = this.fileActions.getCurrentPermissions();
+						var action = this.fileActions.getDefault(mime,type, permissions);
+						if (action) {
+							event.preventDefault();
+							// also set on global object for legacy apps
+							window.FileActions.currentFile = this.fileActions.currentFile;
+							action(filename, {
+								$file: $tr,
+								fileList: this,
+								fileActions: this.fileActions,
+								dir: $tr.attr('data-path') || this.getCurrentDirectory()
+							});
+						}
+						// deselect row
+						$(event.target).closest('a').blur();
 					}
-					// deselect row
-					$(event.target).closest('a').blur();
+				} else {
+					var fileInfo = this.files[$tr.index()];
+					this._updateDetailsView(fileInfo);
+					event.preventDefault();
 				}
 			}
 		},
@@ -825,7 +889,7 @@
 			var formatted;
 			var text;
 			if (mtime > 0) {
-				formatted = formatDate(mtime);
+				formatted = OC.Util.formatDate(mtime);
 				text = OC.Util.relativeModifiedDate(mtime);
 			} else {
 				formatted = t('files', 'Unable to determine date');
@@ -1239,6 +1303,12 @@
 			ready(iconURL); // set mimeicon URL
 
 			urlSpec.file = OCA.Files.Files.fixPath(path);
+			if (options.x) {
+				urlSpec.x = options.x;
+			}
+			if (options.y) {
+				urlSpec.y = options.y;
+			}
 
 			if (etag){
 				// use etag as cache buster
@@ -1521,6 +1591,7 @@
 								tr.remove();
 								tr = self.add(fileInfo, {updateSummary: false, silent: true});
 								self.$fileList.trigger($.Event('fileActionsReady', {fileList: self, $files: $(tr)}));
+								self._updateDetailsView(fileInfo);
 							}
 						});
 					} else {
@@ -2177,6 +2248,20 @@
 
 				}
 			});
+		},
+
+		/**
+		 * Register a tab view to be added to all views
+		 */
+		registerTabView: function(tabView) {
+			this._detailsView.addTabView(tabView);
+		},
+
+		/**
+		 * Register a detail view to be added to all views
+		 */
+		registerDetailView: function(detailView) {
+			this._detailsView.addDetailView(detailView);
 		}
 	};
 
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
new file mode 100644
index 0000000000000000000000000000000000000000..a00d907d0d6849ae9ee260fa0643a9744b804be4
--- /dev/null
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+	var TEMPLATE =
+		'<div class="thumbnail"></div><div title="{{name}}" class="fileName ellipsis">{{name}}</div>' +
+		'<div class="file-details ellipsis">' +
+		'    <a href="#" ' +
+		'    alt="{{starAltText}}"' +
+		'    class="action action-favorite favorite">' +
+		'    <img class="svg" src="{{starIcon}}" />' +
+		'    </a>' +
+		'    <span class="size" title="{{altSize}}">{{size}}</span>, <span class="date" title="{{altDate}}">{{date}}</span>' +
+		'</div>';
+
+	/**
+	 * @class OCA.Files.MainFileInfoDetailView
+	 * @classdesc
+	 *
+	 * Displays main details about a file
+	 *
+	 */
+	var MainFileInfoDetailView = function() {
+		this.initialize();
+	};
+	/**
+	 * @memberof OCA.Files
+	 */
+	MainFileInfoDetailView.prototype = _.extend({}, OCA.Files.DetailFileInfoView.prototype,
+		/** @lends OCA.Files.MainFileInfoDetailView.prototype */ {
+		_template: null,
+
+		/**
+		 * Initialize the details view
+		 */
+		initialize: function() {
+			this.$el = $('<div class="mainFileInfoView"></div>');
+		},
+
+		/**
+		 * Renders this details view
+		 */
+		render: function() {
+			this.$el.empty();
+
+			if (!this._template) {
+				this._template = Handlebars.compile(TEMPLATE);
+			}
+
+			if (this._fileInfo) {
+				var isFavorite = (this._fileInfo.tags || []).indexOf(OC.TAG_FAVORITE) >= 0;
+				this.$el.append(this._template({
+					nameLabel: t('files', 'Name'),
+					name: this._fileInfo.name,
+					pathLabel: t('files', 'Path'),
+					path: this._fileInfo.path,
+					sizeLabel: t('files', 'Size'),
+					size: OC.Util.humanFileSize(this._fileInfo.size, true),
+					altSize: n('files', '%n byte', '%n bytes', this._fileInfo.size),
+					dateLabel: t('files', 'Modified'),
+					altDate: OC.Util.formatDate(this._fileInfo.mtime),
+					date: OC.Util.relativeModifiedDate(this._fileInfo.mtime),
+					starAltText: isFavorite ? t('files', 'Favorited') : t('files', 'Favorite'),
+					starIcon: OC.imagePath('core', isFavorite ? 'actions/starred' : 'actions/star')
+				}));
+
+				// TODO: we really need OC.Previews
+				var $iconDiv = this.$el.find('.thumbnail');
+				if (this._fileInfo.mimetype !== 'httpd/unix-directory') {
+					// TODO: inject utility class?
+					FileList.lazyLoadPreview({
+						path: this._fileInfo.path + '/' + this._fileInfo.name,
+						mime: this._fileInfo.mimetype,
+						etag: this._fileInfo.etag,
+						x: 50,
+						y: 50,
+						callback: function(previewUrl) {
+							$iconDiv.css('background-image', 'url("' + previewUrl + '")');
+						}
+					});
+				} else {
+					// TODO: special icons / shared / external
+					$iconDiv.css('background-image', 'url("' + OC.MimeType.getIconUrl('dir') + '")');
+				}
+				this.$el.find('[title]').tooltip({placement: 'bottom'});
+			}
+		}
+	});
+
+	OCA.Files.MainFileInfoDetailView = MainFileInfoDetailView;
+})();
diff --git a/apps/files/tests/js/detailsviewSpec.js b/apps/files/tests/js/detailsviewSpec.js
new file mode 100644
index 0000000000000000000000000000000000000000..db1e24fd68e19d7098b3a221e2bc1c789bc75982
--- /dev/null
+++ b/apps/files/tests/js/detailsviewSpec.js
@@ -0,0 +1,105 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2015 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+describe('OCA.Files.DetailsView tests', function() {
+	var detailsView;
+
+	beforeEach(function() {
+		detailsView = new OCA.Files.DetailsView();
+	});
+	afterEach(function() {
+		detailsView.destroy();
+		detailsView = undefined;
+	});
+	it('renders itself empty when nothing registered', function() {
+		detailsView.render();
+		expect(detailsView.$el.find('.detailFileInfoContainer').length).toEqual(1);
+		expect(detailsView.$el.find('.tabsContainer').length).toEqual(1);
+	});
+	describe('file info detail view', function() {
+		it('renders registered view', function() {
+			var testView = new OCA.Files.DetailFileInfoView();
+			var testView2 = new OCA.Files.DetailFileInfoView();
+			detailsView.addDetailView(testView);
+			detailsView.addDetailView(testView2);
+			detailsView.render();
+
+			expect(detailsView.$el.find('.detailFileInfoContainer .detailFileInfoView').length).toEqual(2);
+		});
+		it('updates registered tabs when fileinfo is updated', function() {
+			var viewRenderStub = sinon.stub(OCA.Files.DetailFileInfoView.prototype, 'render');
+			var testView = new OCA.Files.DetailFileInfoView();
+			var testView2 = new OCA.Files.DetailFileInfoView();
+			detailsView.addDetailView(testView);
+			detailsView.addDetailView(testView2);
+			detailsView.render();
+
+			var fileInfo = {id: 5, name: 'test.txt'};
+			viewRenderStub.reset();
+			detailsView.setFileInfo(fileInfo);
+
+			expect(testView.getFileInfo()).toEqual(fileInfo);
+			expect(testView2.getFileInfo()).toEqual(fileInfo);
+
+			expect(viewRenderStub.callCount).toEqual(2);
+			viewRenderStub.restore();
+		});
+	});
+	describe('tabs', function() {
+		var testView, testView2;
+
+		beforeEach(function() {
+			testView = new OCA.Files.DetailTabView('test1');
+			testView2 = new OCA.Files.DetailTabView('test2');
+			detailsView.addTabView(testView);
+			detailsView.addTabView(testView2);
+			detailsView.render();
+		});
+		it('renders registered tabs', function() {
+			expect(detailsView.$el.find('.tab').length).toEqual(2);
+		});
+		it('updates registered tabs when fileinfo is updated', function() {
+			var tabRenderStub = sinon.stub(OCA.Files.DetailTabView.prototype, 'render');
+			var fileInfo = {id: 5, name: 'test.txt'};
+			tabRenderStub.reset();
+			detailsView.setFileInfo(fileInfo);
+
+			expect(testView.getFileInfo()).toEqual(fileInfo);
+			expect(testView2.getFileInfo()).toEqual(fileInfo);
+
+			expect(tabRenderStub.callCount).toEqual(2);
+			tabRenderStub.restore();
+		});
+		it('selects the first tab by default', function() {
+			expect(detailsView.$el.find('.tabHeader').eq(0).hasClass('selected')).toEqual(true);
+			expect(detailsView.$el.find('.tabHeader').eq(1).hasClass('selected')).toEqual(false);
+			expect(detailsView.$el.find('.tab').eq(0).hasClass('hidden')).toEqual(false);
+			expect(detailsView.$el.find('.tab').eq(1).hasClass('hidden')).toEqual(true);
+		});
+		it('switches the current tab when clicking on tab header', function() {
+			detailsView.$el.find('.tabHeader').eq(1).click();
+			expect(detailsView.$el.find('.tabHeader').eq(0).hasClass('selected')).toEqual(false);
+			expect(detailsView.$el.find('.tabHeader').eq(1).hasClass('selected')).toEqual(true);
+			expect(detailsView.$el.find('.tab').eq(0).hasClass('hidden')).toEqual(true);
+			expect(detailsView.$el.find('.tab').eq(1).hasClass('hidden')).toEqual(false);
+		});
+	});
+});
diff --git a/apps/files/tests/js/favoritespluginspec.js b/apps/files/tests/js/favoritespluginspec.js
index 90b40ede74b43afcc2a268b2f42f9389739da6a9..1b144c287071f7a3c0c918c3cf52ea3a5bf6a56a 100644
--- a/apps/files/tests/js/favoritespluginspec.js
+++ b/apps/files/tests/js/favoritespluginspec.js
@@ -113,7 +113,7 @@ describe('OCA.Files.FavoritesPlugin tests', function() {
 				shareOwner: 'user2'
 			}]);
 
-			fileList.findFileEl('testdir').find('td a.name').click();
+			fileList.findFileEl('testdir').find('td .nametext').click();
 
 			expect(OCA.Files.App.fileList.getCurrentDirectory()).toEqual('/somewhere/inside/subdir/testdir');
 
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index 09d698088ae07308e31f21dfdb65cd38847aa9e4..5c0c8c96bc5b2df714070f84f4b6ace06682c128 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -1870,6 +1870,50 @@ describe('OCA.Files.FileList tests', function() {
 			});
 		})
 	});
+	describe('Details sidebar', function() {
+		beforeEach(function() {
+			fileList.setFiles(testFiles);
+		});
+		it('Clicking on a file row will trigger file action if no details view configured', function() {
+			fileList._detailsView = null;
+			var updateDetailsViewStub = sinon.stub(fileList, '_updateDetailsView');
+			var actionStub = sinon.stub();
+			fileList.setFiles(testFiles);
+			fileList.fileActions.register(
+				'text/plain',
+				'Test',
+				OC.PERMISSION_ALL,
+				function() {
+					// Specify icon for hitory button
+					return OC.imagePath('core','actions/history');
+				},
+				actionStub
+			);
+			fileList.fileActions.setDefault('text/plain', 'Test');
+			var $tr = fileList.findFileEl('One.txt');
+			$tr.find('td.filename>a.name').click();
+			expect(actionStub.calledOnce).toEqual(true);
+			expect(updateDetailsViewStub.notCalled).toEqual(true);
+			updateDetailsViewStub.restore();
+		});
+		it('Clicking on a file row will trigger details sidebar', function() {
+			fileList.fileActions.setDefault('text/plain', 'Test');
+			var $tr = fileList.findFileEl('One.txt');
+			$tr.find('td.filename>a.name').click();
+			expect($tr.hasClass('highlighted')).toEqual(true);
+
+			expect(fileList._detailsView.getFileInfo().id).toEqual(1);
+		});
+		it('Clicking outside to deselect a file row will trigger details sidebar', function() {
+			var $tr = fileList.findFileEl('One.txt');
+			$tr.find('td.filename>a.name').click();
+
+			fileList.$el.find('tfoot').click();
+
+			expect($tr.hasClass('highlighted')).toEqual(false);
+			expect(fileList._detailsView.getFileInfo()).toEqual(null);
+		});
+	});
 	describe('File actions', function() {
 		it('Clicking on a file name will trigger default action', function() {
 			var actionStub = sinon.stub();
@@ -1886,7 +1930,7 @@ describe('OCA.Files.FileList tests', function() {
 			);
 			fileList.fileActions.setDefault('text/plain', 'Test');
 			var $tr = fileList.findFileEl('One.txt');
-			$tr.find('td.filename>a.name').click();
+			$tr.find('td.filename .nametext').click();
 			expect(actionStub.calledOnce).toEqual(true);
 			expect(actionStub.getCall(0).args[0]).toEqual('One.txt');
 			var context = actionStub.getCall(0).args[1];
diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js
new file mode 100644
index 0000000000000000000000000000000000000000..10ad38097c6b45bf8ab1c2776720f04cbe21dae4
--- /dev/null
+++ b/apps/files/tests/js/mainfileinfodetailviewSpec.js
@@ -0,0 +1,104 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2015 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+describe('OCA.Files.MainFileInfoDetailView tests', function() {
+	var view, tooltipStub, previewStub, fncLazyLoadPreview, fileListMock;
+
+	beforeEach(function() {
+		tooltipStub = sinon.stub($.fn, 'tooltip');
+		fileListMock = sinon.mock(OCA.Files.FileList.prototype);
+		view = new OCA.Files.MainFileInfoDetailView();
+	});
+	afterEach(function() {
+		view.destroy();
+		view = undefined;
+		tooltipStub.restore();
+		fileListMock.restore();
+
+	});
+	describe('rendering', function() {
+		var testFileInfo;
+		beforeEach(function() {
+			view = new OCA.Files.MainFileInfoDetailView();
+			testFileInfo = {
+				id: 5,
+				name: 'One.txt',
+				path: '/subdir',
+				size: 123456789,
+				mtime: Date.UTC(2015, 6, 17, 1, 2, 0, 0)
+			};
+		});
+		it('displays basic info', function() {
+			var clock = sinon.useFakeTimers(Date.UTC(2015, 6, 17, 1, 2, 0, 3));
+			var dateExpected = OC.Util.formatDate(Date(Date.UTC(2015, 6, 17, 1, 2, 0, 0)));
+			view.setFileInfo(testFileInfo);
+			expect(view.$el.find('.fileName').text()).toEqual('One.txt');
+			expect(view.$el.find('.fileName').attr('title')).toEqual('One.txt');
+			expect(view.$el.find('.size').text()).toEqual('117.7 MB');
+			expect(view.$el.find('.size').attr('title')).toEqual('123456789 bytes');
+			expect(view.$el.find('.date').text()).toEqual('a few seconds ago');
+			expect(view.$el.find('.date').attr('title')).toEqual(dateExpected);
+			clock.restore();
+		});
+		it('displays favorite icon', function() {
+			view.setFileInfo(_.extend(testFileInfo, {
+				tags: [OC.TAG_FAVORITE]
+			}));
+			expect(view.$el.find('.favorite img').attr('src'))
+				.toEqual(OC.imagePath('core', 'actions/starred'));
+
+			view.setFileInfo(_.extend(testFileInfo, {
+				tags: []
+			}));
+			expect(view.$el.find('.favorite img').attr('src'))
+				.toEqual(OC.imagePath('core', 'actions/star'));
+		});
+		it('displays mime icon', function() {
+			// File
+			view.setFileInfo(_.extend(testFileInfo, {
+				mimetype: 'text/calendar'
+			}));
+
+			expect(view.$el.find('.thumbnail').css('background-image'))
+				.toContain('filetypes/text-calendar.svg');
+
+			// Folder
+			view.setFileInfo(_.extend(testFileInfo, {
+				mimetype: 'httpd/unix-directory'
+			}));
+
+			expect(view.$el.find('.thumbnail').css('background-image'))
+				.toContain('filetypes/folder.svg');
+		});
+		it('displays thumbnail', function() {
+			view.setFileInfo(_.extend(testFileInfo, {
+				mimetype: 'text/plain'
+			}));
+
+			var expectation = fileListMock.expects('lazyLoadPreview');
+			expectation.once();
+
+			view.setFileInfo(testFileInfo);
+
+			fileListMock.verify();
+		});
+	});
+});
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
index f72f502462244ed96c9ce38a78033917ef490136..9000fafd8dd1835e4feb53c690fbe502b04b2e49 100644
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -56,6 +56,7 @@ $application->setupPropagation();
 
 \OCP\Util::addScript('files_sharing', 'share');
 \OCP\Util::addScript('files_sharing', 'external');
+\OCP\Util::addStyle('files_sharing', 'sharetabview');
 
 // FIXME: registering a job here will cause additional useless SQL queries
 // when the route is not cron.php, needs a better way
diff --git a/apps/files_sharing/css/sharetabview.css b/apps/files_sharing/css/sharetabview.css
new file mode 100644
index 0000000000000000000000000000000000000000..42c9bee71731ab7c5c456b434b40fa27442f7780
--- /dev/null
+++ b/apps/files_sharing/css/sharetabview.css
@@ -0,0 +1,3 @@
+.app-files .shareTabView {
+	min-height: 100px;
+}
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index 5923e426f05fafa262f2df0e902c3c47e0d92d2c..1993efe7d73261cf07222b0ed211d530d3375293 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -57,7 +57,8 @@ OCA.Sharing.PublicApp = {
 					scrollContainer: $(window),
 					dragOptions: dragOptions,
 					folderDropOptions: folderDropOptions,
-					fileActions: fileActions
+					fileActions: fileActions,
+					detailsViewEnabled: false
 				}
 			);
 			this.files = OCA.Files.Files;
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index e7823454c532d1f3bd9aaa58eb5e32c7acf53fe6..12bec0e8c9abef02ef2ae1c64774cbdff50a1d85 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -140,6 +140,10 @@
 					}
 				});
 			}, t('files_sharing', 'Share'));
+
+			OC.addScript('files_sharing', 'sharetabview').done(function() {
+				fileList.registerTabView(new OCA.Sharing.ShareTabView('shareTabView'));
+			});
 		},
 
 		/**
diff --git a/apps/files_sharing/js/sharetabview.js b/apps/files_sharing/js/sharetabview.js
new file mode 100644
index 0000000000000000000000000000000000000000..e02de9237519f942befdd8a92bfe693023687f50
--- /dev/null
+++ b/apps/files_sharing/js/sharetabview.js
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+	var TEMPLATE =
+		'<div>Owner: {{owner}}';
+
+	/**
+	 * @class OCA.Sharing.ShareTabView
+	 * @classdesc
+	 *
+	 * Displays sharing information
+	 *
+	 */
+	var ShareTabView = function(id) {
+		this.initialize(id);
+	};
+	/**
+	 * @memberof OCA.Sharing
+	 */
+	ShareTabView.prototype = _.extend({}, OCA.Files.DetailTabView.prototype,
+		/** @lends OCA.Sharing.ShareTabView.prototype */ {
+		_template: null,
+
+		/**
+		 * Initialize the details view
+		 */
+		initialize: function() {
+			OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments);
+			this.$el.addClass('shareTabView');
+		},
+
+		getLabel: function() {
+			return t('files_sharing', 'Sharing');
+		},
+
+		/**
+		 * Renders this details view
+		 */
+		render: function() {
+			this.$el.empty();
+
+			if (!this._template) {
+				this._template = Handlebars.compile(TEMPLATE);
+			}
+
+			if (this._fileInfo) {
+				this.$el.append(this._template({
+					owner: this._fileInfo.shareOwner || OC.currentUser
+				}));
+
+			} else {
+				// TODO: render placeholder text?
+			}
+		}
+	});
+
+	OCA.Sharing.ShareTabView = ShareTabView;
+})();
+
diff --git a/apps/files_sharing/tests/js/appSpec.js b/apps/files_sharing/tests/js/appSpec.js
index 49bca5680010e74dea33b69c1b35a2ef47e8a0c9..133bd44f7506957dfb8daf5c584c42a8ba4cfe56 100644
--- a/apps/files_sharing/tests/js/appSpec.js
+++ b/apps/files_sharing/tests/js/appSpec.js
@@ -132,7 +132,7 @@ describe('OCA.Sharing.App tests', function() {
 				shareOwner: 'user2'
 			}]);
 
-			fileListIn.findFileEl('testdir').find('td a.name').click();
+			fileListIn.findFileEl('testdir').find('td .nametext').click();
 
 			expect(OCA.Files.App.fileList.getCurrentDirectory()).toEqual('/somewhere/inside/subdir/testdir');
 
diff --git a/core/css/apps.css b/core/css/apps.css
index 57133729f151fea915c36e527372160b4b443a21..5769120c5ed08cab03efcb27ea2d46be37125866 100644
--- a/core/css/apps.css
+++ b/core/css/apps.css
@@ -417,7 +417,39 @@
 	min-height: 100%;
 }
 
+/* APP-SIDEBAR ----------------------------------------------------------------*/
+
+/*
+	Sidebar: a sidebar to be used within #app-content
+	 have it as first element within app-content in order to shrink other
+	 sibling containers properly. Compare Files app for example.
+*/
+#app-sidebar {
+	position: fixed;
+	top: 45px;
+	right: 0;
+	left: auto;
+	bottom: 0;
+	width: 27%;
+	display: block;
+	background: #eee;
+	-webkit-transition: margin-right 300ms;
+	-moz-transition: margin-right 300ms;
+	-o-transition: margin-right 300ms;
+	transition: margin-right 300ms;
+	overflow-x: hidden;
+	overflow-y: auto;
+	visibility: visible;
+	z-index: 500;
+}
 
+#app-content.with-app-sidebar {
+	margin-right: 27%;
+}
+
+#app-sidebar.disappear {
+	visibility: hidden;
+}
 
 /* APP-SETTINGS ---------------------------------------------------------------*/
 
@@ -556,3 +588,50 @@ em {
 	padding:16px;
 }
 
+/* generic tab styles */
+.tabHeaders {
+	margin: 15px;
+	background-color: #1D2D44;
+}
+
+.tabHeaders .tabHeader {
+	float: left;
+	border: 1px solid #ddd;
+	padding: 5px;
+	cursor: pointer;
+	background-color: #f8f8f8;
+	font-weight: bold;
+}
+.tabHeaders .tabHeader, .tabHeaders .tabHeader a {
+	color: #888;
+}
+
+.tabHeaders .tabHeader:first-child {
+	border-top-left-radius: 4px;
+	border-bottom-left-radius: 4px;
+}
+
+.tabHeaders .tabHeader:last-child {
+	border-top-right-radius: 4px;
+	border-bottom-right-radius: 4px;
+}
+
+.tabHeaders .tabHeader.selected,
+.tabHeaders .tabHeader:hover {
+	background-color: #e8e8e8;
+}
+
+.tabHeaders .tabHeader.selected,
+.tabHeaders .tabHeader.selected a,
+.tabHeaders .tabHeader:hover,
+.tabHeaders .tabHeader:hover a {
+	color: #000;
+}
+
+.tabsContainer {
+	clear: left;
+}
+
+.tabsContainer .tab {
+	padding: 15px;
+}
diff --git a/core/css/mobile.css b/core/css/mobile.css
index 80217d7069cdcb7a4ded9e15a4448cfa430a2726..2256d821d738519357239f8cc6e7bef050e38132 100644
--- a/core/css/mobile.css
+++ b/core/css/mobile.css
@@ -103,6 +103,10 @@
 	z-index: 1000;
 }
 
+#app-sidebar{
+	width: 100%;
+}
+
 /* allow horizontal scrollbar in settings
 	otherwise user management is not usable on mobile */
 #body-settings #app-content {
diff --git a/core/js/apps.js b/core/js/apps.js
index 71170bbc23a0c19dce0d425a1ec449cd3f4c031c..d0d351f5147939d564129fdfd20be19101fd1b1a 100644
--- a/core/js/apps.js
+++ b/core/js/apps.js
@@ -20,6 +20,26 @@
 		}
 	};
 
+	/**
+	 * Shows the #app-sidebar and add .with-app-sidebar to subsequent siblings
+	 */
+	exports.Apps.showAppSidebar = function() {
+		var $appSidebar = $('#app-sidebar');
+		$appSidebar.removeClass('disappear')
+		$('#app-content').addClass('with-app-sidebar');
+
+	};
+
+	/**
+	 * Shows the #app-sidebar and removes .with-app-sidebar from subsequent
+	 * siblings
+	 */
+	exports.Apps.hideAppSidebar = function() {
+		var $appSidebar = $('#app-sidebar');
+		$appSidebar.addClass('disappear');
+		$('#app-content').removeClass('with-app-sidebar');
+	};
+
 	/**
 	 * Provides a way to slide down a target area through a button and slide it
 	 * up if the user clicks somewhere else. Used for the news app settings and
diff --git a/core/js/core.json b/core/js/core.json
index 0f052b798a98668accafaacfa384a4002220bfa4..1053debaa99968ba9ad431113720a80c3c421e5a 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -20,6 +20,7 @@
 		"oc-dialogs.js",
 		"js.js",
 		"l10n.js",
+		"apps.js",
 		"share.js",
 		"octemplate.js",
 		"eventsource.js",
diff --git a/core/js/js.js b/core/js/js.js
index 45c9c90362fa44e9dc87ad8fcb0f0561db755d82..72d4edd28dd1fc21e5ec6148dbec0cd5f6b529f9 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -1366,13 +1366,13 @@ function initCore() {
 				// if there is a scrollbar …
 				if($('#app-content').get(0).scrollHeight > $('#app-content').height()) {
 					if($(window).width() > 768) {
-						controlsWidth = $('#content').width() - $('#app-navigation').width() - getScrollBarWidth();
+						controlsWidth = $('#content').width() - $('#app-navigation').width() - $('#app-sidebar').width() - getScrollBarWidth();
 					} else {
 						controlsWidth = $('#content').width() - getScrollBarWidth();
 					}
 				} else { // if there is none
 					if($(window).width() > 768) {
-						controlsWidth = $('#content').width() - $('#app-navigation').width();
+						controlsWidth = $('#content').width() - $('#app-navigation').width() - $('#app-sidebar').width();
 					} else {
 						controlsWidth = $('#content').width();
 					}
diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js
index 29293e89bcb7030d7d98bee8212c7771daad6328..dbe005ba2e9c71e00c78dbabc86971b30880c0a9 100644
--- a/core/js/tests/specHelper.js
+++ b/core/js/tests/specHelper.js
@@ -121,6 +121,8 @@ window.isPhantom = /phantom/i.test(navigator.userAgent);
 			OC.TestUtil = TestUtil;
 		}
 
+		moment.locale('en');
+
 		// reset plugins
 		OC.Plugins._plugins = [];