From 799a2a99dfdce58596069a1b3c461ebc232cd8da Mon Sep 17 00:00:00 2001 From: Zlatin Balevsky Date: Sun, 2 May 2021 15:28:53 +0100 Subject: [PATCH] ability to create and delete folders --- .../main/groovy/com/muwire/core/Core.groovy | 4 ++ .../muwire/core/messenger/Messenger.groovy | 21 +++++++ .../core/messenger/UIFolderCreateEvent.groovy | 7 +++ .../core/messenger/UIFolderDeleteEvent.groovy | 7 +++ .../com/muwire/gui/MainFrameController.groovy | 57 +++++++++++++++++++ gui/griffon-app/i18n/messages.properties | 8 +++ .../com/muwire/gui/MainFrameModel.groovy | 2 + .../views/com/muwire/gui/MainFrameView.groovy | 41 ++++++++++++- 8 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 core/src/main/groovy/com/muwire/core/messenger/UIFolderCreateEvent.groovy create mode 100644 core/src/main/groovy/com/muwire/core/messenger/UIFolderDeleteEvent.groovy diff --git a/core/src/main/groovy/com/muwire/core/Core.groovy b/core/src/main/groovy/com/muwire/core/Core.groovy index 6517020f..78104a90 100644 --- a/core/src/main/groovy/com/muwire/core/Core.groovy +++ b/core/src/main/groovy/com/muwire/core/Core.groovy @@ -2,6 +2,8 @@ package com.muwire.core import com.muwire.core.files.PersisterDoneEvent import com.muwire.core.files.PersisterFolderService +import com.muwire.core.messenger.UIFolderCreateEvent +import com.muwire.core.messenger.UIFolderDeleteEvent import java.nio.charset.StandardCharsets import java.util.concurrent.atomic.AtomicBoolean @@ -499,6 +501,8 @@ public class Core { register(UIMessageEvent.class, messenger) register(UIMessageDeleteEvent.class, messenger) register(UIMessageReadEvent.class, messenger) + register(UIFolderCreateEvent.class, messenger) + register(UIFolderDeleteEvent.class, messenger) } File modulesProps = new File(home, "mwmodules.list") diff --git a/core/src/main/groovy/com/muwire/core/messenger/Messenger.groovy b/core/src/main/groovy/com/muwire/core/messenger/Messenger.groovy index b5b0a094..ae39b314 100644 --- a/core/src/main/groovy/com/muwire/core/messenger/Messenger.groovy +++ b/core/src/main/groovy/com/muwire/core/messenger/Messenger.groovy @@ -256,4 +256,25 @@ class Messenger { File messageFile = new File(file, deriveName(message)) messageFile.delete() } + + synchronized void onUIFolderCreateEvent(UIFolderCreateEvent e) { + File folder = new File(localFolders, e.name) + if (folder.mkdir()) { + folders.put(e.name, folder) + messages.put(folder, new LinkedHashSet()) + } + } + + synchronized void onUIFolderDeleteEvent(UIFolderDeleteEvent e) { + File folder = new File(localFolders, e.name) + if (!folder.exists()) + return + + folders.remove(e.name) + messages.remove(folder) + + diskIO.execute({ + folder.deleteDir() + }) + } } \ No newline at end of file diff --git a/core/src/main/groovy/com/muwire/core/messenger/UIFolderCreateEvent.groovy b/core/src/main/groovy/com/muwire/core/messenger/UIFolderCreateEvent.groovy new file mode 100644 index 00000000..3dafd680 --- /dev/null +++ b/core/src/main/groovy/com/muwire/core/messenger/UIFolderCreateEvent.groovy @@ -0,0 +1,7 @@ +package com.muwire.core.messenger + +import com.muwire.core.Event + +class UIFolderCreateEvent extends Event { + String name +} diff --git a/core/src/main/groovy/com/muwire/core/messenger/UIFolderDeleteEvent.groovy b/core/src/main/groovy/com/muwire/core/messenger/UIFolderDeleteEvent.groovy new file mode 100644 index 00000000..b2750aff --- /dev/null +++ b/core/src/main/groovy/com/muwire/core/messenger/UIFolderDeleteEvent.groovy @@ -0,0 +1,7 @@ +package com.muwire.core.messenger + +import com.muwire.core.Event + +class UIFolderDeleteEvent extends Event { + String name +} diff --git a/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy b/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy index d1fff0f8..e7711ea7 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy @@ -1,4 +1,8 @@ package com.muwire.gui + +import com.muwire.core.messenger.UIFolderCreateEvent +import com.muwire.core.messenger.UIFolderDeleteEvent + import static com.muwire.gui.Translator.trans import griffon.core.GriffonApplication import griffon.core.artifact.GriffonController @@ -863,6 +867,59 @@ class MainFrameController { CopyPasteSupport.copyToClipboard(feed.getPublisher().toBase64()) } + @ControllerAction + void createMessageFolder() { + String name = null + while(name == null) { + name = JOptionPane.showInputDialog(trans("FOLDER_ENTER_NAME")) + if (name == null) + return + name = name.trim() + if (name.length() == 0) { + JOptionPane.showMessageDialog(null, trans("FOLDER_NAME_EMPTY"), + trans("FOLDER_NAME_EMPTY"), JOptionPane.WARNING_MESSAGE) + name = null + continue + } + if (model.messageFoldersMap.containsKey(name)) { + JOptionPane.showMessageDialog(null, trans("FOLDER_ALREADY_EXISTS"), + trans("FOLDER_ALREADY_EXISTS"), JOptionPane.WARNING_MESSAGE) + name = null + continue + } + } + + def params = [:] + params['core'] = core + params['outgoing'] = false + params['name'] = name + def group = application.mvcGroupManager.createMVCGroup('message-folder', 'folder-$name', params) + view.addUserMessageFolder(group) + + UIFolderCreateEvent event = new UIFolderCreateEvent(name: name) + core.eventBus.publish(event) + } + + @ControllerAction + void deleteMessageFolder() { + + def group = model.messageFoldersMap.get(model.folderIdx) + if (group == null) + return + + if (!group.model.messages.isEmpty()) { + int result = JOptionPane.showConfirmDialog(null, trans("FOLDER_CONFIRM_DELETE"), + trans("FOLDER_CONFIRM_DELETE_TITLE"), JOptionPane.YES_NO_OPTION) + if (result != JOptionPane.YES_OPTION) + return + } + + view.deleteUserMessageFolder(model.folderIdx) + + UIFolderDeleteEvent event = new UIFolderDeleteEvent(name: model.folderIdx) + core.eventBus.publish(event) + } + void startChat(Persona p) { if (!mvcGroup.getChildrenGroups().containsKey(p.getHumanReadableName())) { def params = [:] diff --git a/gui/griffon-app/i18n/messages.properties b/gui/griffon-app/i18n/messages.properties index 9a1c79a0..88712c8f 100644 --- a/gui/griffon-app/i18n/messages.properties +++ b/gui/griffon-app/i18n/messages.properties @@ -590,6 +590,14 @@ REPLY=Reply REPLY_ALL=Reply All DOWNLOAD_ALL=Download All COLLECTION=Collection +FOLDERS=Folders +CREATE_FOLDER=New +DELETE_FOLDER=Delete +FOLDER_ENTER_NAME=Please enter a name for the new folder +FOLDER_NAME_EMPTY=A folder name cannot be blank +FOLDER_ALREADY_EXISTS=A folder with that name already exists +FOLDER_CONFIRM_DELETE_TITLE=Folder not empty +FOLDER_CONFIRM_DELETE=This folder is not empty. Are you sure you want to delete it? ## New message window UNREAD=Unread diff --git a/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy b/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy index a5305e4f..8577e853 100644 --- a/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy +++ b/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy @@ -158,6 +158,8 @@ class MainFrameModel { @Observable boolean viewItemCommentButtonEnabled @Observable boolean deleteCollectionButtonEnabled + @Observable boolean deleteMessageFolderButtonEnabled + @Observable boolean searchesPaneButtonEnabled @Observable boolean downloadsPaneButtonEnabled @Observable boolean uploadsPaneButtonEnabled diff --git a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy index 26372ab3..8ce9955c 100644 --- a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy @@ -650,7 +650,16 @@ class MainFrameView { list(id: "message-folders-list", model: model.messageFolderListModel, constraints: gbc(weightx: 100, anchor: GridBagConstraints.LINE_START)) } - panel(border: etchedBorder(), constraints : gbc(gridx:0, gridy:1, fill: GridBagConstraints.BOTH, + panel(border: etchedBorder(), constraints : gbc(gridx: 0, gridy:1, fill: GridBagConstraints.HORIZONTAL, + weightx:0, weighty: 0)) { + gridBagLayout() + label(text : trans("FOLDERS"), constraints : gbc(gridx:0, gridy: 0)) + button(text : trans("CREATE_FOLDER"), constraints : gbc(gridx:0, gridy: 1, weightx: 100, fill:GridBagConstraints.HORIZONTAL), + createMessageFolderAction) + button(text : trans("DELETE_FOLDER"), enabled : bind {model.deleteMessageFolderButtonEnabled}, + constraints : gbc(gridx:0, gridy: 2, weightx: 100, fill: GridBagConstraints.HORIZONTAL), deleteMessageFolderAction) + } + panel(border: etchedBorder(), constraints : gbc(gridx:0, gridy:2, fill: GridBagConstraints.BOTH, weightx: 100, weighty: 100)) { gridLayout(rows: 1, cols: 1) scrollPane() { @@ -1198,16 +1207,36 @@ class MainFrameView { model.folderIdx = model.messageFolders[index].model.name messageFolderContents.getLayout().show(messageFolderContents, model.folderIdx) userMessageFolderList.clearSelection() + model.deleteMessageFolderButtonEnabled = false }) userMessageFolderList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION) userMessageFolderList.addListSelectionListener({ int index = userMessageFolderList.getSelectedIndex() - if (index < 0) + if (index < 0) { + model.deleteMessageFolderButtonEnabled = false return + } model.folderIdx = model.messageFolders[index + Messenger.RESERVED_FOLDERS.size()].model.name messageFolderContents.getLayout().show(messageFolderContents, model.folderIdx) systemMessageFolderList.clearSelection() + model.deleteMessageFolderButtonEnabled = true + }) + + JPopupMenu folderMenu = new JPopupMenu() + JMenuItem deleteItem = new JMenuItem(trans("DELETE_FOLDER")) + deleteItem.addActionListener({controller.deleteMessageFolder()}) + folderMenu.add(deleteItem) + + userMessageFolderList.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger() || e.button == MouseEvent.BUTTON3) + showPopupMenu(folderMenu, e) + } + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger() || e.button == MouseEvent.BUTTON3) + showPopupMenu(folderMenu, e) + } }) // chat tabs @@ -1710,6 +1739,14 @@ class MainFrameView { messageFolderContents.add(group.view.folderPanel, group.model.name) } + + void deleteUserMessageFolder(String name) { + def group = model.messageFoldersMap.remove(name) + if (group == null) + return + model.userMessageFolderListModel.removeElement(name) + messageFolderContents.remove(group.view.folderPanel) + } int getSelectedContactsTableRow() { def table = builder.getVariable("contacts-table")