From a1f5c9bc603798d0d18d732fc2e346e649e546b4 Mon Sep 17 00:00:00 2001 From: MrLetsplay Date: Sat, 22 Jun 2024 22:30:30 +0200 Subject: [PATCH] Add resource change listener (WIP) --- .../mrletsplay/shareclient/ShareClient.java | 72 ++++++++++++++++++- .../shareclient/util/ShareSession.java | 12 ++++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/mrletsplay/shareclient/ShareClient.java b/src/main/java/me/mrletsplay/shareclient/ShareClient.java index fac263a..f956835 100644 --- a/src/main/java/me/mrletsplay/shareclient/ShareClient.java +++ b/src/main/java/me/mrletsplay/shareclient/ShareClient.java @@ -12,9 +12,12 @@ import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; @@ -37,7 +40,6 @@ import me.mrletsplay.shareclient.util.listeners.ShareClientPageListener; import me.mrletsplay.shareclient.util.listeners.ShareClientPartListener; import me.mrletsplay.shareclient.util.listeners.ShareClientWindowListener; import me.mrletsplay.shareclient.views.ShareView; -import me.mrletsplay.shareclientcore.connection.Change; import me.mrletsplay.shareclientcore.connection.ConnectionException; import me.mrletsplay.shareclientcore.connection.DisconnectListener; import me.mrletsplay.shareclientcore.connection.MessageListener; @@ -92,6 +94,65 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener, Di Arrays.stream(p.getEditorReferences()).forEach(e -> partListener.addDocumentListener(e)); }); }); + + ResourcesPlugin.getWorkspace().addResourceChangeListener(event -> handleChange(event.getDelta()), IResourceChangeEvent.POST_CHANGE); + // TODO: handle PRE_CLOSE events? + } + + private void handleChange(IResourceDelta delta) { + ShareSession session = ShareClient.getDefault().getActiveSession(); + if(session == null) return; + + IResource resource = delta.getResource(); + SharedProject project = session.getSharedProject(resource.getProject()); + if(project != null) { + switch(delta.getKind()) { + case IResourceDelta.ADDED -> { + if(resource instanceof IFile file) { + if(file.isDerived()) return; + + Path filePath = file.getFullPath().toPath(); + ProjectAndPath path = getProjectAndPath(file); + ProjectRelativePath relativePath = new ProjectRelativePath(project.getRemoteName(), path.path()); + SharedDocument document = session.getSharedDocument(relativePath); + if(document != null) { + // Shouldn't be the case + System.err.println("Resource was created but is already shared"); + session.removeSharedDocument(relativePath); // Remove the existing shared document + } + + try { + document = session.createSharedDocument(relativePath, Files.readAllBytes(filePath)); + sendFullSyncOrChecksum(session.getConnection(), AddressableMessage.BROADCAST_SITE_ID, relativePath, filePath, false); + } catch (IOException e) { + e.printStackTrace(); + MessageDialog.openError(null, "Share Client", "Failed to update file: " + e.toString()); + return; + } + } + + System.out.println("ADDED " + delta.getResource() + " | Derived: " + delta.getResource().isDerived()); + } + case IResourceDelta.REMOVED -> { + if(resource instanceof IFile file) { + if(file.isDerived()) return; + + ProjectAndPath path = getProjectAndPath(file); + ProjectRelativePath relativePath = new ProjectRelativePath(project.getRemoteName(), path.path()); + session.removeSharedDocument(relativePath); + + // TODO: send delete message + } + + System.out.println("REMOVED " + delta.getResource() + " | Derived: " + delta.getResource().isDerived()); + } + case IResourceDelta.CHANGED -> /* TODO: check for (external) file changes? */ System.out.println("CHANGED " + delta.getResource() + " | Derived: " + delta.getResource().isDerived()); + } + } + + for(IResourceDelta child : delta.getAffectedChildren()) { + handleChange(child); + } } @Override @@ -289,10 +350,9 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener, Di } if(message instanceof ChangeMessage change) { - Change c = change.change(); ProjectRelativePath path; try { - path = ProjectRelativePath.of(c.documentPath()); + path = ProjectRelativePath.of(change.documentPath()); }catch(IllegalArgumentException e) { return; } @@ -373,6 +433,12 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener, Di return filePath; } + private ProjectAndPath getProjectAndPath(IFile file) { + IProject project = file.getProject(); + Path projectLocation = project.getLocation().toPath(); + return new ProjectAndPath(file.getProject(), projectLocation.relativize(file.getFullPath().toPath()).toString()); + } + private Map getProjectFiles(SharedProject project) { try { Path projectLocation = project.getLocal().getLocation().toPath(); diff --git a/src/main/java/me/mrletsplay/shareclient/util/ShareSession.java b/src/main/java/me/mrletsplay/shareclient/util/ShareSession.java index fc0bcb1..74b0bbe 100644 --- a/src/main/java/me/mrletsplay/shareclient/util/ShareSession.java +++ b/src/main/java/me/mrletsplay/shareclient/util/ShareSession.java @@ -81,6 +81,18 @@ public class ShareSession { return sharedDocuments.get(path); } + public SharedDocument createSharedDocument(ProjectRelativePath path, byte[] initialContents) { + if(sharedDocuments.containsKey(path)) return null; + + SharedDocument document = new SharedDocument(connection, path.toString()); + sharedDocuments.put(path, document); + return document; + } + + public void removeSharedDocument(ProjectRelativePath path) { + sharedDocuments.remove(path); + } + public SharedDocument getOrCreateSharedDocument(ProjectRelativePath path, Supplier initialContents) { return sharedDocuments.computeIfAbsent(path, p -> { SharedDocument doc = new SharedDocument(connection, path.toString(), initialContents == null ? null : initialContents.get());