diff --git a/src/chatty/TwitchClient.java b/src/chatty/TwitchClient.java index 87694bf66..70e7ffaf5 100644 --- a/src/chatty/TwitchClient.java +++ b/src/chatty/TwitchClient.java @@ -872,6 +872,14 @@ private void sendMessage(String channel, String text, boolean allowCommandMessag } } + /** + * Check if the message should be sent as a reply. + * + * @param channel The channel to send the message to (not null) + * @param text The text to send (not null) + * @return true if the message was handled by this method, false if it + * should be sent normally + */ private boolean sendAsReply(String channel, String text) { boolean restricted = settings.getBoolean("mentionReplyRestricted"); boolean doubleAt = text.startsWith("@@"); @@ -888,7 +896,8 @@ private boolean sendAsReply(String channel, String text) { if (result.action != SelectReplyMessageResult.Action.SEND_NORMALLY) { // Should not send normally, so return true if (result.action == SelectReplyMessageResult.Action.REPLY) { - sendReply(channel, actualMsg, username, result.atMsgId, null); + // If changed to parent msg-id, atMsg will be null + sendReply(channel, actualMsg, username, result.atMsgId, result.atMsg); } return true; } @@ -898,6 +907,15 @@ private boolean sendAsReply(String channel, String text) { return false; } + /** + * Send a reply. + * + * @param channel The channel to send to (not null) + * @param text The text to send (not null) + * @param atUsername The username to address (not null) + * @param atMsgId The msg-id to use as reply thread parent (not null) + * @param atMsg The parent msg text (may be null) + */ private void sendReply(String channel, String text, String atUsername, String atMsgId, String atMsg) { MsgTags tags = MsgTags.create("reply-parent-msg-id", atMsgId); if (c.sendSpamProtectedMessage(channel, text, false, tags)) { @@ -2950,7 +2968,7 @@ public void onChannelMessage(User user, String text, boolean action, MsgTags tag } else { g.printMessage(user, text, action, tags); - if (tags.isReply() && tags.hasReplyUserMsg()) { + if (tags.isReply() && tags.hasReplyUserMsg() && tags.hasId()) { ReplyManager.addReply(tags.getReplyParentMsgId(), tags.getId(), String.format("<%s> %s", user.getName(), text), tags.getReplyUserMsg()); } if (!action) { diff --git a/src/chatty/TwitchConnection.java b/src/chatty/TwitchConnection.java index 33e3036b0..b91f2bc1c 100644 --- a/src/chatty/TwitchConnection.java +++ b/src/chatty/TwitchConnection.java @@ -1408,7 +1408,7 @@ public void onChannelCommand(MsgTags tags, String nick, if (tags.containsKey("followers-only")) { channelStates.setFollowersOnly(channel, tags.get("followers-only")); } - if (!tags.isEmpty("room-id")) { + if (tags.hasValue("room-id")) { listener.onRoomId(channel, tags.get("room-id")); if (Helper.isRegularChannel(channel)) { // Set id for room (this should not run too often to diff --git a/src/chatty/gui/components/SelectReplyMessage.java b/src/chatty/gui/components/SelectReplyMessage.java index 9d1788a79..e82400630 100644 --- a/src/chatty/gui/components/SelectReplyMessage.java +++ b/src/chatty/gui/components/SelectReplyMessage.java @@ -163,11 +163,14 @@ else if (action == Action.CTRL_ENTER) { private void confirm() { User.TextMessage selected = list.getSelectedValue(); if (selected != null) { - result = new SelectReplyMessageResult(selected.id); + result = new SelectReplyMessageResult(selected.id, selected.text); if (continueThread.isSelected()) { String parentMsgId = ReplyManager.getParentMsgId(selected.id); if (parentMsgId != null) { - result = new SelectReplyMessageResult(parentMsgId); + // Overwrite result with parent msg-id if available + // Msg should be null for this, since the selected.text + // isn't the parent text + result = new SelectReplyMessageResult(parentMsgId, null); } } } @@ -177,9 +180,10 @@ private void confirm() { public SelectReplyMessageResult select() { if (list.getModel().getSize() == 0) { // No messages available, so immediatelly return - return null; + return SEND_NORMALLY_RESULT; } list.setSelectedIndex(list.getModel().getSize() - 1); + list.ensureIndexIsVisible(list.getSelectedIndex()); setLocationRelativeTo(getParent()); setVisible(true); return result; @@ -194,15 +198,18 @@ public enum Action { } public final String atMsgId; + public final String atMsg; public final Action action; - public SelectReplyMessageResult(String atMsgId) { + public SelectReplyMessageResult(String atMsgId, String atMsg) { this.atMsgId = atMsgId; + this.atMsg = atMsg; this.action = Action.REPLY; } public SelectReplyMessageResult(Action action) { this.atMsgId = null; + this.atMsg = null; this.action = action; } @@ -213,6 +220,9 @@ public static void main(String[] args) { user.addMessage("abc", true, "1"); user.addMessage("abc2", true, "2"); user.addMessage("abc2", true, null); + for (int i=0;i<30;i++) { + user.addMessage("blah"+i, false, i+"msg-id"); + } System.out.println(SelectReplyMessage.show(user)); System.exit(0); } diff --git a/src/chatty/gui/components/help/help-settings.html b/src/chatty/gui/components/help/help-settings.html index d713bec2b..98c4df8b5 100644 --- a/src/chatty/gui/components/help/help-settings.html +++ b/src/chatty/gui/components/help/help-settings.html @@ -1193,6 +1193,10 @@

Channels

  • off - Log no channels whatsoever
  • +

    Tip: Add $_whisper_ to the whitelist or blacklist + to affect all whispers that are output in the "One Window" tab or + "Per User" tabs.

    +

    Other Settings

    Folder
    diff --git a/src/chatty/gui/components/help/help.html b/src/chatty/gui/components/help/help.html index 9b75c706e..dfeb28549 100644 --- a/src/chatty/gui/components/help/help.html +++ b/src/chatty/gui/components/help/help.html @@ -5,7 +5,7 @@ -

    Chatty (Version: 0.13-b2)

    +

    Chatty (Version: 0.13-b3)

    diff --git a/src/chatty/gui/components/settings/LogSettings.java b/src/chatty/gui/components/settings/LogSettings.java index df13a51a6..ea7d61bac 100644 --- a/src/chatty/gui/components/settings/LogSettings.java +++ b/src/chatty/gui/components/settings/LogSettings.java @@ -321,7 +321,8 @@ private static class ChannelFormatter implements DataFormatter { */ @Override public String format(String input) { - if (input != null && !input.isEmpty() && !input.startsWith("#")) { + if (input != null && !input.isEmpty() && !input.startsWith("#") + && !input.startsWith("$")) { input = "#"+input; } if (input.length() == 1) { diff --git a/src/chatty/gui/components/textpane/FixSelection.java b/src/chatty/gui/components/textpane/FixSelection.java index 8239c6617..3da5f46e3 100644 --- a/src/chatty/gui/components/textpane/FixSelection.java +++ b/src/chatty/gui/components/textpane/FixSelection.java @@ -6,9 +6,7 @@ import javax.swing.text.JTextComponent; /** - * Move the dot/mark (selection or not) when text is added/removed, so it stays - * on the same content. - * + * * @author tduva */ public class FixSelection implements DocumentListener { @@ -38,27 +36,16 @@ public void changedUpdate(DocumentEvent e) { } private void fix(DocumentEvent e) { - int dot = c.getCaret().getDot(); - int mark = c.getCaret().getMark(); - - int change = 0; - if (e.getType() == DocumentEvent.EventType.INSERT) { - change = e.getLength(); - } - else if (e.getType() == DocumentEvent.EventType.REMOVE) { - change = -e.getLength(); - } - - // Check separately, something may be changed within the selection - if (dot > e.getOffset()) { - dot = dot + change; - } - if (mark > e.getOffset()) { - mark = mark + change; - } - c.getCaret().setDot(mark); - if (mark != dot) { - c.getCaret().moveDot(dot); + int start = c.getSelectionStart(); + int end = c.getSelectionEnd(); + if (start != end && start > e.getOffset()) { + if (e.getType() == DocumentEvent.EventType.INSERT) { + c.setSelectionStart(start + e.getLength()); + c.setSelectionEnd(end + e.getLength()); + } else if (e.getType() == DocumentEvent.EventType.REMOVE) { + c.setSelectionStart(start - e.getLength()); + c.setSelectionEnd(end - e.getLength()); + } } } diff --git a/src/chatty/gui/components/textpane/LinkController.java b/src/chatty/gui/components/textpane/LinkController.java index 1fdaef73f..dc25b8a7b 100644 --- a/src/chatty/gui/components/textpane/LinkController.java +++ b/src/chatty/gui/components/textpane/LinkController.java @@ -824,9 +824,14 @@ private static void makeReplacementPopupText(String replacedText, MyPopup p) { private static void makeReplyPopupText(String replyMsgId, MyPopup p) { List replies = ReplyManager.getReplies(replyMsgId); StringBuilder b = new StringBuilder(); - for (Reply reply : replies) { - b.append(StringUtil.addLinebreaks(Helper.htmlspecialchars_encode(reply.userMsg), 70, true)); - b.append("
    "); + if (replies != null) { + for (Reply reply : replies) { + b.append(StringUtil.addLinebreaks(Helper.htmlspecialchars_encode(reply.userMsg), 70, true)); + b.append("
    "); + } + } + else { + b.append("No reply data found (may have expired)."); } p.setText(String.format("%sThread:
    %s
    ", POPUP_HTML_PREFIX, b.toString())); diff --git a/src/chatty/util/ReplyManager.java b/src/chatty/util/ReplyManager.java index 6b938980a..4ac3a57d4 100644 --- a/src/chatty/util/ReplyManager.java +++ b/src/chatty/util/ReplyManager.java @@ -17,7 +17,7 @@ */ public class ReplyManager { - private static final long DELETE_TIME = TimeUnit.HOURS.toMillis(4); + private static final long DELETE_TIME = TimeUnit.HOURS.toMillis(12); // private static final long DELETE_TIME = TimeUnit.MINUTES.toMillis(2); private static final Map> data = new HashMap<>(); diff --git a/src/chatty/util/chatlog/ChatLog.java b/src/chatty/util/chatlog/ChatLog.java index 69935ca54..d53097cdf 100644 --- a/src/chatty/util/chatlog/ChatLog.java +++ b/src/chatty/util/chatlog/ChatLog.java @@ -293,14 +293,24 @@ private boolean isChanEnabled(String channel) { if (mode.equals("off")) { return false; } - if (mode.equals("always")) { + else if (mode.equals("always")) { return true; } - if (mode.equals("blacklist") && !settings.listContains("logBlacklist", channel)) { - return true; + else if (mode.equals("blacklist")) { + if (!settings.listContains("logBlacklist", channel)) { + return true; + } + if (channel.startsWith("$") && !settings.listContains("logBlacklist", "$_whisper_")) { + return true; + } } - if (mode.equals("whitelist") && settings.listContains("logWhitelist", channel)) { - return true; + else if (mode.equals("whitelist")) { + if (settings.listContains("logWhitelist", channel)) { + return true; + } + if (channel.startsWith("$") && settings.listContains("logWhitelist", "$_whisper_")) { + return true; + } } return false; } diff --git a/src/chatty/util/irc/IrcMsgTags.java b/src/chatty/util/irc/IrcMsgTags.java index 01c28db05..e5a59db07 100644 --- a/src/chatty/util/irc/IrcMsgTags.java +++ b/src/chatty/util/irc/IrcMsgTags.java @@ -101,8 +101,9 @@ public boolean isValueOf(String key, String... values) { return false; } - public boolean isEmpty(String key) { - return !tags.containsKey(key) || tags.get(key).isEmpty(); + public boolean hasValue(String key) { + String value = tags.get(key); + return value != null && !value.isEmpty(); } /** diff --git a/src/chatty/util/irc/MsgTags.java b/src/chatty/util/irc/MsgTags.java index 4b2e85775..42cb1d594 100644 --- a/src/chatty/util/irc/MsgTags.java +++ b/src/chatty/util/irc/MsgTags.java @@ -21,6 +21,10 @@ public String getId() { return get("id"); } + public boolean hasId() { + return hasValue("id"); + } + public int getBits() { return getInteger("bits", 0); } @@ -46,7 +50,7 @@ public boolean isFromPubSub() { } public boolean hasReplyUserMsg() { - return containsKey("reply-parent-msg-body") && containsKey("reply-parent-display-name"); + return hasValue("reply-parent-msg-body") && hasValue("reply-parent-display-name"); } public String getReplyUserMsg() { @@ -59,7 +63,7 @@ public String getReplyUserMsg() { } public boolean isReply() { - return containsKey("reply-parent-msg-id"); + return hasValue("reply-parent-msg-id"); } public String getReplyParentMsgId() {