From efdc07e032a1f17c7ffa637431154672c88c97ae Mon Sep 17 00:00:00 2001 From: Vasily Date: Wed, 16 Oct 2019 12:30:26 +0300 Subject: [PATCH] Merge pull request #523 from grafixeyehero/itemcontextmenu-icon Add icon on item context menu (cherry picked from commit d4862df2661dc71db123637cced41a664f410607) Signed-off-by: Joshua Boniface --- src/components/itemcontextmenu.js | 297 +++++++++++++++++------------- 1 file changed, 166 insertions(+), 131 deletions(-) diff --git a/src/components/itemcontextmenu.js b/src/components/itemcontextmenu.js index 77bc88a25b..46a65cabc3 100644 --- a/src/components/itemcontextmenu.js +++ b/src/components/itemcontextmenu.js @@ -1,5 +1,5 @@ -define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', 'playbackManager', 'loading', 'appSettings', 'browser', 'actionsheet'], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) { - 'use strict'; +define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter", "playbackManager", "loading", "appSettings", "browser", "actionsheet"], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) { + "use strict"; function getCommands(options) { var item = options.item; @@ -9,18 +9,20 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', var user = options.user; var commands = []; - if (canPlay && item.MediaType !== 'Photo') { + if (canPlay && item.MediaType !== "Photo") { if (options.play !== false) { commands.push({ - name: globalize.translate('Play'), - id: 'resume' + name: globalize.translate("Play"), + id: "resume", + icon: "play_arrow" }); } - if (options.playAllFromHere && item.Type !== 'Program' && item.Type !== 'TvChannel') { + if (options.playAllFromHere && item.Type !== "Program" && item.Type !== "TvChannel") { commands.push({ - name: globalize.translate('PlayAllFromHere'), - id: 'playallfromhere' + name: globalize.translate("PlayAllFromHere"), + id: "playallfromhere", + icon: "play_arrow" }); } } @@ -28,22 +30,24 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (playbackManager.canQueue(item)) { if (options.queue !== false) { commands.push({ - name: globalize.translate('AddToPlayQueue'), - id: 'queue' + name: globalize.translate("AddToPlayQueue"), + id: "queue", + icon: "playlist_add" }); } if (options.queue !== false) { commands.push({ - name: globalize.translate('PlayNext'), - id: 'queuenext' + name: globalize.translate("PlayNext"), + id: "queuenext", + icon: "playlist_add" }); } //if (options.queueAllFromHere) { // commands.push({ - // name: globalize.translate('QueueAllFromHere'), - // id: 'queueallfromhere' + // name: globalize.translate("QueueAllFromHere"), + // id: "queueallfromhere" // }); //} } @@ -51,11 +55,12 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (item.IsFolder || item.Type === "MusicArtist" || item.Type === "MusicGenre") { - if (item.CollectionType !== 'livetv') { + if (item.CollectionType !== "livetv") { if (options.shuffle !== false) { commands.push({ - name: globalize.translate('Shuffle'), - id: 'shuffle' + name: globalize.translate("Shuffle"), + id: "shuffle", + icon: "shuffle" }); } } @@ -64,8 +69,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (item.MediaType === "Audio" || item.Type === "MusicAlbum" || item.Type === "MusicArtist" || item.Type === "MusicGenre") { if (options.instantMix !== false && !itemHelper.isLocalItem(item)) { commands.push({ - name: globalize.translate('InstantMix'), - id: 'instantmix' + name: globalize.translate("InstantMix"), + id: "instantmix", + icon: "shuffle" }); } } @@ -79,75 +85,91 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (!restrictOptions) { if (itemHelper.supportsAddingToCollection(item)) { commands.push({ - name: globalize.translate('AddToCollection'), - id: 'addtocollection' + name: globalize.translate("AddToCollection"), + id: "addtocollection", + icon: "playlist_add" }); } if (itemHelper.supportsAddingToPlaylist(item)) { commands.push({ - name: globalize.translate('AddToPlaylist'), - id: 'addtoplaylist' + name: globalize.translate("AddToPlaylist"), + id: "addtoplaylist", + icon: "playlist_add" }); } } - if ((item.Type === 'Timer') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) { + if ((item.Type === "Timer") && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) { commands.push({ - name: globalize.translate('CancelRecording'), - id: 'canceltimer' + name: globalize.translate("CancelRecording"), + id: "canceltimer", + icon: "cancel" }); } - if ((item.Type === 'Recording' && item.Status === 'InProgress') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) { + if ((item.Type === "Recording" && item.Status === "InProgress") && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) { commands.push({ - name: globalize.translate('CancelRecording'), - id: 'canceltimer' + name: globalize.translate("CancelRecording"), + id: "canceltimer", + icon: "cancel" }); } - if ((item.Type === 'SeriesTimer') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) { + if ((item.Type === "SeriesTimer") && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) { commands.push({ - name: globalize.translate('CancelSeries'), - id: 'cancelseriestimer' + name: globalize.translate("CancelSeries"), + id: "cancelseriestimer", + icon: "cancel" }); } if (item.CanDelete && options.deleteItem !== false) { - if (item.Type === 'Playlist' || item.Type === 'BoxSet') { + if (item.Type === "Playlist" || item.Type === "BoxSet") { commands.push({ - name: globalize.translate('Delete'), - id: 'delete' + name: globalize.translate("Delete"), + id: "delete", + icon: "delete" }); } else { commands.push({ - name: globalize.translate('DeleteMedia'), - id: 'delete' + name: globalize.translate("DeleteMedia"), + id: "delete", + icon: "delete" }); } } // Books are promoted to major download Button and therefor excluded in the context menu - if ((item.CanDownload && appHost.supports('filedownload')) && item.Type !== "Book") { + if ((item.CanDownload && appHost.supports("filedownload")) && item.Type !== "Book") { commands.push({ - name: globalize.translate('Download'), - id: 'download' + name: globalize.translate("Download"), + id: "download", + icon: "file_download" }); commands.push({ - name: globalize.translate('CopyStreamURL'), - id: 'copy-stream' + name: globalize.translate("CopyStreamURL"), + id: "copy-stream", + icon: "content_copy" + }); + } + + if (commands.length) { + commands.push({ + divider: true }); } var canEdit = itemHelper.canEdit(user, item); if (canEdit) { - if (options.edit !== false && item.Type !== 'SeriesTimer') { - var text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata'); + if (options.edit !== false && item.Type !== "SeriesTimer") { + var text = (item.Type === "Timer" || item.Type === "SeriesTimer") ? globalize.translate("Edit") : globalize.translate("EditMetadata"); commands.push({ name: text, - id: 'edit' + id: "edit", + icon: "edit" }); } } @@ -155,18 +177,20 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (itemHelper.canEditImages(user, item)) { if (options.editImages !== false) { commands.push({ - name: globalize.translate('EditImages'), - id: 'editimages' + name: globalize.translate("EditImages"), + id: "editimages", + icon: "edit" }); } } if (canEdit) { - if (item.MediaType === 'Video' && item.Type !== 'TvChannel' && item.Type !== 'Program' && item.LocationType !== 'Virtual' && !(item.Type === 'Recording' && item.Status !== 'Completed')) { + if (item.MediaType === "Video" && item.Type !== "TvChannel" && item.Type !== "Program" && item.LocationType !== "Virtual" && !(item.Type === "Recording" && item.Status !== "Completed")) { if (options.editSubtitles !== false) { commands.push({ - name: globalize.translate('EditSubtitles'), - id: 'editsubtitles' + name: globalize.translate("EditSubtitles"), + id: "editsubtitles", + icon: "closed_caption" }); } } @@ -175,8 +199,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (options.identify !== false) { if (itemHelper.canIdentify(user, item)) { commands.push({ - name: globalize.translate('Identify'), - id: 'identify' + name: globalize.translate("Identify"), + id: "identify", + icon: "edit" }); } } @@ -184,48 +209,54 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (item.MediaSources) { if (options.moremediainfo !== false) { commands.push({ - name: globalize.translate('MoreMediaInfo'), - id: 'moremediainfo' + name: globalize.translate("MoreMediaInfo"), + id: "moremediainfo", + icon: "info" }); } } - if (item.Type === 'Program' && options.record !== false) { + if (item.Type === "Program" && options.record !== false) { if (item.TimerId) { commands.push({ - name: Globalize.translate('ManageRecording'), - id: 'record' + name: Globalize.translate("ManageRecording"), + id: "record", + icon: "fiber_manual_record" }); } } - if (item.Type === 'Program' && options.record !== false) { + if (item.Type === "Program" && options.record !== false) { if (!item.TimerId) { commands.push({ - name: Globalize.translate('Record'), - id: 'record' + name: Globalize.translate("Record"), + id: "record", + icon: "fiber_manual_record" }); } } if (itemHelper.canRefreshMetadata(item, user)) { commands.push({ - name: globalize.translate('RefreshMetadata'), - id: 'refresh' + name: globalize.translate("RefreshMetadata"), + id: "refresh", + icon: "refresh" }); } if (item.PlaylistItemId && options.playlistId) { commands.push({ - name: globalize.translate('RemoveFromPlaylist'), - id: 'removefromplaylist' + name: globalize.translate("RemoveFromPlaylist"), + id: "removefromplaylist", + icon: "remove" }); } if (options.collectionId) { commands.push({ - name: globalize.translate('RemoveFromCollection'), - id: 'removefromcollection' + name: globalize.translate("RemoveFromCollection"), + id: "removefromcollection", + icon: "remove" }); } @@ -233,8 +264,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (options.share === true) { if (itemHelper.canShare(item, user)) { commands.push({ - name: globalize.translate('Share'), - id: 'share' + name: globalize.translate("Share"), + id: "share", + icon: "share" }); } } @@ -243,23 +275,26 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', if (options.sync !== false) { if (itemHelper.canSync(user, item)) { commands.push({ - name: globalize.translate('Sync'), - id: 'sync' + name: globalize.translate("Sync"), + id: "sync", + icon: "sync" }); } } - if (options.openAlbum !== false && item.AlbumId && item.MediaType !== 'Photo') { + if (options.openAlbum !== false && item.AlbumId && item.MediaType !== "Photo") { commands.push({ - name: Globalize.translate('ViewAlbum'), - id: 'album' + name: Globalize.translate("ViewAlbum"), + id: "album", + icon: "album" }); } if (options.openArtist !== false && item.ArtistItems && item.ArtistItems.length) { commands.push({ - name: Globalize.translate('ViewArtist'), - id: 'artist' + name: Globalize.translate("ViewArtist"), + id: "artist", + icon: "person" }); } @@ -283,24 +318,24 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', return new Promise(function (resolve, reject) { switch (id) { - case 'addtocollection': - require(['collectionEditor'], function (collectionEditor) { + case "addtocollection": + require(["collectionEditor"], function (collectionEditor) { new collectionEditor().show({ items: [itemId], serverId: serverId }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; - case 'addtoplaylist': - require(['playlistEditor'], function (playlistEditor) { + case "addtoplaylist": + require(["playlistEditor"], function (playlistEditor) { new playlistEditor().show({ items: [itemId], serverId: serverId }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; - case 'download': - require(['fileDownloader'], function (fileDownloader) { + case "download": + require(["fileDownloader"], function (fileDownloader) { var downloadHref = apiClient.getItemDownloadUrl(itemId); fileDownloader.download([{ url: downloadHref, @@ -310,7 +345,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', getResolveFunction(getResolveFunction(resolve, id), id)(); }); break; - case 'copy-stream': + case "copy-stream": var downloadHref = apiClient.getItemDownloadUrl(itemId); var textArea = document.createElement("textarea"); textArea.value = downloadHref; @@ -318,10 +353,10 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', textArea.focus(); textArea.select(); try { - document.execCommand('copy'); + document.execCommand("copy"); - require(['toast'], function (toast) { - toast(globalize.translate('CopyStreamURLSuccess')); + require(["toast"], function (toast) { + toast(globalize.translate("CopyStreamURLSuccess")); }); } catch (err) { console.error("Failed to copy to clipboard"); @@ -330,118 +365,118 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', document.body.removeChild(textArea); getResolveFunction(resolve, id)(); break; - case 'editsubtitles': - require(['subtitleEditor'], function (subtitleEditor) { + case "editsubtitles": + require(["subtitleEditor"], function (subtitleEditor) { subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; - case 'edit': + case "edit": editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); break; - case 'editimages': - require(['imageEditor'], function (imageEditor) { + case "editimages": + require(["imageEditor"], function (imageEditor) { imageEditor.show({ itemId: itemId, serverId: serverId }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; - case 'identify': - require(['itemIdentifier'], function (itemIdentifier) { + case "identify": + require(["itemIdentifier"], function (itemIdentifier) { itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; - case 'moremediainfo': - require(['itemMediaInfo'], function (itemMediaInfo) { + case "moremediainfo": + require(["itemMediaInfo"], function (itemMediaInfo) { itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; - case 'refresh': + case "refresh": refresh(apiClient, item); getResolveFunction(resolve, id)(); break; - case 'open': + case "open": appRouter.showItem(item); getResolveFunction(resolve, id)(); break; - case 'play': + case "play": play(item, false); getResolveFunction(resolve, id)(); break; - case 'resume': + case "resume": play(item, true); getResolveFunction(resolve, id)(); break; - case 'queue': + case "queue": play(item, false, true); getResolveFunction(resolve, id)(); break; - case 'queuenext': + case "queuenext": play(item, false, true, true); getResolveFunction(resolve, id)(); break; - case 'record': - require(['recordingCreator'], function (recordingCreator) { + case "record": + require(["recordingCreator"], function (recordingCreator) { recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; - case 'shuffle': + case "shuffle": playbackManager.shuffle(item); getResolveFunction(resolve, id)(); break; - case 'instantmix': + case "instantmix": playbackManager.instantMix(item); getResolveFunction(resolve, id)(); break; - case 'delete': + case "delete": deleteItem(apiClient, item).then(getResolveFunction(resolve, id, true, true), getResolveFunction(resolve, id)); break; - case 'share': + case "share": navigator.share({ title: item.Name, text: item.Overview, url: "https://github.com/jellyfin/jellyfin" }); break; - case 'album': + case "album": appRouter.showItem(item.AlbumId, item.ServerId); getResolveFunction(resolve, id)(); break; - case 'artist': + case "artist": appRouter.showItem(item.ArtistItems[0].Id, item.ServerId); getResolveFunction(resolve, id)(); break; - case 'playallfromhere': + case "playallfromhere": getResolveFunction(resolve, id)(); break; - case 'queueallfromhere': + case "queueallfromhere": getResolveFunction(resolve, id)(); break; - case 'removefromplaylist': + case "removefromplaylist": apiClient.ajax({ - url: apiClient.getUrl('Playlists/' + options.playlistId + '/Items', { - EntryIds: [item.PlaylistItemId].join(',') + url: apiClient.getUrl("Playlists/" + options.playlistId + "/Items", { + EntryIds: [item.PlaylistItemId].join(",") }), - type: 'DELETE' + type: "DELETE" }).then(function () { getResolveFunction(resolve, id, true)(); }); break; - case 'removefromcollection': + case "removefromcollection": apiClient.ajax({ type: "DELETE", url: apiClient.getUrl("Collections/" + options.collectionId + "/Items", { - Ids: [item.Id].join(',') + Ids: [item.Id].join(",") }) }).then(function () { getResolveFunction(resolve, id, true)(); }); break; - case 'canceltimer': + case "canceltimer": deleteTimer(apiClient, item, resolve, id); break; - case 'cancelseriestimer': + case "cancelseriestimer": deleteSeriesTimer(apiClient, item, resolve, id); break; default: @@ -452,7 +487,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function deleteTimer(apiClient, item, resolve, command) { - require(['recordingHelper'], function (recordingHelper) { + require(["recordingHelper"], function (recordingHelper) { var timerId = item.TimerId || item.Id; recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () { getResolveFunction(resolve, command, true)(); @@ -461,7 +496,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function deleteSeriesTimer(apiClient, item, resolve, command) { - require(['recordingHelper'], function (recordingHelper) { + require(["recordingHelper"], function (recordingHelper) { recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () { getResolveFunction(resolve, command, true)(); }); @@ -469,14 +504,14 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function play(item, resume, queue, queueNext) { - var method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play'; + var method = queue ? (queueNext ? "queueNext" : "queue") : "play"; var startPosition = 0; if (resume && item.UserData && item.UserData.PlaybackPositionTicks) { startPosition = item.UserData.PlaybackPositionTicks; } - if (item.Type === 'Program') { + if (item.Type === "Program") { playbackManager[method]({ ids: [item.ChannelId], startPositionTicks: startPosition, @@ -494,16 +529,16 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', return new Promise(function (resolve, reject) { var serverId = apiClient.serverInfo().Id; - if (item.Type === 'Timer') { - require(['recordingEditor'], function (recordingEditor) { + if (item.Type === "Timer") { + require(["recordingEditor"], function (recordingEditor) { recordingEditor.show(item.Id, serverId).then(resolve, reject); }); - } else if (item.Type === 'SeriesTimer') { - require(['seriesRecordingEditor'], function (recordingEditor) { + } else if (item.Type === "SeriesTimer") { + require(["seriesRecordingEditor"], function (recordingEditor) { recordingEditor.show(item.Id, serverId).then(resolve, reject); }); } else { - require(['metadataEditor'], function (metadataEditor) { + require(["metadataEditor"], function (metadataEditor) { metadataEditor.show(item.Id, serverId).then(resolve, reject); }); } @@ -512,7 +547,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', function deleteItem(apiClient, item) { return new Promise(function (resolve, reject) { - require(['deleteHelper'], function (deleteHelper) { + require(["deleteHelper"], function (deleteHelper) { deleteHelper.deleteItem({ item: item, navigate: false @@ -524,11 +559,11 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function refresh(apiClient, item) { - require(['refreshDialog'], function (refreshDialog) { + require(["refreshDialog"], function (refreshDialog) { new refreshDialog({ itemIds: [item.Id], serverId: apiClient.serverInfo().Id, - mode: item.Type === 'CollectionFolder' ? 'scan' : null + mode: item.Type === "CollectionFolder" ? "scan" : null }).show(); }); } @@ -542,7 +577,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', return actionsheet.show({ items: commands, positionTo: options.positionTo, - resolveOnClick: ['share'] + resolveOnClick: ["share"] }).then(function (id) { return executeCommand(options.item, id, options); });