Narrow the desktop contact list
Each contact shows just the date it was last seen, without the client dot and at half the usual nesting; the full time and server move under the phonetic nickname as "Last seen … on …". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,8 @@ import javax.swing.JTree;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.TransferHandler;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.basic.BasicTreeUI;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
@@ -70,6 +72,7 @@ import java.util.regex.Pattern;
|
||||
final class ContactsDialog extends JDialog {
|
||||
|
||||
private static final DateTimeFormatter SEEN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
|
||||
private static final DateTimeFormatter SEEN_DAY = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final Pattern CLIENT_LINK = Pattern.compile("client://[^\\]\\s]+");
|
||||
|
||||
private final ContactStore contacts;
|
||||
@@ -89,6 +92,7 @@ final class ContactsDialog extends JDialog {
|
||||
private final JRadioButton blockedRadio = new JRadioButton("Blocked");
|
||||
private final JRadioButton friendRadio = new JRadioButton("Friend");
|
||||
private final JTextField phoneticField = new JTextField(18);
|
||||
private final JLabel lastSeenLabel = new JLabel(" ");
|
||||
private final JRadioButton bothRadio = new JRadioButton(NicknameDisplay.BOTH.label());
|
||||
private final JRadioButton onlyCustomRadio = new JRadioButton(NicknameDisplay.ONLY_CUSTOM.label());
|
||||
private final JRadioButton onlyNicknameRadio = new JRadioButton(NicknameDisplay.ONLY_NICKNAME.label());
|
||||
@@ -173,6 +177,12 @@ final class ContactsDialog extends JDialog {
|
||||
root.add(neutral);
|
||||
tree.setRootVisible(false);
|
||||
tree.setShowsRootHandles(true);
|
||||
// Half the usual nesting, so long names and their dates fit in the narrow list.
|
||||
if (tree.getUI() instanceof BasicTreeUI) {
|
||||
BasicTreeUI ui = (BasicTreeUI) tree.getUI();
|
||||
ui.setLeftChildIndent(UIScale.scale(4));
|
||||
ui.setRightChildIndent(UIScale.scale(5));
|
||||
}
|
||||
tree.setRowHeight(UIScale.scale(20));
|
||||
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
tree.setCellRenderer(new ContactRenderer());
|
||||
@@ -332,6 +342,8 @@ final class ContactsDialog extends JDialog {
|
||||
c.weightx = 1;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
row.add(phoneticField, c);
|
||||
c.gridy = 4;
|
||||
row.add(lastSeenLabel, c);
|
||||
return row;
|
||||
}
|
||||
|
||||
@@ -426,10 +438,12 @@ final class ContactsDialog extends JDialog {
|
||||
if (c == null) {
|
||||
nicknameField.setText("");
|
||||
phoneticField.setText("");
|
||||
lastSeenLabel.setText(" ");
|
||||
return;
|
||||
}
|
||||
nicknameField.setText(c.nickname);
|
||||
phoneticField.setText(c.phoneticNickname);
|
||||
lastSeenLabel.setText(lastSeen(c));
|
||||
(c.type == ContactType.FRIEND ? friendRadio : c.type == ContactType.BLOCKED ? blockedRadio : neutralRadio)
|
||||
.setSelected(true);
|
||||
(c.nicknameDisplay == NicknameDisplay.ONLY_CUSTOM ? onlyCustomRadio
|
||||
@@ -447,6 +461,12 @@ final class ContactsDialog extends JDialog {
|
||||
}
|
||||
}
|
||||
|
||||
private static String lastSeen(Contact c) {
|
||||
if (c.lastSeen == null) return "Never seen";
|
||||
String where = c.lastSeenServerName.isEmpty() ? c.lastSeenServerAddress : c.lastSeenServerName;
|
||||
return "Last seen " + SEEN.format(c.lastSeen) + (where.isEmpty() ? "" : " on " + where);
|
||||
}
|
||||
|
||||
private static void setDetailsEnabled(Component component, boolean enabled) {
|
||||
component.setEnabled(enabled);
|
||||
if (component instanceof java.awt.Container) {
|
||||
@@ -514,6 +534,10 @@ final class ContactsDialog extends JDialog {
|
||||
// ---- rendering ----
|
||||
|
||||
private static final class ContactRenderer extends DefaultTreeCellRenderer {
|
||||
private final Border margin = getBorder();
|
||||
/** Keeps a group's name clear of its expand arrow, which the tight nesting brings close. */
|
||||
private final Border groupMargin = BorderFactory.createCompoundBorder(margin, new ScaledEmptyBorder(0, 4, 0, 0));
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
|
||||
boolean leaf, int row, boolean hasFocus) {
|
||||
@@ -522,23 +546,18 @@ final class ContactsDialog extends JDialog {
|
||||
if (obj instanceof Contact) {
|
||||
Contact c = (Contact) obj;
|
||||
setText("<html>" + esc(c.nickname) + " <span style='color:" + hex(sel ? getForeground() : Theme.chatSystem())
|
||||
+ "'> " + esc(lastSeen(c)) + "</span></html>");
|
||||
setIcon(Icons.clientIdle());
|
||||
+ "'> " + (c.lastSeen == null ? "Never" : SEEN_DAY.format(c.lastSeen)) + "</span></html>");
|
||||
setFont(Theme.uiFont());
|
||||
setBorder(margin);
|
||||
} else {
|
||||
setText(String.valueOf(obj));
|
||||
setIcon(null);
|
||||
setFont(Theme.uiBold());
|
||||
setBorder(groupMargin);
|
||||
}
|
||||
setIcon(null);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static String lastSeen(Contact c) {
|
||||
if (c.lastSeen == null) return "Never";
|
||||
String where = c.lastSeenServerName.isEmpty() ? c.lastSeenServerAddress : c.lastSeenServerName;
|
||||
return where.isEmpty() ? SEEN.format(c.lastSeen) : SEEN.format(c.lastSeen) + " on " + where;
|
||||
}
|
||||
|
||||
private static String esc(String s) {
|
||||
return s.replace("&", "&").replace("<", "<").replace(">", ">");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user