diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF index 9e50dea..4d3842e 100644 --- a/META-INF/MANIFEST.MF +++ b/META-INF/MANIFEST.MF @@ -4,7 +4,7 @@ Bundle-Name: ShareClient Bundle-SymbolicName: ShareClient;singleton:=true Bundle-Version: 1.0.0 Import-Package: javax.inject;version="[1.0.0,2.0.0)" -Bundle-Activator: me.mrletsplay.shareclient.Activator +Bundle-Activator: me.mrletsplay.shareclient.ShareClient Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.ui.editors;bundle-version="3.17.0", diff --git a/plugin.xml b/plugin.xml index 86b8195..511077b 100644 --- a/plugin.xml +++ b/plugin.xml @@ -6,11 +6,11 @@ point="org.eclipse.ui.commands"> + name="Share Client"> @@ -60,13 +60,13 @@ point="org.eclipse.ui.views"> + name="Share Client"> diff --git a/src/main/java/me/mrletsplay/shareclient/Activator.java b/src/main/java/me/mrletsplay/shareclient/Activator.java deleted file mode 100644 index 5ab4682..0000000 --- a/src/main/java/me/mrletsplay/shareclient/Activator.java +++ /dev/null @@ -1,99 +0,0 @@ -package me.mrletsplay.shareclient; - -import java.net.URI; -import java.util.Random; -import java.util.UUID; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -import me.mrletsplay.shareclientcore.connection.ConnectionException; -import me.mrletsplay.shareclientcore.connection.RemoteConnection; -import me.mrletsplay.shareclientcore.connection.WebSocketConnection; - -/** - * The activator class controls the plug-in life cycle - */ -public class Activator extends AbstractUIPlugin { - - // The plug-in ID - public static final String PLUGIN_ID = "ShareClient"; //$NON-NLS-1$ - - // The shared instance - private static Activator plugin; - - private RemoteConnection activeConnection; - - /** - * The constructor - */ - public Activator() { - } - - @Override - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - - System.out.println("STARTING"); - getPreferenceStore().setDefault(ShareClientPreferences.SERVER_URI, "ws://localhost:5473"); -// new ShareWSClient(URI.create("ws://localhost:5473")).connect(); - } - - @Override - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static Activator getDefault() { - return plugin; - } - - public RemoteConnection openConnection(String sessionID) { - String serverURI = getPreferenceStore().getString(ShareClientPreferences.SERVER_URI); - if(serverURI == null) return null; - - String username = getPreferenceStore().getString(ShareClientPreferences.USERNAME); - if(username == null || username.isBlank()) username = "user" + new Random().nextInt(1000); - - activeConnection = new WebSocketConnection(URI.create(serverURI), username); - try { - activeConnection.connect(sessionID); // TODO: connect to existing session - } catch (ConnectionException e) { - MessageDialog.openInformation( - null, - "Share Client", - "Failed to connect to server: " + e); - activeConnection = null; - return null; - } - - return activeConnection; - } - - public RemoteConnection getOrOpenConnection() { - if(activeConnection == null) { - openConnection(UUID.randomUUID().toString()); - } - - return activeConnection; - } - - public void closeConnection() { - if(activeConnection == null) return; - activeConnection.disconnect(); - activeConnection = null; - } - - public RemoteConnection getActiveConnection() { - return activeConnection; - } - -} diff --git a/src/main/java/me/mrletsplay/shareclient/ShareClient.java b/src/main/java/me/mrletsplay/shareclient/ShareClient.java new file mode 100644 index 0000000..5095a8a --- /dev/null +++ b/src/main/java/me/mrletsplay/shareclient/ShareClient.java @@ -0,0 +1,166 @@ +package me.mrletsplay.shareclient; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.UUID; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +import me.mrletsplay.shareclient.util.Peer; +import me.mrletsplay.shareclient.util.ProjectRelativePath; +import me.mrletsplay.shareclient.views.ShareView; +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.FullSyncMessage; +import me.mrletsplay.shareclientcore.connection.message.Message; +import me.mrletsplay.shareclientcore.connection.message.PeerJoinMessage; + +/** + * The activator class controls the plug-in life cycle + */ +public class ShareClient extends AbstractUIPlugin implements MessageListener { + + // The plug-in ID + public static final String PLUGIN_ID = "ShareClient"; //$NON-NLS-1$ + + // The shared instance + private static ShareClient plugin; + + private RemoteConnection activeConnection; + private ShareView view; + private List peers; + + /** + * The constructor + */ + public ShareClient() { + this.peers = new ArrayList<>(); + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + + getPreferenceStore().setDefault(ShareClientPreferences.SERVER_URI, "ws://localhost:5473"); +// new ShareWSClient(URI.create("ws://localhost:5473")).connect(); + } + + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static ShareClient getDefault() { + return plugin; + } + + private void updateView() { + if(view == null) return; + Display.getDefault().asyncExec(() -> view.getViewer().setInput(peers.stream().map(p -> p.name()).toArray(String[]::new))); + } + + public RemoteConnection openConnection(String sessionID) { + String serverURI = getPreferenceStore().getString(ShareClientPreferences.SERVER_URI); + if(serverURI == null) return null; + + String username = getPreferenceStore().getString(ShareClientPreferences.USERNAME); + if(username == null || username.isBlank()) username = "user" + new Random().nextInt(1000); + + WebSocketConnection connection = new WebSocketConnection(URI.create(serverURI), username); + try { + connection.connect(sessionID); // TODO: connect to existing session + } catch (ConnectionException e) { + MessageDialog.openInformation( + null, + "Share Client", + "Failed to connect to server: " + e); + return null; + } + + connection.addListener(this); + + return activeConnection = connection; + } + + public RemoteConnection getOrOpenConnection() { + if(activeConnection == null) { + openConnection(UUID.randomUUID().toString()); + } + + return activeConnection; + } + + public void closeConnection() { + if(activeConnection == null) return; + activeConnection.disconnect(); + activeConnection = null; + peers.clear(); + updateView(); + } + + public RemoteConnection getActiveConnection() { + return activeConnection; + } + + public void setView(ShareView view) { + this.view = view; + } + + public ShareView getView() { + return view; + } + + @Override + public void onMessage(Message message) { + System.out.println("Got: " + message); + if(message instanceof PeerJoinMessage join) { + peers.add(new Peer(join.peerName(), join.peerSiteID())); + updateView(); + } + + if(message instanceof FullSyncMessage sync) { + // TODO: handle FULL_SYNC + ProjectRelativePath path; + try { + path = ProjectRelativePath.of(sync.documentPath()); + }catch(IllegalArgumentException e) { + return; + } + + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.projectName()); + if(project == null) return; // TODO: create project + + Path filePath = project.getLocation().toPath().resolve(path.relativePath()); + try { + if(!Files.exists(filePath)) { + Files.createDirectories(filePath.getParent()); + Files.createFile(filePath); + } + + Files.write(filePath, sync.content()); + } catch (IOException e) { + // TODO: handle exception + } + } + } + +} diff --git a/src/main/java/me/mrletsplay/shareclient/ShareClientPreferencePage.java b/src/main/java/me/mrletsplay/shareclient/ShareClientPreferencePage.java index b0aa9fa..a565442 100644 --- a/src/main/java/me/mrletsplay/shareclient/ShareClientPreferencePage.java +++ b/src/main/java/me/mrletsplay/shareclient/ShareClientPreferencePage.java @@ -10,7 +10,7 @@ public class ShareClientPreferencePage extends FieldEditorPreferencePage impleme public ShareClientPreferencePage() { // super(GRID); - setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setPreferenceStore(ShareClient.getDefault().getPreferenceStore()); setDescription("Share Client Preferences"); } diff --git a/src/main/java/me/mrletsplay/shareclient/handlers/ShareProjectHandler.java b/src/main/java/me/mrletsplay/shareclient/handlers/ShareProjectHandler.java index 07e41c0..50d55d9 100644 --- a/src/main/java/me/mrletsplay/shareclient/handlers/ShareProjectHandler.java +++ b/src/main/java/me/mrletsplay/shareclient/handlers/ShareProjectHandler.java @@ -11,7 +11,7 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.handlers.HandlerUtil; -import me.mrletsplay.shareclient.Activator; +import me.mrletsplay.shareclient.ShareClient; import me.mrletsplay.shareclientcore.connection.RemoteConnection; public class ShareProjectHandler extends AbstractHandler { @@ -32,7 +32,7 @@ public class ShareProjectHandler extends AbstractHandler { IPath path = project.getLocation(); if(path == null) return null; - RemoteConnection con = Activator.getDefault().getOrOpenConnection(); + RemoteConnection con = ShareClient.getDefault().getOrOpenConnection(); if(con == null) return null; // TODO: handle case when adding project to existing session diff --git a/src/main/java/me/mrletsplay/shareclient/util/Peer.java b/src/main/java/me/mrletsplay/shareclient/util/Peer.java new file mode 100644 index 0000000..aaa5135 --- /dev/null +++ b/src/main/java/me/mrletsplay/shareclient/util/Peer.java @@ -0,0 +1,3 @@ +package me.mrletsplay.shareclient.util; + +public record Peer(String name, int siteID) {} diff --git a/src/main/java/me/mrletsplay/shareclient/views/ShareView.java b/src/main/java/me/mrletsplay/shareclient/views/ShareView.java index adae457..92c2c47 100644 --- a/src/main/java/me/mrletsplay/shareclient/views/ShareView.java +++ b/src/main/java/me/mrletsplay/shareclient/views/ShareView.java @@ -1,16 +1,10 @@ package me.mrletsplay.shareclient.views; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import javax.inject.Inject; -import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IToolBarManager; @@ -26,18 +20,16 @@ import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PartInitException; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.part.ViewPart; -import me.mrletsplay.shareclient.Activator; -import me.mrletsplay.shareclient.util.ProjectRelativePath; +import me.mrletsplay.shareclient.ShareClient; import me.mrletsplay.shareclientcore.connection.ConnectionException; import me.mrletsplay.shareclientcore.connection.RemoteConnection; -import me.mrletsplay.shareclientcore.connection.message.FullSyncMessage; -import me.mrletsplay.shareclientcore.connection.message.PeerJoinMessage; import me.mrletsplay.shareclientcore.connection.message.RequestFullSyncMessage; public class ShareView extends ViewPart { @@ -51,8 +43,6 @@ public class ShareView extends ViewPart { private TableViewer viewer; - private List peerNames = new ArrayList<>(); - class ViewLabelProvider extends LabelProvider implements ITableLabelProvider { @Override public String getColumnText(Object obj, int index) { @@ -68,12 +58,25 @@ public class ShareView extends ViewPart { } } + @Override + public void init(IViewSite site) throws PartInitException { + super.init(site); + System.out.println(ShareClient.getDefault()); + ShareClient.getDefault().setView(this); + } + + @Override + public void dispose() { + super.dispose(); + ShareClient.getDefault().setView(null); + } + @Override public void createPartControl(Composite parent) { viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(ArrayContentProvider.getInstance()); - viewer.setInput(new String[] {}); + viewer.setInput(new String[0]); viewer.setLabelProvider(new ViewLabelProvider()); // Create the help context id for the viewer's control @@ -103,69 +106,34 @@ public class ShareView extends ViewPart { input.setBlockOnOpen(true); if(input.open() != InputDialog.OK) return; - RemoteConnection connection = Activator.getDefault().getActiveConnection(); + RemoteConnection connection = ShareClient.getDefault().getActiveConnection(); if(connection != null) connection.disconnect(); - connection = Activator.getDefault().openConnection(input.getValue()); + connection = ShareClient.getDefault().openConnection(input.getValue()); if(connection == null) return; - connection.addListener(m -> { - System.out.println("Got: " + m); - if(m instanceof PeerJoinMessage join) { - peerNames.add(join.peerName()); - Display.getDefault().asyncExec(() -> viewer.setInput(peerNames.toArray(String[]::new))); - } - - if(m instanceof FullSyncMessage sync) { - // TODO: handle FULL_SYNC - ProjectRelativePath path; - try { - path = ProjectRelativePath.of(sync.documentPath()); - }catch(IllegalArgumentException e) { - return; - } - - IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.projectName()); - if(project == null) return; // TODO: create project - - Path filePath = project.getLocation().toPath().resolve(path.relativePath()); - try { - if(!Files.exists(filePath)) { - Files.createDirectories(filePath.getParent()); - Files.createFile(filePath); - } - - Files.write(filePath, sync.content()); - } catch (IOException e) { - // TODO: handle exception - } - } - }); - try { connection.send(new RequestFullSyncMessage(connection.getSiteID(), null)); updateActionBars(); } catch (ConnectionException e) { - Activator.getDefault().closeConnection(); + ShareClient.getDefault().closeConnection(); showMessage("Failed to send: " + e); } } }; - if(Activator.getDefault().getActiveConnection() == null) toolbars.add(joinSession); + if(ShareClient.getDefault().getActiveConnection() == null) toolbars.add(joinSession); Action leaveSession = new Action("Leave session", ImageDescriptor.createFromFile(ShareView.class, "/icons/stop.png")) { @Override public void run() { - Activator.getDefault().closeConnection(); - peerNames.clear(); - viewer.setInput(peerNames.toArray(String[]::new)); + ShareClient.getDefault().closeConnection(); updateActionBars(); } }; - if(Activator.getDefault().getActiveConnection() != null) toolbars.add(leaveSession); + if(ShareClient.getDefault().getActiveConnection() != null) toolbars.add(leaveSession); Action showSettings = new Action("Settings", ImageDescriptor.createFromFile(ShareView.class, "/icons/cog.png")) { @@ -190,6 +158,10 @@ public class ShareView extends ViewPart { message); } + public TableViewer getViewer() { + return viewer; + } + @Override public void setFocus() { viewer.getControl().setFocus();