gustav/source/Connection.d

284 lines
6.8 KiB
D

module Connection;
import core.thread;
import gui;
import gdk.Threads : te = threadsEnter, tl = threadsLeave;
import gtk.Box;
import std.stdio;
import libdnet.dclient;
import std.socket;
import gtk.ListBox;
import gtk.Label;
public final class Connection : Thread
{
private GUI gui;
private Box box;
private ListBox channels;
private ListBox users;
private ListBox textArea;
private DClient client;
private Address address;
private string[] auth;
/* TODO: Check if we need to protect */
/* TODO: So far usage is in signal handlers (mutex safved) and within te-tl lock for notifications */
private string currentChannel; /* TODO: Used to track what notificaitons come throug */
private Label currentChannelLabel; /* TODO: Using getChild would be nicer, but yeah, this is for the title */
this(GUI gui, Address address, string[] auth)
{
super(&worker);
this.gui = gui;
this.address = address;
this.auth = auth;
start();
}
private void worker()
{
/* Create a new Label */
currentChannelLabel = new Label("CHANNEL NAME GOES HERE");
/**
* Setup the tab for this connection
*/
te();
box = getChatPane();
gui.notebook.add(box);
//gui.notebook setChildPacking(box, true, true, 0, GtkPackType.START);
// gui.mainWindow.
gui.notebook.setTabLabelText(box, auth[0]~"@"~address.toString());
gui.notebook.showAll();
tl();
/**
* Connects and logs in
*/
client = new DClient(address);
client.auth(auth[0], auth[1]); /* TODO: DO this without auth (the list in the loop, crahses server) */
/* Display all channels */
channelList();
/**
* Notification loop
*
* Awaits notifications and then displays them
*/
while(true)
{
/* Receive a notification */
byte[] notificationData = client.awaitNotification();
writeln(notificationData);
te();
import std.conv;
textArea.add(new Label(to!(string)(notificationData)));
textArea.showAll();
process(notificationData);
//gui.mainWindow.showAll();
tl();
//Thread.sleep(dur!("seconds")(2));
}
}
/**
* Processes an incoming notification
* accordingly
*/
private void process(byte[] data)
{
/* TODO: Implement me */
/* TODO: Check notification type */
ubyte notificationType = data[0];
/* For normal message (to channel or user) */
if(notificationType == 0)
{
/* TODO: Decode using tristanable */
writeln("new message");
}
/* Channel notification (ntype=1) */
else if(notificationType == 1)
{
/* TODO: Decode using tristanable */
/* TODO: Get the username of the user that left */
//writeln("user left/join message");
/* Get the sub-type */
ubyte subType = data[1];
/* If the notification was leave (stype=0) */
if(subType == 0)
{
string username = cast(string)data[2..data.length];
textArea.add(new Label(("<-- "~username~" left the channel")));
textArea.showAll();
}
/* If the notification was join (stype=1) */
else if(subType == 1)
{
string username = cast(string)data[2..data.length];
/* Show joined message */
textArea.add(new Label(("--> "~username~" joined the channel")));
textArea.showAll();
/* Add the joined user to the members list */
users.add(new Label(username));
users.showAll();
}
/* TODO: Unknown */
else
{
}
}
}
private void channelList()
{
te();
channelList_unsafe();
tl();
}
/**
* Lists all channels and displays them
*
* Only to be aclled when locked (i.e. by the event
* loop signal dispatch or when we lock it
* i.e. `channelList`)
*/
private void channelList_unsafe()
{
string[] channelList = client.list();
foreach(string channel; channelList)
{
channels.add(new Label(channel));
channels.showAll();
}
}
private void selectChannel(ListBox s)
{
/* Get the name of the channel selected */
string channelSelected = (cast(Label)(s.getSelectedRow().getChild())).getText();
/* Join the channel */
client.join(channelSelected);
/* Set this as the currently selected channel */
currentChannel = channelSelected;
currentChannelLabel.setText(currentChannel);
// currentChannelLabel.show();
// box.show();
/* Fetch a list of members */
string[] members = client.getMembers(channelSelected);
/* Display the members */
users.removeAll();
foreach(string member; members)
{
users.add(new Label(member));
users.showAll();
}
/* Clear the text area */
textArea.removeAll();
textArea.showAll();
}
/**
* Creates a message box
*
* A message box consists of two labels
* one being the name of the person who sent
* the message and the next being the message
* itself
*/
private Box createMessageBox()
{
return null;
}
private Box getChatPane()
{
/* The main page of the tab */
Box box = new Box(GtkOrientation.HORIZONTAL, 1);
/* The channels box */
Box channelBox = new Box(GtkOrientation.VERTICAL, 1);
/* The channel's list */
channels = new ListBox();
channels.addOnSelectedRowsChanged(&selectChannel);
channelBox.add(new Label("Channels"));
channelBox.add(channels);
/* The user's box */
Box userBox = new Box(GtkOrientation.VERTICAL, 1);
/* The user's list */
users = new ListBox();
userBox.add(new Label("Users"));
userBox.add(users);
/* The text box */
Box textBox = new Box(GtkOrientation.VERTICAL, 1);
textBox.add(currentChannelLabel);
textArea = new ListBox();
textBox.add(textArea);
box.add(channelBox);
box.add(textBox);
box.packEnd(userBox,0,0,0);
textBox.setChildPacking(textArea, true, true, 0, GtkPackType.START);
box.setChildPacking(textBox, true, true, 0, GtkPackType.START);
return box;
}
private int getPageNum()
{
return gui.notebook.pageNum(box);
}
public void shutdown()
{
/* This is called from gui.d */
int pageNum = getPageNum();
if(pageNum == -1)
{
/* TODO: Error handling */
}
else
{
gui.notebook.removePage(pageNum);
gui.notebook.showAll();
}
}
}