Add editor listeners
This commit is contained in:
parent
050b09d1aa
commit
9812d9bd2f
@ -97,5 +97,11 @@
|
||||
name="Share Client">
|
||||
</page>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.startup">
|
||||
<startup
|
||||
class="me.mrletsplay.shareclient.ShareClient">
|
||||
</startup>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
||||
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
@ -20,26 +21,38 @@ import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jface.dialogs.MessageDialog;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.ui.IStartup;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import me.mrletsplay.shareclient.util.ChecksumUtil;
|
||||
import me.mrletsplay.shareclient.util.Peer;
|
||||
import me.mrletsplay.shareclient.util.ProjectRelativePath;
|
||||
import me.mrletsplay.shareclient.util.ShareSession;
|
||||
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.MessageListener;
|
||||
import me.mrletsplay.shareclientcore.connection.RemoteConnection;
|
||||
import me.mrletsplay.shareclientcore.connection.WebSocketConnection;
|
||||
import me.mrletsplay.shareclientcore.connection.message.AddressableMessage;
|
||||
import me.mrletsplay.shareclientcore.connection.message.ChangeMessage;
|
||||
import me.mrletsplay.shareclientcore.connection.message.ChecksumMessage;
|
||||
import me.mrletsplay.shareclientcore.connection.message.FullSyncMessage;
|
||||
import me.mrletsplay.shareclientcore.connection.message.Message;
|
||||
import me.mrletsplay.shareclientcore.connection.message.PeerJoinMessage;
|
||||
import me.mrletsplay.shareclientcore.connection.message.PeerLeaveMessage;
|
||||
import me.mrletsplay.shareclientcore.connection.message.RequestFullSyncMessage;
|
||||
import me.mrletsplay.shareclientcore.document.SharedDocument;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class ShareClient extends AbstractUIPlugin implements MessageListener {
|
||||
public class ShareClient extends AbstractUIPlugin implements MessageListener, IStartup {
|
||||
|
||||
// The plug-in ID
|
||||
public static final String PLUGIN_ID = "ShareClient"; //$NON-NLS-1$
|
||||
@ -47,11 +60,15 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener {
|
||||
// The shared instance
|
||||
private static ShareClient plugin;
|
||||
|
||||
private ShareClientPartListener partListener = new ShareClientPartListener();
|
||||
|
||||
private ShareView view;
|
||||
private ShareSession activeSession;
|
||||
|
||||
public ShareClient() {
|
||||
private Map<ProjectRelativePath, SharedDocument> sharedDocuments;
|
||||
|
||||
public ShareClient() {
|
||||
this.sharedDocuments = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -147,6 +164,11 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener {
|
||||
updateView();
|
||||
}
|
||||
|
||||
if(message instanceof PeerLeaveMessage leave) {
|
||||
activeSession.getPeers().removeIf(p -> p.siteID() == leave.peerSiteID());
|
||||
updateView();
|
||||
}
|
||||
|
||||
if (message instanceof FullSyncMessage sync) {
|
||||
// TODO: handle FULL_SYNC
|
||||
ProjectRelativePath path;
|
||||
@ -182,6 +204,8 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener {
|
||||
Files.createFile(filePath);
|
||||
}
|
||||
|
||||
// TODO: update sharedDocuments
|
||||
|
||||
Files.write(filePath, sync.content());
|
||||
project.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||
} catch (IOException | CoreException e) {
|
||||
@ -227,18 +251,50 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener {
|
||||
|
||||
RemoteConnection connection = activeSession.getConnection();
|
||||
for (var en : paths.entrySet()) {
|
||||
if (!Files.isRegularFile(en.getValue()))
|
||||
continue;
|
||||
try {
|
||||
byte[] bytes = Files.readAllBytes(en.getValue());
|
||||
connection.send(new FullSyncMessage(req.siteID(), en.getKey().toString(), bytes));
|
||||
} catch (IOException | ConnectionException e) {
|
||||
e.printStackTrace();
|
||||
MessageDialog.openError(null, "Share Client", "Failed to send file contents: " + e.toString());
|
||||
return;
|
||||
}
|
||||
if(!sendFullSyncOrChecksum(connection, req.siteID(), en.getKey(), en.getValue(), false)) return;
|
||||
}
|
||||
}
|
||||
|
||||
if(message instanceof ChangeMessage change) {
|
||||
Change c = change.change();
|
||||
try {
|
||||
ProjectRelativePath path = ProjectRelativePath.of(c.documentPath());
|
||||
}catch(IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: insert change into document in sharedDocuments
|
||||
}
|
||||
}
|
||||
|
||||
public void addSharedProject(IProject project) {
|
||||
activeSession.getSharedProjects().add(project);
|
||||
|
||||
RemoteConnection connection = activeSession.getConnection();
|
||||
for(Map.Entry<ProjectRelativePath, Path> en : getProjectFiles(project).entrySet()) {
|
||||
// TODO: add new document to sharedDocuments
|
||||
if(!sendFullSyncOrChecksum(connection, AddressableMessage.BROADCAST_SITE_ID, en.getKey(), en.getValue(), false)) return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendFullSyncOrChecksum(RemoteConnection connection, int siteID, ProjectRelativePath relativePath, Path filePath, boolean checksum) {
|
||||
if (!Files.isRegularFile(filePath)) return false;
|
||||
|
||||
try {
|
||||
byte[] bytes = Files.readAllBytes(filePath);
|
||||
|
||||
if(!checksum) {
|
||||
connection.send(new FullSyncMessage(siteID, relativePath.toString(), bytes));
|
||||
}else {
|
||||
connection.send(new ChecksumMessage(siteID, relativePath.toString(), ChecksumUtil.generateSHA256(bytes)));
|
||||
}
|
||||
} catch (IOException | ConnectionException e) {
|
||||
e.printStackTrace();
|
||||
MessageDialog.openError(null, "Share Client", "Failed to send file contents: " + e.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<ProjectRelativePath, Path> getProjectFiles(IProject project) {
|
||||
@ -255,4 +311,20 @@ public class ShareClient extends AbstractUIPlugin implements MessageListener {
|
||||
}
|
||||
}
|
||||
|
||||
public ShareClientPartListener getPartListener() {
|
||||
return partListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void earlyStartup() {
|
||||
PlatformUI.getWorkbench().addWindowListener(ShareClientWindowListener.INSTANCE);
|
||||
Arrays.stream(PlatformUI.getWorkbench().getWorkbenchWindows()).forEach(w -> {
|
||||
w.addPageListener(ShareClientPageListener.INSTANCE);
|
||||
Arrays.stream(w.getPages()).forEach(p -> {
|
||||
p.addPartListener(partListener);
|
||||
Arrays.stream(p.getEditorReferences()).forEach(e -> partListener.addDocumentListener(e));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,9 +35,7 @@ public class ShareProjectHandler extends AbstractHandler {
|
||||
ShareSession session = ShareClient.getDefault().getOrStartSession();
|
||||
if(session == null) return null;
|
||||
|
||||
session.getSharedProjects().add(project);
|
||||
|
||||
// TODO: broadcast FULL_SYNC for newly added project
|
||||
ShareClient.getDefault().addSharedProject(project);
|
||||
|
||||
// IEditorPart editor = window.getActivePage().getActiveEditor();
|
||||
// if(!(editor instanceof ITextEditor)) return null;
|
||||
|
@ -0,0 +1,22 @@
|
||||
package me.mrletsplay.shareclient.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class ChecksumUtil {
|
||||
|
||||
private static final MessageDigest SHA_256;
|
||||
|
||||
static {
|
||||
try {
|
||||
SHA_256 = MessageDigest.getInstance("SHA-256");
|
||||
}catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] generateSHA256(byte[] bytes) {
|
||||
return SHA_256.digest(bytes);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package me.mrletsplay.shareclient.util.listeners;
|
||||
|
||||
import org.eclipse.ui.IPageListener;
|
||||
import org.eclipse.ui.IWorkbenchPage;
|
||||
|
||||
import me.mrletsplay.shareclient.ShareClient;
|
||||
|
||||
public class ShareClientPageListener implements IPageListener {
|
||||
|
||||
public static final ShareClientPageListener INSTANCE = new ShareClientPageListener();
|
||||
|
||||
private ShareClientPageListener() {}
|
||||
|
||||
@Override
|
||||
public void pageOpened(IWorkbenchPage page) {
|
||||
page.addPartListener(ShareClient.getDefault().getPartListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pageClosed(IWorkbenchPage page) {
|
||||
page.removePartListener(ShareClient.getDefault().getPartListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pageActivated(IWorkbenchPage page) {}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package me.mrletsplay.shareclient.util.listeners;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.jface.text.DocumentEvent;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IDocumentListener;
|
||||
import org.eclipse.ui.IEditorInput;
|
||||
import org.eclipse.ui.IEditorPart;
|
||||
import org.eclipse.ui.IPartListener2;
|
||||
import org.eclipse.ui.IWorkbenchPart;
|
||||
import org.eclipse.ui.IWorkbenchPartReference;
|
||||
import org.eclipse.ui.part.FileEditorInput;
|
||||
import org.eclipse.ui.texteditor.ITextEditor;
|
||||
|
||||
import me.mrletsplay.shareclient.util.ProjectRelativePath;
|
||||
|
||||
public class ShareClientPartListener implements IPartListener2 {
|
||||
|
||||
private Map<ProjectRelativePath, IDocumentListener> listeners = new HashMap<>();
|
||||
|
||||
private IDocumentListener createListener(ProjectRelativePath path) {
|
||||
if(listeners.containsKey(path)) return listeners.get(path);
|
||||
|
||||
IDocumentListener listener = new IDocumentListener() {
|
||||
|
||||
private boolean ignoreChanges = false;
|
||||
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent event) {
|
||||
System.out.println("Change in document at " + path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void documentAboutToBeChanged(DocumentEvent event) {
|
||||
|
||||
}
|
||||
};
|
||||
listeners.put(path, listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
public void addDocumentListener(IWorkbenchPartReference partRef) {
|
||||
IWorkbenchPart part = partRef.getPart(false);
|
||||
if(!(part instanceof IEditorPart)) return;
|
||||
IEditorPart editor = (IEditorPart) part;
|
||||
if(!(editor instanceof ITextEditor)) return;
|
||||
ITextEditor textEditor = (ITextEditor) editor;
|
||||
IEditorInput editorInput = editor.getEditorInput();
|
||||
if(!(editorInput instanceof FileEditorInput)) return;
|
||||
FileEditorInput fileEditorInput = (FileEditorInput) editorInput;
|
||||
IDocument document = textEditor.getDocumentProvider().getDocument(editorInput);
|
||||
|
||||
IFile file = fileEditorInput.getFile();
|
||||
IProject project = file.getProject();
|
||||
|
||||
Path filePath = project.getLocation().toPath().relativize(file.getLocation().toPath());
|
||||
ProjectRelativePath relPath = new ProjectRelativePath(project.getName(), filePath.toString());
|
||||
System.out.println(relPath);
|
||||
document.addDocumentListener(createListener(relPath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partOpened(IWorkbenchPartReference partRef) {
|
||||
addDocumentListener(partRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partInputChanged(IWorkbenchPartReference partRef) {
|
||||
addDocumentListener(partRef);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package me.mrletsplay.shareclient.util.listeners;
|
||||
|
||||
import org.eclipse.ui.IWindowListener;
|
||||
import org.eclipse.ui.IWorkbenchWindow;
|
||||
|
||||
public class ShareClientWindowListener implements IWindowListener {
|
||||
|
||||
public static final ShareClientWindowListener INSTANCE = new ShareClientWindowListener();
|
||||
|
||||
private ShareClientWindowListener() {}
|
||||
|
||||
@Override
|
||||
public void windowOpened(IWorkbenchWindow window) {
|
||||
window.addPageListener(ShareClientPageListener.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(IWorkbenchWindow window) {
|
||||
window.removePageListener(ShareClientPageListener.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowActivated(IWorkbenchWindow window) {}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated(IWorkbenchWindow window) {}
|
||||
|
||||
}
|
@ -5,7 +5,6 @@ import java.util.Arrays;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.jface.action.Action;
|
||||
import org.eclipse.jface.action.IToolBarManager;
|
||||
import org.eclipse.jface.dialogs.InputDialog;
|
||||
@ -105,8 +104,6 @@ public class ShareView extends ViewPart {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
showMessage(Arrays.stream(ResourcesPlugin.getWorkspace().getRoot().getProjects()).map(p -> p.getName() + ": " + p.getLocation().toString()).toList().toString());
|
||||
|
||||
InputDialog input = new InputDialog(viewer.getControl().getShell(), "Join session", "Enter session id", "EEE", null);
|
||||
input.setBlockOnOpen(true);
|
||||
if(input.open() != InputDialog.OK) return;
|
||||
|
Loading…
Reference in New Issue
Block a user