diff --git a/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy b/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy index cbf9ed30..a77e3865 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy @@ -1,6 +1,7 @@ package com.muwire.gui import com.muwire.core.chat.LocalChatLink +import com.muwire.core.profile.MWProfileHeader import static com.muwire.gui.Translator.trans @@ -194,6 +195,7 @@ class ChatRoomController { case ChatAction.JOIN : processJoin(e.timestamp, e.sender); break case ChatAction.JOINED : processJoined(command.payload); break case ChatAction.LEAVE : processLeave(e.timestamp, e.sender); break + case ChatAction.PROFILE : processProfile(command.payload); break; } } @@ -209,7 +211,7 @@ class ChatRoomController { private void processJoin(long timestamp, Persona p) { String toDisplay = DataHelper.formatTime(timestamp) + " " + trans("JOINED_ROOM", p.getHumanReadableName()) + "\n" runInsideUIAsync { - model.members.add(p) + model.members.add(model.buildChatPOP(p)) view.appendGray(toDisplay) trimLines() view.membersTable?.model?.fireTableDataChanged() @@ -220,7 +222,7 @@ class ChatRoomController { runInsideUIAsync { list.split(",").each { Persona p = new Persona(new ByteArrayInputStream(Base64.decode(it))) - model.members.add(p) + model.members.add(model.buildChatPOP(p)) } view.membersTable?.model?.fireTableDataChanged() } @@ -229,17 +231,27 @@ class ChatRoomController { private void processLeave(long timestamp, Persona p) { String toDisplay = DataHelper.formatTime(timestamp) + " " + trans("LEFT_ROOM",p.getHumanReadableName()) + "\n" runInsideUIAsync { - model.members.remove(p) + model.members.remove(model.buildChatPOP(p)) view.appendGray(toDisplay) trimLines() view.membersTable?.model?.fireTableDataChanged() } } + private processProfile(String payload) { + byte[] decoded = Base64.decode(payload) + MWProfileHeader header = new MWProfileHeader(new ByteArrayInputStream(decoded)) + runInsideUIAsync { + model.profileHeaders.put(header.getPersona(), header) + view.membersTable?.model?.fireTableDataChanged() + } + } + void handleLeave(Persona p) { String toDisplay = DataHelper.formatTime(System.currentTimeMillis()) + " " + trans("USER_DISCONNECTED",p.getHumanReadableName()) + "\n" runInsideUIAsync { - if (model.members.remove(p)) { + if (model.members.remove(model.buildChatPOP(p))) { + model.profileHeaders.remove(p) view.appendGray(toDisplay) trimLines() view.membersTable?.model?.fireTableDataChanged() diff --git a/gui/griffon-app/models/com/muwire/gui/ChatRoomModel.groovy b/gui/griffon-app/models/com/muwire/gui/ChatRoomModel.groovy index bc8a722d..4fad24b9 100644 --- a/gui/griffon-app/models/com/muwire/gui/ChatRoomModel.groovy +++ b/gui/griffon-app/models/com/muwire/gui/ChatRoomModel.groovy @@ -2,11 +2,15 @@ package com.muwire.gui import com.muwire.core.Core import com.muwire.core.Persona - +import com.muwire.core.profile.MWProfileHeader +import com.muwire.gui.profile.PersonaOrProfile +import com.muwire.gui.profile.ThumbnailIcon import griffon.core.artifact.GriffonModel import griffon.transform.Observable import griffon.metadata.ArtifactProviderFor +import javax.swing.Icon + @ArtifactProviderFor(GriffonModel) class ChatRoomModel { Core core @@ -16,13 +20,61 @@ class ChatRoomModel { boolean console boolean privateChat String roomTabName + Map profileHeaders = new HashMap<>() - def members = [] + List members = [] UISettings settings void mvcGroupInit(Map args) { - members.add(core.me) + members.add(new ChatPOP(core.me)) + if (core.myProfile != null) + profileHeaders.put(core.me, core.myProfile.getHeader()) settings = application.context.get("ui-settings") } + + ChatPOP buildChatPOP(Persona persona) { + new ChatPOP(persona) + } + + class ChatPOP implements PersonaOrProfile { + final Persona persona + Icon icon + + ChatPOP(Persona persona) { + this.persona = persona + } + + public Persona getPersona() { + return persona + } + + public String getTitle() { + MWProfileHeader header = profileHeaders.get(persona) + if (header == null) + return "" + return HTMLSanitizer.sanitize(header.getTitle()) + } + + public Icon getThumbnail() { + MWProfileHeader header = profileHeaders.get(persona) + if (header == null) + return null + if (icon == null) { + icon = new ThumbnailIcon(header.getThumbNail()) + } + return icon + } + + public int hashCode() { + persona.hashCode() + } + + public boolean equals(Object o) { + if (!(o instanceof ChatPOP)) + return false + ChatPOP other = (ChatPOP)o + persona == other.persona + } + } } \ No newline at end of file diff --git a/gui/griffon-app/views/com/muwire/gui/ChatRoomView.groovy b/gui/griffon-app/views/com/muwire/gui/ChatRoomView.groovy index 24514a5e..bcde1d0b 100644 --- a/gui/griffon-app/views/com/muwire/gui/ChatRoomView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/ChatRoomView.groovy @@ -1,5 +1,8 @@ package com.muwire.gui +import com.muwire.gui.profile.PersonaOrProfile +import com.muwire.gui.profile.PersonaOrProfileCellRenderer +import com.muwire.gui.profile.PersonaOrProfileComparator import griffon.core.artifact.GriffonView import static com.muwire.gui.Translator.trans import griffon.inject.MVCMember @@ -77,8 +80,9 @@ class ChatRoomView { scrollPane { membersTable = table(autoCreateRowSorter : true, rowHeight : rowHeight) { tableModel(list : model.members) { - closureColumn(header : trans("NAME"), preferredWidth: 100, type: Persona, read : {it}) - closureColumn(header : trans("TRUST_STATUS"), preferredWidth: 30, type : String, read : {trans(model.core.trustService.getLevel(it.destination).name())}) + closureColumn(header : trans("NAME"), preferredWidth: 100, type: PersonaOrProfile, read : {it}) + closureColumn(header : trans("TRUST_STATUS"), preferredWidth: 30, type : String, + read : {trans(model.core.trustService.getLevel(it.getPersona().destination).name())}) } } } @@ -124,8 +128,8 @@ class ChatRoomView { if (membersTable != null) { - membersTable.setDefaultRenderer(Persona.class, new PersonaCellRenderer()) - membersTable.rowSorter.setComparator(0, new PersonaComparator()) + membersTable.setDefaultRenderer(PersonaOrProfile.class, new PersonaOrProfileCellRenderer()) + membersTable.rowSorter.setComparator(0, new PersonaOrProfileComparator()) membersTable.rowSorter.addRowSorterListener({evt -> lastMembersTableSortEvent = evt}) membersTable.rowSorter.setSortsOnUpdates(true) membersTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION)