Avatars in chat, multi-line paste support

dbus-notify
Zlatin Balevsky 2022-06-08 17:10:03 +01:00
parent 9b931dbdb4
commit 27b734bc40
No known key found for this signature in database
GPG Key ID: A72832072D525E41
6 changed files with 121 additions and 21 deletions

View File

@ -38,7 +38,6 @@
|Downloads queue with priorities | N/A | Core, GUI | Medium | |Downloads queue with priorities | N/A | Core, GUI | Medium |
|Remote queuing of uploads | N/A | Core, Network, GUI | Medium | |Remote queuing of uploads | N/A | Core, Network, GUI | Medium |
|Incomplete file handling | 2 | Core, Portable | Low | |Incomplete file handling | 2 | Core, Portable | Low |
|Chat - break up lines on CR/LF | N/A | GUI | Low |
|Chat - enforce # in room names | N/A | GUI | Low | |Chat - enforce # in room names | N/A | GUI | Low |
|Chat - jump from notification window to room | N/A | GUI | Optional | |Chat - jump from notification window to room | N/A | GUI | Optional |
|Chat - emoji support | 113 | GUI | Low | |Chat - emoji support | 113 | GUI | Low |

View File

@ -61,14 +61,7 @@ class ChatRoomController {
long now = System.currentTimeMillis() long now = System.currentTimeMillis()
if (command.action == ChatAction.SAY && command.payload.length() > 0) { if (command.action == ChatAction.SAY && command.payload.length() > 0) {
String header = DataHelper.formatTime(now) + " <" + model.core.me.getHumanReadableName() + ">" view.appendSay(command.payload, model.buildChatPOP(model.core.me), now)
StyledDocument sd = view.roomTextArea.getStyledDocument()
sd.insertString(sd.getEndPosition().getOffset() - 1, header, sd.getStyle("italic"))
sd.insertString(sd.getEndPosition().getOffset() - 1, " ", sd.getStyle("regular"))
sd.insertString(sd.getEndPosition().getOffset() - 1, command.payload, sd.getStyle("regular"))
sd.insertString(sd.getEndPosition().getOffset() - 1, "\n", sd.getStyle("regular"))
trimLines()
} }
if (command.action == ChatAction.JOIN && model.console) { if (command.action == ChatAction.JOIN && model.console) {
@ -208,8 +201,7 @@ class ChatRoomController {
private void processSay(ChatMessageEvent e, String text) { private void processSay(ChatMessageEvent e, String text) {
runInsideUIAsync { runInsideUIAsync {
view.appendSay(text, e.sender, e.timestamp) view.appendSay(text, model.buildChatPOP(e.sender), e.timestamp)
trimLines()
if (!model.console) if (!model.console)
view.chatNotificator.onMessage(mvcGroup.mvcId) view.chatNotificator.onMessage(mvcGroup.mvcId)
} }
@ -266,7 +258,7 @@ class ChatRoomController {
} }
} }
private void trimLines() { void trimLines() {
if (model.settings.maxChatLines < 0) if (model.settings.maxChatLines < 0)
return return
while(view.getLineCount() > model.settings.maxChatLines) while(view.getLineCount() > model.settings.maxChatLines)

View File

@ -1,6 +1,9 @@
package com.muwire.gui package com.muwire.gui
import com.muwire.core.trust.TrustLevel import com.muwire.core.trust.TrustLevel
import com.muwire.gui.chat.ChatEntry
import com.muwire.gui.chat.ChatTextField
import com.muwire.gui.contacts.POPLabel
import com.muwire.gui.profile.PersonaOrProfile import com.muwire.gui.profile.PersonaOrProfile
import com.muwire.gui.profile.PersonaOrProfileCellRenderer import com.muwire.gui.profile.PersonaOrProfileCellRenderer
import com.muwire.gui.profile.PersonaOrProfileComparator import com.muwire.gui.profile.PersonaOrProfileComparator
@ -8,6 +11,11 @@ import griffon.core.GriffonApplication
import griffon.core.artifact.GriffonView import griffon.core.artifact.GriffonView
import javax.inject.Inject import javax.inject.Inject
import javax.swing.BorderFactory
import javax.swing.JLabel
import javax.swing.JScrollPane
import javax.swing.border.Border
import java.text.SimpleDateFormat
import static com.muwire.gui.Translator.trans import static com.muwire.gui.Translator.trans
import griffon.inject.MVCMember import griffon.inject.MVCMember
@ -52,15 +60,21 @@ class ChatRoomView {
def pane def pane
def parent def parent
def sayField ChatTextField sayField
JTextPane roomTextArea JTextPane roomTextArea
def textScrollPane def textScrollPane
def membersTable def membersTable
def lastMembersTableSortEvent def lastMembersTableSortEvent
UISettings settings
private static final SimpleDateFormat SDF = new SimpleDateFormat("dd/MM hh:mm:ss")
void initUI() { void initUI() {
settings = application.context.get("ui-settings")
int rowHeight = application.context.get("row-height") int rowHeight = application.context.get("row-height")
def parentModel = mvcGroup.parentGroup.model def parentModel = mvcGroup.parentGroup.model
sayField = new ChatTextField()
if (model.console || model.privateChat) { if (model.console || model.privateChat) {
pane = builder.panel { pane = builder.panel {
borderLayout() borderLayout()
@ -73,7 +87,9 @@ class ChatRoomView {
panel(constraints : BorderLayout.SOUTH) { panel(constraints : BorderLayout.SOUTH) {
borderLayout() borderLayout()
label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST) label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST)
sayField = textField(enabled : bind {parentModel.sayActionEnabled}, actionPerformed : {controller.say()}, constraints : BorderLayout.CENTER) scrollPane(verticalScrollBarPolicy: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, constraints: BorderLayout.CENTER) {
widget(sayField, enabled: bind { parentModel.sayActionEnabled }, actionPerformed: { controller.say() })
}
} }
} }
} else { } else {
@ -105,7 +121,9 @@ class ChatRoomView {
panel(constraints : BorderLayout.SOUTH) { panel(constraints : BorderLayout.SOUTH) {
borderLayout() borderLayout()
label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST) label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST)
sayField = textField(enabled : bind {parentModel.sayActionEnabled}, actionPerformed : {controller.say()}, constraints : BorderLayout.CENTER) scrollPane(verticalScrollBarPolicy: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, constraints: BorderLayout.CENTER) {
widget(sayField, enabled: bind { parentModel.sayActionEnabled }, actionPerformed: { controller.say() })
}
} }
} }
@ -222,12 +240,26 @@ class ChatRoomView {
doc.insertString(doc.getEndPosition().getOffset() - 1, gray, doc.getStyle("gray")) doc.insertString(doc.getEndPosition().getOffset() - 1, gray, doc.getStyle("gray"))
} }
void appendSay(String text, Persona sender, long timestamp) { void appendSay(String text, PersonaOrProfile sender, long timestamp) {
StyledDocument doc = roomTextArea.getStyledDocument() StyledDocument doc = roomTextArea.getStyledDocument()
String header = DataHelper.formatTime(timestamp) + " <" + sender.getHumanReadableName() + "> " def label = new DateLabel(timestamp)
doc.insertString(doc.getEndPosition().getOffset() - 1, header, doc.getStyle("italic")) def style = doc.addStyle("newStyle", null)
doc.insertString(doc.getEndPosition().getOffset() - 1, text, doc.getStyle("regular")) StyleConstants.setComponent(style, label)
doc.insertString(doc.getEndPosition().getOffset() - 1, " ", style)
Border border = BorderFactory.createEmptyBorder(0, 5, 0, 5)
label = new POPLabel(sender, settings, border, JLabel.TOP)
label.setAlignmentY(0f)
style = doc.addStyle("newStyle", null)
StyleConstants.setComponent(style, label)
doc.insertString(doc.getEndPosition().getOffset() - 1, " ", style)
def textField = new ChatEntry("$text")
style = doc.addStyle("newStyle", null)
StyleConstants.setComponent(style, textField)
doc.insertString(doc.getEndPosition().getOffset() - 1, " ", style)
doc.insertString(doc.getEndPosition().getOffset() - 1, "\n", doc.getStyle("regular")) doc.insertString(doc.getEndPosition().getOffset() - 1, "\n", doc.getStyle("regular"))
controller.trimLines()
} }
int getLineCount() { int getLineCount() {
@ -240,4 +272,12 @@ class ChatRoomView {
Element element = doc.getParagraphElement(0) Element element = doc.getParagraphElement(0)
doc.remove(0, element.getEndOffset()) doc.remove(0, element.getEndOffset())
} }
private static class DateLabel extends JLabel {
DateLabel(long now) {
setAlignmentY(0f)
String text = SDF.format(new Date(now))
setText(text)
}
}
} }

View File

@ -0,0 +1,27 @@
package com.muwire.gui.chat
import javax.swing.JTextArea
import javax.swing.JTextField
class ChatEntry extends JTextArea {
ChatEntry(String text) {
setEditable(false)
setLineWrap(true)
setWrapStyleWord(true)
setColumns(countRows(text))
setText(text)
setAlignmentY(0f)
}
private static int countRows(String text) {
int rv = 0
char newLine = "\n".toCharacter()
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i)
if (c == newLine)
rv++
}
rv
}
}

View File

@ -0,0 +1,34 @@
package com.muwire.gui.chat
import javax.swing.JTextField
import javax.swing.text.AttributeSet
import javax.swing.text.BadLocationException
import javax.swing.text.Document
import javax.swing.text.PlainDocument
class ChatTextField extends JTextField {
ChatTextField() {
setEditable(true)
}
protected Document createDefaultModel() {
return new ChatDocument()
}
private static class ChatDocument extends PlainDocument {
@Override
void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
println "inserting string $str"
getDocumentProperties().put("filterNewlines", false)
super.insertString(offs, str, a)
}
@Override
String getText(int offset, int length) throws BadLocationException {
String rv = super.getText(offset, length)
println "getting string $rv"
return rv
}
}
}

View File

@ -15,11 +15,19 @@ class POPLabel extends JLabel {
private final UISettings settings private final UISettings settings
POPLabel(PersonaOrProfile personaOrProfile, UISettings settings) { POPLabel(PersonaOrProfile personaOrProfile, UISettings settings) {
this(personaOrProfile, settings,
BorderFactory.createEmptyBorder(2, 2, 2, 2),
JLabel.CENTER)
}
POPLabel(PersonaOrProfile personaOrProfile, UISettings settings,
Border border, int verticalAllignment) {
super() super()
setVerticalAlignment(verticalAllignment)
this.personaOrProfile = personaOrProfile this.personaOrProfile = personaOrProfile
this.settings = settings this.settings = settings
Border border = BorderFactory.createEmptyBorder(2, 2, 2, 2) if (border != null)
setBorder(border) setBorder(border)
MWProfileHeader header = personaOrProfile.getHeader() MWProfileHeader header = personaOrProfile.getHeader()