1 module Connection; 2 3 import core.thread; 4 import gui; 5 import gdk.Threads : te = threadsEnter, tl = threadsLeave; 6 import gtk.Box; 7 import std.stdio; 8 import libdnet.dclient; 9 import std.socket; 10 import gtk.ListBox; 11 import gtk.Label; 12 13 public final class Connection : Thread 14 { 15 private GUI gui; 16 private Box box; 17 private ListBox channels; 18 private ListBox users; 19 private ListBox textArea; 20 21 private DClient client; 22 private Address address; 23 24 /* TODO: Check if we need to protect */ 25 /* TODO: So far usage is in signal handlers (mutex safved) and within te-tl lock for notifications */ 26 private string currentChannel; 27 28 this(GUI gui, Address address) 29 { 30 super(&worker); 31 this.gui = gui; 32 this.address = address; 33 start(); 34 } 35 36 private void worker() 37 { 38 te(); 39 40 box = getChatPane(); 41 gui.notebook.add(box); 42 43 gui.notebook.setTabLabelText(box, "user@"~address.toString()); 44 45 gui.notebook.showAll(); 46 47 48 49 tl(); 50 writeln("connection gtk unlock"); 51 52 client = new DClient(address); 53 client.auth("bru", "kak"); /* TODO: DO this without auth (the list in the loop, crahses server) */ 54 writeln("br"); 55 56 57 channelList(); 58 59 /** 60 * Notification loop 61 * 62 * Awaits notifications and then displays them 63 */ 64 while(true) 65 { 66 /* Receive a notification */ 67 byte[] notificationData = client.awaitNotification(); 68 writeln(notificationData); 69 70 te(); 71 import std.conv; 72 textArea.add(new Label(to!(string)(notificationData))); 73 textArea.showAll(); 74 75 process(notificationData); 76 //gui.mainWindow.showAll(); 77 78 tl(); 79 80 //Thread.sleep(dur!("seconds")(2)); 81 } 82 } 83 84 85 86 /** 87 * Processes an incoming notification 88 * accordingly 89 */ 90 private void process(byte[] data) 91 { 92 /* TODO: Implement me */ 93 94 /* TODO: Check notification type */ 95 ubyte notificationType = data[0]; 96 97 /* For normal message (to channel or user) */ 98 if(notificationType == 0) 99 { 100 /* TODO: Decode using tristanable */ 101 102 103 writeln("new message"); 104 } 105 /* Channel notification (ntype=1) */ 106 else if(notificationType == 1) 107 { 108 /* TODO: Decode using tristanable */ 109 /* TODO: Get the username of the user that left */ 110 //writeln("user left/join message"); 111 112 /* Get the sub-type */ 113 ubyte subType = data[1]; 114 115 /* If the notification was leave (stype=0) */ 116 if(subType == 0) 117 { 118 string username = cast(string)data[2..data.length]; 119 textArea.add(new Label(("<-- "~username~" left the channel"))); 120 textArea.showAll(); 121 } 122 /* If the notification was join (stype=1) */ 123 else if(subType == 1) 124 { 125 string username = cast(string)data[2..data.length]; 126 127 /* Show joined message */ 128 textArea.add(new Label(("--> "~username~" joined the channel"))); 129 textArea.showAll(); 130 131 /* Add the joined user to the members list */ 132 users.add(new Label(username)); 133 users.showAll(); 134 } 135 /* TODO: Unknown */ 136 else 137 { 138 139 } 140 } 141 } 142 143 144 145 146 147 private void channelList() 148 { 149 te(); 150 channelList_unsafe(); 151 tl(); 152 } 153 154 /** 155 * Lists all channels and displays them 156 * 157 * Only to be aclled when locked (i.e. by the event 158 * loop signal dispatch or when we lock it 159 * i.e. `channelList`) 160 */ 161 private void channelList_unsafe() 162 { 163 string[] channelList = client.list(); 164 165 foreach(string channel; channelList) 166 { 167 channels.add(new Label(channel)); 168 channels.showAll(); 169 } 170 } 171 172 private void selectChannel(ListBox s) 173 { 174 /* Get the name of the channel selected */ 175 string channelSelected = (cast(Label)(s.getSelectedRow().getChild())).getText(); 176 177 /* Join the channel */ 178 client.join(channelSelected); 179 180 /* Set this as the currently selected channel */ 181 currentChannel = channelSelected; 182 183 /* Fetch a list of members */ 184 string[] members = client.getMembers(channelSelected); 185 186 /* Display the members */ 187 users.removeAll(); 188 foreach(string member; members) 189 { 190 users.add(new Label(member)); 191 users.showAll(); 192 } 193 } 194 195 196 /** 197 * Creates a message box 198 * 199 * A message box consists of two labels 200 * one being the name of the person who sent 201 * the message and the next being the message 202 * itself 203 */ 204 private Box createMessageBox() 205 { 206 return null; 207 } 208 209 private Box getChatPane() 210 { 211 /* The main page of the tab */ 212 Box box = new Box(GtkOrientation.HORIZONTAL, 1); 213 214 /* The channels box */ 215 Box channelBox = new Box(GtkOrientation.VERTICAL, 1); 216 217 /* The channel's list */ 218 channels = new ListBox(); 219 channels.addOnSelectedRowsChanged(&selectChannel); 220 221 channelBox.add(new Label("Channels")); 222 channelBox.add(channels); 223 224 /* The user's box */ 225 Box userBox = new Box(GtkOrientation.VERTICAL, 1); 226 227 /* The user's list */ 228 users = new ListBox(); 229 230 userBox.add(new Label("Users")); 231 userBox.add(users); 232 233 234 235 236 textArea = new ListBox(); 237 238 239 box.add(channelBox); 240 box.add(textArea); 241 box.add(userBox); 242 243 244 245 return box; 246 } 247 248 private int getPageNum() 249 { 250 return gui.notebook.pageNum(box); 251 } 252 253 public void shutdown() 254 { 255 /* This is called from gui.d */ 256 int pageNum = getPageNum(); 257 258 if(pageNum == -1) 259 { 260 /* TODO: Error handling */ 261 } 262 else 263 { 264 gui.notebook.removePage(pageNum); 265 gui.notebook.showAll(); 266 } 267 } 268 }