diff --git a/TODO.md b/TODO.md index e2a048e5..364bc142 100644 --- a/TODO.md +++ b/TODO.md @@ -32,7 +32,6 @@ This helps with scalability * I2P Status panel - display message when connected to external router * Search box - left identation * Ability to disable switching of tabs on actions -* Ability to trust/browse/subscribe from uploads tab ### Web UI/Plugin * HTML 5 media players diff --git a/core/src/main/groovy/com/muwire/core/chat/ChatManager.groovy b/core/src/main/groovy/com/muwire/core/chat/ChatManager.groovy index 8f347109..64c424e4 100644 --- a/core/src/main/groovy/com/muwire/core/chat/ChatManager.groovy +++ b/core/src/main/groovy/com/muwire/core/chat/ChatManager.groovy @@ -29,6 +29,10 @@ class ChatManager { timer.schedule({connect()} as TimerTask, 1000, 1000) } + boolean isConnected(Persona p) { + clients.containsKey(p) + } + void onUIConnectChatEvent(UIConnectChatEvent e) { if (e.host == me) { eventBus.publish(new ChatConnectionEvent(status : ChatConnectionAttemptStatus.SUCCESSFUL, diff --git a/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy b/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy index 7728da0f..ca39d2ec 100644 --- a/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy +++ b/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy @@ -152,4 +152,9 @@ class ContentUploader extends Uploader { public boolean isChatEnabled() { request.chat } + + @Override + public Persona getDownloaderPersona() { + request.downloader + } } diff --git a/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy b/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy index 26677807..cfa4d8da 100644 --- a/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy +++ b/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy @@ -4,6 +4,7 @@ import java.nio.ByteBuffer import java.nio.charset.StandardCharsets import com.muwire.core.InfoHash +import com.muwire.core.Persona import com.muwire.core.connection.Endpoint import net.i2p.data.Base64 @@ -90,4 +91,9 @@ class HashListUploader extends Uploader { public boolean isChatEnabled() { return false; } + + @Override + public Persona getDownloaderPersona() { + request.downloader + } } diff --git a/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy b/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy index 4e4986c7..20855107 100644 --- a/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy +++ b/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy @@ -6,6 +6,7 @@ import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.StandardOpenOption +import com.muwire.core.Persona import com.muwire.core.connection.Endpoint abstract class Uploader { @@ -31,6 +32,7 @@ abstract class Uploader { } abstract String getName(); + /** * @return an integer between 0 and 100 @@ -38,6 +40,7 @@ abstract class Uploader { abstract int getProgress(); abstract String getDownloader(); + abstract Persona getDownloaderPersona(); abstract int getDonePieces(); diff --git a/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy b/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy index 01edfc0a..de80e532 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy @@ -33,6 +33,7 @@ import com.muwire.core.filecert.UICreateCertificateEvent import com.muwire.core.filefeeds.Feed import com.muwire.core.filefeeds.FeedItem import com.muwire.core.filefeeds.UIDownloadFeedItemEvent +import com.muwire.core.filefeeds.UIFeedConfigurationEvent import com.muwire.core.filefeeds.UIFeedDeletedEvent import com.muwire.core.filefeeds.UIFeedUpdateEvent import com.muwire.core.filefeeds.UIFilePublishedEvent @@ -356,6 +357,47 @@ class MainFrameController { startChat(p) view.showChatWindow.call() } + + @ControllerAction + void browseFromUpload() { + Uploader u = view.selectedUploader() + if (u == null) + return + Persona p = u.getDownloaderPersona() + + String groupId = p.getHumanReadableName() + "-browse" + def params = [:] + params['host'] = p + params['core'] = model.core + mvcGroup.createMVCGroup("browse",groupId,params) + } + + @ControllerAction + void subscribeFromUpload() { + Uploader u = view.selectedUploader() + if (u == null) + return + Persona p = u.getDownloaderPersona() + + Feed feed = new Feed(p) + feed.setAutoDownload(core.muOptions.defaultFeedAutoDownload) + feed.setSequential(core.muOptions.defaultFeedSequential) + feed.setItemsToKeep(core.muOptions.defaultFeedItemsToKeep) + feed.setUpdateInterval(core.muOptions.defaultFeedUpdateInterval) + + core.eventBus.publish(new UIFeedConfigurationEvent(feed : feed, newFeed : true)) + view.showFeedsWindow.call() + } + + @ControllerAction + void chatFromUpload() { + Uploader u = view.selectedUploader() + if (u == null) + return + Persona p = u.getDownloaderPersona() + startChat(p) + view.showChatWindow.call() + } void unshareSelectedFile() { def sf = view.selectedSharedFiles() diff --git a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy index f0c4f4fa..a31fbd54 100644 --- a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy @@ -44,6 +44,8 @@ import com.muwire.core.filefeeds.FeedFetchStatus import com.muwire.core.filefeeds.FeedItem import com.muwire.core.files.FileSharedEvent import com.muwire.core.trust.RemoteTrustList +import com.muwire.core.upload.Uploader + import java.awt.BorderLayout import java.awt.CardLayout import java.awt.FlowLayout @@ -782,18 +784,14 @@ class MainFrameView { selectionModel = uploadsTable.getSelectionModel() selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION) - JPopupMenu uploadsTableMenu = new JPopupMenu() - JMenuItem showInLibrary = new JMenuItem("Show in library") - showInLibrary.addActionListener({mvcGroup.controller.showInLibrary()}) - uploadsTableMenu.add(showInLibrary) uploadsTable.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent e) { - if (e.isPopupTrigger()) - showPopupMenu(uploadsTableMenu, e) + if (e.isPopupTrigger() || e.button == MouseEvent.BUTTON3) + showUploadsMenu(e) } public void mousePressed(MouseEvent e) { - if (e.isPopupTrigger()) - showPopupMenu(uploadsTableMenu, e) + if (e.isPopupTrigger() || e.button == MouseEvent.BUTTON3) + showUploadsMenu() } }) @@ -1205,7 +1203,6 @@ class MainFrameView { List items = selectedFeedItems() if (items == null || items.isEmpty()) return - // TODO: finish JPopupMenu menu = new JPopupMenu() if (model.downloadFeedItemButtonEnabled) { JMenuItem download = new JMenuItem("Download") @@ -1255,6 +1252,37 @@ class MainFrameView { } } + void showUploadsMenu(MouseEvent e) { + Uploader uploader = selectedUploader() + if (uploader == null) + return + + JPopupMenu uploadsTableMenu = new JPopupMenu() + JMenuItem showInLibrary = new JMenuItem("Show in library") + showInLibrary.addActionListener({mvcGroup.controller.showInLibrary()}) + uploadsTableMenu.add(showInLibrary) + + if (uploader.isBrowseEnabled()) { + JMenuItem browseItem = new JMenuItem("Browse Host") + browseItem.addActionListener({mvcGroup.controller.browseFromUpload()}) + uploadsTableMenu.add(browseItem) + } + + if (uploader.isFeedEnabled() && mvcGroup.controller.core.feedManager.getFeed(uploader.getDownloaderPersona()) == null) { + JMenuItem feedItem = new JMenuItem("Subscribe") + feedItem.addActionListener({mvcGroup.controller.subscribeFromUpload()}) + uploadsTableMenu.add(feedItem) + } + + if (uploader.isChatEnabled() && !mvcGroup.controller.core.chatManager.isConnected(uploader.getDownloaderPersona())) { + JMenuItem chatItem = new JMenuItem("Chat") + chatItem.addActionListener({mvcGroup.controller.chatFromUpload()}) + uploadsTableMenu.add(chatItem) + } + + showPopupMenu(uploadsTableMenu, e) + } + void showRestoreOrEmpty() { def searchWindow = builder.getVariable("search window") String id