diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js
index 3764328a5d04624107538433a2f272440d19e316..800873cd63827a8f4595f202f9463aa5e0a90630 100644
--- a/apps/files_sharing/js/app.js
+++ b/apps/files_sharing/js/app.js
@@ -8,7 +8,9 @@
  *
  */
 
-OCA.Sharing = {};
+if (!OCA.Sharing) {
+	OCA.Sharing = {};
+}
 OCA.Sharing.App = {
 
 	_inFileList: null,
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index 5a42604c866dbc3c10d84a80f4897ac22e2fc783..db770ad150901dc14a823f50d91fdaf6473edacb 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -8,103 +8,154 @@
  *
  */
 
-$(document).ready(function() {
-	if (!_.isUndefined(OC.Share) && !_.isUndefined(OCA.Files)) {
-		// TODO: make a separate class for this or a hook or jQuery event ?
-		if (OCA.Files.FileList) {
-			var oldCreateRow = OCA.Files.FileList.prototype._createRow;
-			OCA.Files.FileList.prototype._createRow = function(fileData) {
-				var tr = oldCreateRow.apply(this, arguments);
-				if (fileData.shareOwner) {
-					tr.attr('data-share-owner', fileData.shareOwner);
-					// user should always be able to rename a mount point
-					if (fileData.isShareMountPoint) {
-						tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE);
-						tr.attr('data-reshare-permissions', fileData.permissions);
-					}
+(function() {
+	if (!OCA.Sharing) {
+		OCA.Sharing = {};
+	}
+	OCA.Sharing.Util = {
+		initialize: function() {
+			if (!_.isUndefined(OC.Share) && !_.isUndefined(OCA.Files)) {
+				// TODO: make a separate class for this or a hook or jQuery event ?
+				if (OCA.Files.FileList) {
+					var oldCreateRow = OCA.Files.FileList.prototype._createRow;
+					OCA.Files.FileList.prototype._createRow = function(fileData) {
+						var tr = oldCreateRow.apply(this, arguments);
+						if (fileData.shareOwner) {
+							tr.attr('data-share-owner', fileData.shareOwner);
+							// user should always be able to rename a mount point
+							if (fileData.isShareMountPoint) {
+								tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE);
+								tr.attr('data-reshare-permissions', fileData.permissions);
+							}
+						}
+						return tr;
+					};
 				}
-				return tr;
-			};
-		}
 
-		// use delegate to catch the case with multiple file lists
-		$('#content').delegate('#fileList', 'fileActionsReady',function(ev){
-			// if no share action exists because the admin disabled sharing for this user
-			// we create a share notification action to inform the user about files
-			// shared with him otherwise we just update the existing share action.
-			var fileList = ev.fileList;
-			var $fileList = $(this);
-			$fileList.find('[data-share-owner]').each(function() {
-				var $tr = $(this);
-				var $action;
-				var owner;
-				var message;
-				var permissions = $tr.data('permissions');
-				if(permissions & OC.PERMISSION_SHARE) {
-					$action = $tr.find('[data-Action="Share"]');
-					$action.addClass('permanent');
-					owner = $tr.closest('tr').attr('data-share-owner');
-					message = ' ' + t('files_sharing', 'Shared by {owner}', {owner: owner});
-					$action.find('span').text(message);
-				} else {
-					var shareNotification = '<a class="action action-share-notification permanent"' +
-							' data-action="Share-Notification" href="#" original-title="">' +
-							' <img class="svg" src="' + OC.imagePath('core', 'actions/share') + '"></img>';
-					$tr.find('.fileactions').append(function() {
-						var owner = $(this).closest('tr').attr('data-share-owner');
-						var shareBy = t('files_sharing', 'Shared by {owner}', {owner: owner});
-						var $result = $(shareNotification + '<span> ' + shareBy + '</span></span>');
-						$result.on('click', function() {
-							return false;
-						});
-						return $result;
+				// use delegate to catch the case with multiple file lists
+				$('#content').delegate('#fileList', 'fileActionsReady',function(ev){
+					// if no share action exists because the admin disabled sharing for this user
+					// we create a share notification action to inform the user about files
+					// shared with him otherwise we just update the existing share action.
+					var fileList = ev.fileList;
+					var $fileList = $(this);
+					$fileList.find('[data-share-owner]').each(function() {
+						var $tr = $(this);
+						var permissions = $tr.data('permissions');
+						if(permissions & OC.PERMISSION_SHARE) {
+							OC.Share.markFileAsShared($tr, true);
+						} else {
+							// TODO: make this work like/with OC.Share.markFileAsShared()
+							var shareNotification = '<a class="action action-share-notification permanent"' +
+									' data-action="Share-Notification" href="#" original-title="">' +
+									' <img class="svg" src="' + OC.imagePath('core', 'actions/share') + '"></img>';
+							$tr.find('.fileactions').append(function() {
+								var owner = $(this).closest('tr').attr('data-share-owner');
+								var shareBy = t('files_sharing', 'Shared by {owner}', {owner: owner});
+								var $result = $(shareNotification + '<span> ' + shareBy + '</span></span>');
+								$result.on('click', function() {
+									return false;
+								});
+								return $result;
+							});
+						}
 					});
-				}
-			});
 
-			if (!OCA.Sharing.sharesLoaded){
-				OC.Share.loadIcons('file', fileList);
-				// assume that we got all shares, so switching directories
-				// will not invalidate that list
-				OCA.Sharing.sharesLoaded = true;
-			}
-			else{
-				OC.Share.updateIcons('file', fileList);
-			}
-		});
+					if (!OCA.Sharing.sharesLoaded){
+						OC.Share.loadIcons('file', fileList);
+						// assume that we got all shares, so switching directories
+						// will not invalidate that list
+						OCA.Sharing.sharesLoaded = true;
+					}
+					else{
+						OC.Share.updateIcons('file', fileList);
+					}
+				});
 
-		OCA.Files.fileActions.register(
-				'all',
-				'Share',
-				OC.PERMISSION_SHARE,
-				OC.imagePath('core', 'actions/share'),
-				function(filename, context) {
+				OCA.Files.fileActions.register(
+						'all',
+						'Share',
+						OC.PERMISSION_SHARE,
+						OC.imagePath('core', 'actions/share'),
+						function(filename, context) {
 
-			var $tr = context.$file;
-			var itemType = 'file';
-			if ($tr.data('type') === 'dir') {
-				itemType = 'folder';
-			}
-			var possiblePermissions = $tr.data('reshare-permissions');
-			if (_.isUndefined(possiblePermissions)) {
-				possiblePermissions = $tr.data('permissions');
-			}
+					var $tr = context.$file;
+					var itemType = 'file';
+					if ($tr.data('type') === 'dir') {
+						itemType = 'folder';
+					}
+					var possiblePermissions = $tr.data('reshare-permissions');
+					if (_.isUndefined(possiblePermissions)) {
+						possiblePermissions = $tr.data('permissions');
+					}
 
-			var appendTo = $tr.find('td.filename');
-			// Check if drop down is already visible for a different file
-			if (OC.Share.droppedDown) {
-				if ($tr.data('id') !== $('#dropdown').attr('data-item-source')) {
-					OC.Share.hideDropDown(function () {
+					var appendTo = $tr.find('td.filename');
+					// Check if drop down is already visible for a different file
+					if (OC.Share.droppedDown) {
+						if ($tr.data('id') !== $('#dropdown').attr('data-item-source')) {
+							OC.Share.hideDropDown(function () {
+								$tr.addClass('mouseOver');
+								OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
+							});
+						} else {
+							OC.Share.hideDropDown();
+						}
+					} else {
 						$tr.addClass('mouseOver');
 						OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
+					}
+					$('#dropdown').on('sharesChanged', function(ev) {
+						// note: we only update the data attribute because updateIcon()
+						// is called automatically after this event
+						var userShares = ev.itemShares[OC.Share.SHARE_TYPE_USER] || [];
+						var groupShares = ev.itemShares[OC.Share.SHARE_TYPE_GROUP] || [];
+						var linkShares = ev.itemShares[OC.Share.SHARE_TYPE_LINK] || [];
+						var recipients = _.union(userShares, groupShares);
+						if (linkShares.length > 0) {
+							recipients.unshift(t('files_sharing', 'Public'));
+						}
+						// only update the recipients if they existed before
+						// (some file lists don't have them)
+						if (!_.isUndefined($tr.attr('data-share-recipients'))) {
+							// FIXME: use display names from users, we currently only got user ids
+							if (recipients.length) {
+								$tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients));
+							}
+							else {
+								$tr.attr('data-share-recipients', '');
+							}
+						}
 					});
-				} else {
-					OC.Share.hideDropDown();
-				}
-			} else {
-				$tr.addClass('mouseOver');
-				OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
+				});
 			}
-		});
-	}
+		},
+
+		/**
+		 * Formats a recipient array to be displayed.
+		 * The first four recipients will be shown and the
+		 * other ones will be shown as "+x" where "x" is the number of
+		 * remaining recipients.
+		 *
+		 * @param recipients recipients array
+		 * @param count optional total recipients count (in case the array was shortened)
+		 * @return formatted recipients display text
+		 */
+		formatRecipients: function(recipients, count) {
+			var maxRecipients = 4;
+			var text;
+			if (!_.isNumber(count)) {
+				count = recipients.length;
+			}
+			text = _.first(recipients, maxRecipients).join(', ');
+			if (count > maxRecipients) {
+				text += ', +' + (count - maxRecipients);
+			}
+			return text;
+		}
+	};
+})();
+
+$(document).ready(function() {
+	OCA.Sharing.Util.initialize();
 });
+
diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js
index ef1034ecfdc874b97a0334a07d351f337bb6df8b..9cf74abf6703505921a8a9c75fa60eb92128b631 100644
--- a/apps/files_sharing/js/sharedfilelist.js
+++ b/apps/files_sharing/js/sharedfilelist.js
@@ -48,6 +48,9 @@
 			if (this._sharedWithUser) {
 				$tr.attr('data-share-owner', fileData.shares[0].ownerDisplayName);
 			}
+			if (fileData.recipientsDisplayName) {
+				$tr.attr('data-share-recipients', fileData.recipientsDisplayName);
+			}
 			return $tr;
 		},
 
@@ -179,15 +182,15 @@
 				// inside the same file object (by file id).
 				.reduce(function(memo, file) {
 					var data = memo[file.id];
-					var counterPart = file.share.ownerDisplayName || file.share.targetDisplayName;
+					var recipient = file.share.targetDisplayName;
 					if (!data) {
 						data = memo[file.id] = file;
 						data.shares = [file.share];
 						// using a hash to make them unique,
 						// this is only a list to be displayed
-						data.counterParts = {};
+						data.recipients = {};
 						// counter is cheaper than calling _.keys().length
-						data.counterPartsCount = 0;
+						data.recipientsCount = 0;
 						data.mtime = file.share.stime;
 					}
 					else {
@@ -200,10 +203,14 @@
 
 					if (file.share.type === OC.Share.SHARE_TYPE_LINK) {
 						data.hasLinkShare = true;
-					} else if (counterPart && data.counterPartsCount < 10) {
+					} else if (recipient) {
 						// limit counterparts for output
-						data.counterParts[counterPart] = true;
-						data.counterPartsCount++;
+						if (data.recipientsCount < 3) {
+							// only store the first ones, they will be the only ones
+							// displayed
+							data.recipients[recipient] = true;
+						}
+						data.recipientsCount++;
 					}
 
 					delete file.share;
@@ -213,14 +220,18 @@
 				.values()
 				// Clean up
 				.each(function(data) {
-					// convert the counterParts map to a flat
+					// convert the recipients map to a flat
 					// array of sorted names
-					data.counterParts = _.chain(data.counterParts).keys().sort().value();
+					data.recipients = _.chain(data.recipients).keys().sort().value();
 					if (data.hasLinkShare) {
-						data.counterParts.unshift(t('files_sharing', 'link'));
+						data.recipients.unshift(t('files_sharing', 'Public'));
 						delete data.hasLinkShare;
 					}
-					delete data.counterPartsCount;
+					data.recipientsDisplayName = OCA.Sharing.Util.formatRecipients(
+						data.recipients,
+						data.recipientsCount
+					);
+					delete data.recipientsCount;
 				})
 				// Sort by expected sort comparator
 				.sortBy(this._sortComparator)
diff --git a/core/js/share.js b/core/js/share.js
index 0c6d39e446c378cfa607fb75339688c9516084ac..d80205317630a008368584f0d6d084bb7ad20709 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -56,20 +56,14 @@ OC.Share={
 				image = OC.imagePath('core', 'actions/public');
 			}
 			if (itemType !== 'file' && itemType !== 'folder') {
-				$fileList.find('a.share[data-item="'+item+'"]').css('background', 'url('+image+') no-repeat center');
+				$('a.share[data-item="'+item+'"]').css('background', 'url('+image+') no-repeat center');
 			} else {
+				// TODO: ultimately this part should be moved to files_sharing app
 				var file = $fileList.find('tr[data-id="'+item+'"]');
 				var shareFolder = OC.imagePath('core', 'filetypes/folder-shared');
 				var img;
 				if (file.length > 0) {
-					var type = file.data('type');
-					if (type === 'dir') {
-						file.children('.filename').css('background-image', 'url('+shareFolder+')');
-					}
-					var action = $(file).find('.fileactions .action[data-action="Share"]');
-					img = action.find('img').attr('src', image);
-					action.addClass('permanent');
-					action.html(' <span>'+t('core', 'Shared')+'</span>').prepend(img);
+					this.markFileAsShared(file, true, image);
 				} else {
 					var dir = currentDir;
 					if (dir.length > 1) {
@@ -82,6 +76,7 @@ OC.Share={
 								var files = $fileList.find('.filename');
 								var i;
 								for (i = 0; i < actions.length; i++) {
+									// TODO: use this.markFileAsShared()
 									img = $(actions[i]).find('img');
 									if (img.attr('src') !== OC.imagePath('core', 'actions/public')) {
 										img.attr('src', image);
@@ -125,29 +120,9 @@ OC.Share={
 		if (itemType != 'file' && itemType != 'folder') {
 			$('a.share[data-item="'+itemSource+'"]').css('background', 'url('+image+') no-repeat center');
 		} else {
-			var file = $('tr').filterAttr('data-id', String(itemSource));
-			if (file.length > 0) {
-				var type = file.data('type');
-				var shareFolder = OC.imagePath('core', 'filetypes/folder');
-				if (type === 'dir' && shares) {
-					shareFolder = OC.imagePath('core', 'filetypes/folder-shared');
-					file.children('.filename').css('background-image', 'url('+shareFolder+')');
-				} else if (type === 'dir') {
-					file.children('.filename').css('background-image', 'url('+shareFolder+')');
-				}
-				var action = $(file).find('.fileactions .action').filterAttr('data-action', 'Share');
-				// in case of multiple lists/rows, there might be more than one visible
-				action.each(function() {
-					var action = $(this);
-					var img = action.find('img').attr('src', image);
-					if (shares) {
-						action.addClass('permanent');
-						action.html(' <span>'+ escapeHTML(t('core', 'Shared'))+'</span>').prepend(img);
-					} else {
-						action.removeClass('permanent');
-						action.html(' <span>'+ escapeHTML(t('core', 'Share'))+'</span>').prepend(img);
-					}
-				});
+			var $tr = $('tr').filterAttr('data-id', String(itemSource));
+			if ($tr.length > 0) {
+				this.markFileAsShared($tr, shares, image);
 			}
 		}
 		if (shares) {
@@ -157,6 +132,59 @@ OC.Share={
 			delete OC.Share.statuses[itemSource];
 		}
 	},
+	/**
+	 * Marks/unmarks a given file as shared
+	 *
+	 * @param $tr file element to mark as shared
+	 * @param state true to mark as shared, false to unmark
+	 * @param image image to use for the icon
+	 */
+	markFileAsShared: function($tr, state, image) {
+		var action = $tr.find('.fileactions .action[data-action="Share"]');
+		var type = $tr.data('type');
+		var img = action.find('img');
+		var message;
+		var recipients;
+		var owner;
+		var shareFolderIcon;
+		if (type === 'dir' && state) {
+			shareFolderIcon = OC.imagePath('core', 'filetypes/folder-shared');
+			$tr.children('.filename').css('background-image', 'url(' + shareFolderIcon + ')');
+		} else if (type === 'dir') {
+			shareFolderIcon = OC.imagePath('core', 'filetypes/folder');
+			$tr.children('.filename').css('background-image', 'url(' + shareFolderIcon + ')');
+		}
+		if (state) {
+			recipients = $tr.attr('data-share-recipients');
+			owner = $tr.attr('data-share-owner');
+
+			action.addClass('permanent');
+			message = t('core', 'Shared');
+			if (owner && !recipients) {
+				message = t('files_sharing', 'Shared by {owner}', {owner: owner});
+				image = image || OC.imagePath('core', 'actions/share');
+			}
+			if (recipients) {
+				image = image || OC.imagePath('core', 'actions/shared');
+				if (owner) {
+					message = ' ' + t(
+						'files_sharing',
+						'Shared by {owner} with You, {recipients}',
+						{owner: owner, recipients: recipients}
+					);
+				}
+				else {
+					message = t('core', 'Shared with {recipients}', {recipients: recipients});
+				}
+			}
+			action.html(' <span>'+ message + '</span>').prepend(img);
+		}
+		else {
+			action.removeClass('permanent');
+			action.html(' <span>'+ escapeHTML(t('core', 'Share'))+'</span>').prepend(img);
+		}
+		img.attr('src', image);
+	},
 	loadItem:function(itemType, itemSource) {
 		var data = '';
 		var checkReshare = true;
@@ -384,6 +412,7 @@ OC.Share={
 				OC.Share.share(itemType, itemSource, shareType, shareWith, permissions, itemSourceName, expirationDate, function() {
 					OC.Share.addShareWith(shareType, shareWith, selected.item.label, permissions, possiblePermissions);
 					$('#shareWith').val('');
+					$('#dropdown').trigger(new $.Event('sharesChanged', {itemShares: OC.Share.itemShares}));
 					OC.Share.updateIcon(itemType, itemSource);
 				});
 				return false;
@@ -665,6 +694,7 @@ $(document).ready(function() {
 			$li.remove();
 			var index = OC.Share.itemShares[shareType].indexOf(shareWith);
 			OC.Share.itemShares[shareType].splice(index, 1);
+			$('#dropdown').trigger(new $.Event('sharesChanged', {itemShares: OC.Share.itemShares}));
 			OC.Share.updateIcon(itemType, itemSource);
 			if (typeof OC.Share.statuses[itemSource] === 'undefined') {
 				$('#expiration').hide('blind');
@@ -723,6 +753,7 @@ $(document).ready(function() {
 			if (oc_appconfig.core.enforcePasswordForPublicLink === false) {
 				OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, '', OC.PERMISSION_READ, itemSourceName, expirationDate, function(data) {
 					OC.Share.showLink(data.token, null, itemSource);
+					$('#dropdown').trigger(new $.Event('sharesChanged', {itemShares: OC.Share.itemShares}));
 					OC.Share.updateIcon(itemType, itemSource);
 				});
 			} else {