From 27d93cc4524e8e31d9c404f61d0cbb1624b73899 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Tue, 21 Jul 2026 11:32:34 +0300 Subject: [PATCH] ContactList: extract ContactListGroupsState --- .../jivesoftware/spark/ui/ContactList.java | 51 ++++-------------- .../spark/ui/ContactListGroupsState.java | 52 +++++++++++++++++++ 2 files changed, 61 insertions(+), 42 deletions(-) create mode 100644 core/src/main/java/org/jivesoftware/spark/ui/ContactListGroupsState.java diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ContactList.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactList.java index 270c85db6..67aa8e1e5 100644 --- a/core/src/main/java/org/jivesoftware/spark/ui/ContactList.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactList.java @@ -16,7 +16,6 @@ package org.jivesoftware.spark.ui; import org.jivesoftware.MainWindow; -import org.jivesoftware.Spark; import org.jivesoftware.resource.Default; import org.jivesoftware.resource.Res; import org.jivesoftware.resource.SparkRes; @@ -71,9 +70,6 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; import java.util.*; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; @@ -96,7 +92,9 @@ public class ContactList extends JPanel implements private ContactItem activeItem; private ContactGroup activeGroup; - private ContactGroup unfiledGroup; + private final ContactGroup unfiledGroup; + private final ContactGroup offlineGroup; + private List sharedGroups = new ArrayList<>(); // Create Menus private final JMenuItem addContactMenu; @@ -105,20 +103,15 @@ public class ContactList extends JPanel implements private final JMenuItem chatMenu; private final JMenuItem renameMenu; - private final ContactGroup offlineGroup; private final JCheckBoxMenuItem showHideMenu = new JCheckBoxMenuItem(); private final JCheckBoxMenuItem showOfflineGroupMenu = new JCheckBoxMenuItem(); private final JCheckBoxMenuItem showOfflineUsersMenu = new JCheckBoxMenuItem(); - private List sharedGroups = new ArrayList<>(); - private final CopyOnWriteArrayList contextListeners = new CopyOnWriteArrayList<>(); private final CopyOnWriteArrayList dndListeners = new CopyOnWriteArrayList<>(); private final CopyOnWriteArrayList contactListListeners = new CopyOnWriteArrayList<>(); - private final Properties props; - private final File propertiesFile; - + private final ContactListGroupsState groupsState = new ContactListGroupsState(); private final LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); private ContactItem contactItem; @@ -174,15 +167,6 @@ public class ContactList extends JPanel implements workspace.getCardPanel().add(RETRY_PANEL, _reconnectPanel); add(contactListScrollPane, BorderLayout.CENTER); - // Load Properties file - props = new Properties(); - // Save to a properties file. - propertiesFile = new File(Spark.getSparkUserHome(), "/groups.properties"); - try { - props.load(new FileInputStream(propertiesFile)); - } catch (IOException e) { - // File does not exist. - } // Add ActionListener(s) to menus addPseudoContactGroup(unfiledGroup); addPseudoContactGroup(offlineGroup); @@ -851,12 +835,7 @@ public class ContactList extends JPanel implements } group.addContactGroupListener(this); fireContactGroupAdded(group); - // Check state - String prop = props.getProperty(group.getGroupName()); - if (prop != null) { - boolean isCollapsed = Boolean.parseBoolean(prop); - group.setCollapsed(isCollapsed); - } + group.setCollapsed(groupsState.isGroupCollapsed(group)); } /** @@ -902,9 +881,8 @@ public class ContactList extends JPanel implements newContactGroup.addContactGroupListener(this); fireContactGroupAdded(newContactGroup); // Check state - String prop = props.getProperty(newContactGroup.getGroupName()); - if (prop != null) { - boolean isCollapsed = Boolean.parseBoolean(prop); + boolean isCollapsed = groupsState.isGroupCollapsed(newContactGroup); + if (isCollapsed) { newContactGroup.setCollapsed(isCollapsed); } groupAdded = true; @@ -1957,21 +1935,10 @@ public class ContactList extends JPanel implements } public void saveState() { - if (props == null) { - return; - } - // save collapsed groups - props.clear(); for (ContactGroup contactGroup : getContactGroups()) { - if (contactGroup.isCollapsed()) { - props.put(contactGroup.getGroupName(), "true"); - } - } - try { - props.store(new FileOutputStream(propertiesFile), null); - } catch (IOException e) { - Log.error("Unable to save group properties.", e); + groupsState.setGroupCollapsed(contactGroup, contactGroup.isCollapsed()); } + groupsState.saveState(); } @Override diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ContactListGroupsState.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactListGroupsState.java new file mode 100644 index 000000000..f6a8f7f87 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactListGroupsState.java @@ -0,0 +1,52 @@ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.Spark; +import org.jivesoftware.spark.util.log.Log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +class ContactListGroupsState { + private final Properties props; + private final File propertiesFile; + + ContactListGroupsState() { + props = new Properties(); + propertiesFile = new File(Spark.getSparkUserHome(), "/groups.properties"); + try { + props.load(new FileInputStream(propertiesFile)); + } catch (IOException e) { + // File does not exist. + } + } + + void saveState() { + if (props == null) { + return; + } + // remove from props all false values + props.entrySet().removeIf(entry -> !Boolean.parseBoolean((String) entry.getValue())); + try { + props.store(new FileOutputStream(propertiesFile), null); + } catch (IOException e) { + Log.error("Unable to save group properties.", e); + } + } + + boolean isGroupCollapsed(ContactGroup group) { + // Check state + String prop = props.getProperty(group.getGroupName()); + return Boolean.parseBoolean(prop); + } + + void setGroupCollapsed(ContactGroup contactGroup, boolean collapsed) { + if (!collapsed) { + props.remove(contactGroup.getGroupName()); + } else { + props.put(contactGroup.getGroupName(), "true"); + } + } +}