Display share icon in file list row. Update share icon status when the sharing state changed.tags/v8.2beta1
@@ -367,6 +367,20 @@ | |||
return model; | |||
}, | |||
/** | |||
* Displays the details view for the given file and | |||
* selects the given tab | |||
* | |||
* @param {string} fileName file name for which to show details | |||
* @param {string} [tabId] optional tab id to select | |||
*/ | |||
showDetailsView: function(fileName, tabId) { | |||
this._updateDetailsView(fileName); | |||
if (tabId) { | |||
this._detailsView.selectTab(tabId); | |||
} | |||
}, | |||
/** | |||
* Update the details view to display the given file | |||
* |
@@ -32,6 +32,7 @@ | |||
if (fileList.id === 'trashbin' || fileList.id === 'files.public') { | |||
return; | |||
} | |||
var fileActions = fileList.fileActions; | |||
var oldCreateRow = fileList._createRow; | |||
fileList._createRow = function(fileData) { | |||
var tr = oldCreateRow.apply(this, arguments); | |||
@@ -78,7 +79,9 @@ | |||
$files = fileList.$fileList.find('tr'); | |||
} | |||
_.each($files, function(file) { | |||
OCA.Sharing.Util.updateFileActionIcon($(file)); | |||
var $tr = $(file); | |||
var shareStatus = OC.Share.statuses[$tr.data('id')]; | |||
OCA.Sharing.Util._updateFileActionIcon($tr, !!shareStatus, shareStatus && shareStatus.link); | |||
}); | |||
} | |||
@@ -96,22 +99,66 @@ | |||
} | |||
}); | |||
fileList.registerTabView(new OCA.Sharing.ShareTabView('shareTabView')); | |||
fileActions.registerAction({ | |||
name: 'Share', | |||
displayName: '', | |||
mime: 'all', | |||
permissions: OC.PERMISSION_SHARE, | |||
icon: OC.imagePath('core', 'actions/share'), | |||
type: OCA.Files.FileActions.TYPE_INLINE, | |||
actionHandler: function(fileName) { | |||
fileList.showDetailsView(fileName, 'shareTabView'); | |||
} | |||
}); | |||
var shareTab = new OCA.Sharing.ShareTabView('shareTabView'); | |||
// detect changes and change the matching list entry | |||
shareTab.on('sharesChanged', function(shareModel) { | |||
var fileInfoModel = shareModel.fileInfoModel; | |||
var $tr = fileList.findFileEl(fileInfoModel.get('name')); | |||
OCA.Sharing.Util._updateFileListDataAttributes(fileList, $tr, shareModel); | |||
if (!OCA.Sharing.Util._updateFileActionIcon($tr, shareModel.hasUserShares(), shareModel.hasLinkShare())) { | |||
// remove icon, if applicable | |||
OC.Share.markFileAsShared($tr, false, false); | |||
} | |||
}); | |||
fileList.registerTabView(shareTab); | |||
}, | |||
/** | |||
* Update file list data attributes | |||
*/ | |||
_updateFileListDataAttributes: function(fileList, $tr, shareModel) { | |||
// files app current cannot show recipients on load, so we don't update the | |||
// icon when changed for consistency | |||
if (fileList.id === 'files') { | |||
return; | |||
} | |||
var recipients = _.pluck(shareModel.get('shares'), 'share_with_displayname'); | |||
// note: we only update the data attribute because updateIcon() | |||
if (recipients.length) { | |||
$tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients)); | |||
} | |||
else { | |||
$tr.removeAttr('data-share-recipients'); | |||
} | |||
}, | |||
/** | |||
* Update the file action share icon for the given file | |||
* | |||
* @param $tr file element of the file to update | |||
* @param {bool} hasUserShares true if a user share exists | |||
* @param {bool} hasLinkShare true if a link share exists | |||
* | |||
* @return {bool} true if the icon was set, false otherwise | |||
*/ | |||
updateFileActionIcon: function($tr) { | |||
_updateFileActionIcon: function($tr, hasUserShares, hasLinkShare) { | |||
// if the statuses are loaded already, use them for the icon | |||
// (needed when scrolling to the next page) | |||
var shareStatus = OC.Share.statuses[$tr.data('id')]; | |||
if (shareStatus || $tr.attr('data-share-recipients') || $tr.attr('data-share-owner')) { | |||
if (hasUserShares || hasLinkShare || $tr.attr('data-share-recipients') || $tr.attr('data-share-owner')) { | |||
var permissions = $tr.data('permissions'); | |||
var hasLink = !!(shareStatus && shareStatus.link); | |||
OC.Share.markFileAsShared($tr, true, hasLink); | |||
OC.Share.markFileAsShared($tr, true, hasLinkShare); | |||
if ((permissions & OC.PERMISSION_SHARE) === 0 && $tr.attr('data-share-owner')) { | |||
// 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 | |||
@@ -130,7 +177,9 @@ | |||
return $result; | |||
}); | |||
} | |||
return true; | |||
} | |||
return false; | |||
}, | |||
/** |
@@ -38,8 +38,10 @@ | |||
* Renders this details view | |||
*/ | |||
render: function() { | |||
var self = this; | |||
if (this._dialog) { | |||
// remove/destroy older instance | |||
this._dialog.model.off(); | |||
this._dialog.remove(); | |||
this._dialog = null; | |||
} | |||
@@ -69,7 +71,10 @@ | |||
}); | |||
this.$el.find('.dialogContainer').append(this._dialog.$el); | |||
this._dialog.render(); | |||
shareModel.fetch(); | |||
this._dialog.model.fetch(); | |||
this._dialog.model.on('change', function() { | |||
self.trigger('sharesChanged', shareModel); | |||
}); | |||
} else { | |||
this.$el.empty(); | |||
// TODO: render placeholder text? |
@@ -175,7 +175,7 @@ | |||
this._collections = {}; | |||
if(!this.model.hasShares()) { | |||
if(!this.model.hasUserShares()) { | |||
return []; | |||
} | |||
@@ -149,8 +149,6 @@ | |||
options.error(model); | |||
} | |||
} | |||
//FIXME: updateIcon belongs to view | |||
OC.Share.updateIcon(itemType, itemSource); | |||
}, | |||
function(result) { | |||
var msg = t('core', 'Error'); | |||
@@ -236,8 +234,6 @@ | |||
var itemSource = this.get('itemSource'); | |||
OC.Share.share(itemType, itemSource, shareType, shareWith, permissions, fileName, options.expiration, function() { | |||
model.fetch(); | |||
//FIXME: updateIcon belongs to view | |||
OC.Share.updateIcon(itemType, itemSource); | |||
}); | |||
}, | |||
@@ -255,8 +251,6 @@ | |||
OC.Share.unshare(itemType, itemSource, shareType, shareWith, function() { | |||
model.fetch(); | |||
//FIXME: updateIcon belongs to view | |||
OC.Share.updateIcon(itemType, itemSource); | |||
}); | |||
}, | |||
@@ -291,12 +285,25 @@ | |||
}, | |||
/** | |||
* whether this item has share information | |||
* whether this item has user share information | |||
* @returns {boolean} | |||
*/ | |||
hasShares: function() { | |||
hasUserShares: function() { | |||
var shares = this.get('shares'); | |||
return _.isArray(this.get('shares')); | |||
return _.isArray(shares) && shares.length > 0; | |||
}, | |||
/** | |||
* Returns whether this item has a link share | |||
* | |||
* @return {bool} true if a link share exists, false otherwise | |||
*/ | |||
hasLinkShare: function() { | |||
var linkShare = this.get('linkShare'); | |||
if (linkShare && linkShare.isLinkShare) { | |||
return true; | |||
} | |||
return false; | |||
}, | |||
/** | |||
@@ -544,7 +551,27 @@ | |||
}); | |||
}, | |||
legacyFillCurrentShares: function(shares) { | |||
/** | |||
* Updates OC.Share.itemShares and OC.Share.statuses. | |||
* | |||
* This is required in case the user navigates away and comes back, | |||
* the share statuses from the old arrays are still used to fill in the icons | |||
* in the file list. | |||
*/ | |||
_legacyFillCurrentShares: function(shares) { | |||
var fileId = this.fileInfoModel.get('id'); | |||
if (!shares || !shares.length) { | |||
delete OC.Share.statuses[fileId]; | |||
return; | |||
} | |||
var currentShareStatus = OC.Share.statuses[fileId]; | |||
if (!currentShareStatus) { | |||
currentShareStatus = {link: false}; | |||
OC.Share.statuses[fileId] = currentShareStatus; | |||
} | |||
currentShareStatus.link = false; | |||
OC.Share.currentShares = {}; | |||
OC.Share.itemShares = []; | |||
_.each(shares, | |||
@@ -552,15 +579,15 @@ | |||
* @param {OC.Share.Types.ShareInfo} share | |||
*/ | |||
function(share) { | |||
if (!OC.Share.currentShares[share.share_type]) { | |||
OC.Share.currentShares[share.share_type] = []; | |||
} | |||
OC.Share.currentShares[share.share_type].push(share); | |||
if (!OC.Share.itemShares[share.share_type]) { | |||
OC.Share.itemShares[share.share_type] = []; | |||
if (share.share_type === OC.Share.SHARE_TYPE_LINK) { | |||
OC.Share.itemShares[share.share_type] = true; | |||
currentShareStatus.link = true; | |||
} else { | |||
if (!OC.Share.itemShares[share.share_type]) { | |||
OC.Share.itemShares[share.share_type] = []; | |||
} | |||
OC.Share.itemShares[share.share_type].push(share.share_with); | |||
} | |||
OC.Share.itemShares[share.share_type].push(share.share_with); | |||
} | |||
); | |||
}, | |||
@@ -589,7 +616,7 @@ | |||
/** @type {OC.Share.Types.ShareInfo[]} **/ | |||
var shares = _.toArray(data.shares); | |||
this.legacyFillCurrentShares(shares); | |||
this._legacyFillCurrentShares(shares); | |||
var linkShare = { isLinkShare: false }; | |||
// filter out the share by link |