OverviewFilesCommitsIssuesDocsReleasesPeers

godot-keet commits / 676991d

Group bar view selector + room list sort options
Group bar: OptionButton to select data view (Groups, Members, Topics, Category, Activity). Each mode recomputes graph clusters with the corresponding MI algo and shows them as group icons. Room list: OptionButton for sort (Default, Name A-Z, Name Z-A). Applied to all three view modes (home, group joined, group discover). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
676991d1b0982240256288f0266ae7112acf7654
by plankatron <fleeky@gmail.com> · 2026-02-23T14:01:10.000Z

Changed files (4) +104 -23

scenes/group_bar.tscn +5 -0
……@@ -23,6 +23,11 @@ custom_minimum_size = Vector2(48, 48)
2323text = "K"
2424tooltip_text = "Home — My Rooms"
2525
26[node name="ViewSelect" type="OptionButton" parent="Margin/VBox"]
27unique_name_in_owner = true
28layout_mode = 2
29tooltip_text = "Group view mode"
30
2631[node name="HSeparator" type="HSeparator" parent="Margin/VBox"]
2732layout_mode = 2
2833theme_override_constants/separation = 6
scenes/room_list.tscn +5 -0
……@@ -19,6 +19,11 @@ size_flags_horizontal = 3
1919text = "Rooms"
2020horizontal_alignment = 1
2121
22[node name="SortBtn" type="OptionButton" parent="VBox/TitleHBox"]
23unique_name_in_owner = true
24layout_mode = 2
25tooltip_text = "Sort rooms"
26
2227[node name="GroupSettingsBtn" type="Button" parent="VBox/TitleHBox"]
2328unique_name_in_owner = true
2429visible = false
scripts/group_bar.gd +50 -20
……@@ -7,6 +7,7 @@ signal group_selected(group_id: String)
77@onready var group_icons: VBoxContainer = %GroupIcons
88@onready var home_btn: Button = %HomeButton
99@onready var add_btn: Button = %AddButton
10@onready var view_select: OptionButton = %ViewSelect
1011
1112var _registries: Array = []
1213var _registry_meta: Dictionary = {} # reg_key -> meta dict
……@@ -18,6 +19,16 @@ var _popup: PopupMenu = null
1819var _popup_reg_key: String = ""
1920var _settings_window: Window = null
2021var _avatar_picker: AvatarPicker = null
22var _current_view: int = 0 # index into VIEW_MODES
23
24## View modes: what drives the cluster icons
25const VIEW_MODES: Array[Dictionary] = [
26 {"label": "Groups", "algo": {}},
27 {"label": "Members", "algo": {"name": "members-only", "features": [{"type": "members", "weight": 1.0}], "threshold": 0.5, "minSize": 2}},
28 {"label": "Topics", "algo": {"name": "topics-only", "features": [{"type": "topics", "weight": 1.0}], "threshold": 0.3, "minSize": 2}},
29 {"label": "Category", "algo": {"name": "category-only", "features": [{"type": "category", "weight": 1.0}], "threshold": 0.1, "minSize": 2}},
30 {"label": "Activity", "algo": {"name": "activity-only", "features": [{"type": "activity", "weight": 1.0}], "threshold": 0.1, "minSize": 2}},
31]
2132
2233const ICON_SIZE := 48
2334const PILL_WIDTH := 4
……@@ -38,13 +49,36 @@ func _ready() -> void:
3849 home_btn.pressed.connect(_on_home_pressed)
3950 add_btn.pressed.connect(_on_add_pressed)
4051
52 # Populate view mode selector
53 for i: int in VIEW_MODES.size():
54 view_select.add_item(VIEW_MODES[i]["label"], i)
55 view_select.selected = 0
56 view_select.item_selected.connect(_on_view_mode_changed)
57
4158 if KeetService.client.is_connected:
4259 _on_connected()
4360
4461
4562func _on_connected() -> void:
4663 KeetService.discovery.list_registries()
47 KeetService.graph_mgr.compute()
64 _recompute_clusters()
65
66
67func _on_view_mode_changed(idx: int) -> void:
68 _current_view = idx
69 _clusters.clear()
70 _rebuild_icons()
71 _recompute_clusters()
72
73
74func _recompute_clusters() -> void:
75 var algo: Dictionary = VIEW_MODES[_current_view]["algo"]
76 if algo.is_empty():
77 # "Groups" mode — no clusters, just registries
78 _clusters.clear()
79 _rebuild_icons()
80 else:
81 KeetService.graph_mgr.compute(true, algo)
4882
4983
5084func _on_home_pressed() -> void:
……@@ -251,25 +285,21 @@ func _rebuild_icons() -> void:
251285 var icon := _create_group_icon(room_id, label, desc, avatar_b64, is_selected)
252286 group_icons.add_child(icon)
253287
254 # Cluster icons (MI-computed groups, skip trivial ones)
255 var registry_rooms: Dictionary = {}
256 for reg: Variant in _registries:
257 if reg is Dictionary:
258 registry_rooms[reg.get("roomId", "")] = true
259
260 for cluster: Variant in _clusters:
261 if not cluster is Dictionary:
262 continue
263 var rooms: Array = cluster.get("rooms", [])
264 if rooms.size() < 2:
265 continue
266 var cluster_id: String = "cluster:%d" % cluster.get("id", 0)
267 var label: String = cluster.get("label", "")
268 if label == "":
269 label = "%d rooms" % rooms.size()
270 var is_selected: bool = cluster_id == _active_group
271 var c_icon := _create_group_icon(cluster_id, label, "Computed cluster", "", is_selected)
272 group_icons.add_child(c_icon)
288 # Cluster icons — only shown when a clustering algo is selected
289 if _current_view > 0:
290 for cluster: Variant in _clusters:
291 if not cluster is Dictionary:
292 continue
293 var rooms: Array = cluster.get("rooms", [])
294 if rooms.size() < 1:
295 continue
296 var cluster_id: String = "cluster:%d" % cluster.get("id", 0)
297 var label: String = cluster.get("label", "")
298 if label == "":
299 label = "%d rooms" % rooms.size()
300 var is_selected: bool = cluster_id == _active_group
301 var c_icon := _create_group_icon(cluster_id, label, VIEW_MODES[_current_view]["label"], "", is_selected)
302 group_icons.add_child(c_icon)
273303
274304
275305func _style_home_button() -> void:
scripts/room_list_panel.gd +44 -3
……@@ -8,6 +8,7 @@ extends PanelContainer
88enum ViewMode { HOME, GROUP_JOINED, GROUP_DISCOVER }
99
1010@onready var title_label: Label = %Title
11@onready var sort_btn: OptionButton = %SortBtn
1112@onready var group_settings_btn: Button = %GroupSettingsBtn
1213@onready var search_field: LineEdit = %SearchField
1314@onready var my_rooms_list: VBoxContainer = %MyRoomsList
……@@ -53,6 +54,10 @@ var _topic_searching: bool = false
5354## Cluster metadata from graph (cluster_id_str -> {label, topics})
5455var _cluster_meta_cache: Dictionary = {}
5556
57## Sort mode
58enum SortMode { DEFAULT, NAME_AZ, NAME_ZA }
59var _sort_mode: SortMode = SortMode.DEFAULT
60
5661## Style constants
5762const COLOR_SELECTED := Color(0.25, 0.35, 0.55)
5863const COLOR_HOVER := Color(0.2, 0.25, 0.35)
……@@ -86,6 +91,13 @@ func _ready() -> void:
8691 group_settings_btn.pressed.connect(_on_group_settings_pressed)
8792 KeetService.discovery.topic_results.connect(_on_topic_results)
8893
94 # Sort button
95 sort_btn.add_item("Default", 0)
96 sort_btn.add_item("Name A-Z", 1)
97 sort_btn.add_item("Name Z-A", 2)
98 sort_btn.selected = 0
99 sort_btn.item_selected.connect(_on_sort_changed)
100
89101 # Make title clickable for discover mode toggle
90102 title_label.mouse_filter = Control.MOUSE_FILTER_STOP
91103 title_label.gui_input.connect(_on_title_gui_input)
……@@ -234,6 +246,35 @@ func _render_group_discover_view() -> void:
234246 _rebuild_current_group_view()
235247
236248
249func _on_sort_changed(idx: int) -> void:
250 match idx:
251 0: _sort_mode = SortMode.DEFAULT
252 1: _sort_mode = SortMode.NAME_AZ
253 2: _sort_mode = SortMode.NAME_ZA
254 match _view_mode:
255 ViewMode.HOME:
256 _refresh_my_rooms()
257 ViewMode.GROUP_JOINED:
258 _build_joined_group_rooms()
259 ViewMode.GROUP_DISCOVER:
260 _build_discover_group_rooms()
261
262
263func _sorted_rooms(rooms: Array) -> Array:
264 if _sort_mode == SortMode.DEFAULT:
265 return rooms
266 var sorted: Array = rooms.duplicate()
267 sorted.sort_custom(func(a: Variant, b: Variant) -> bool:
268 var ta: String = a.get("title", "") if a is Dictionary else ""
269 var tb: String = b.get("title", "") if b is Dictionary else ""
270 if _sort_mode == SortMode.NAME_AZ:
271 return ta.to_lower() < tb.to_lower()
272 else:
273 return ta.to_lower() > tb.to_lower()
274 )
275 return sorted
276
277
237278func _on_title_gui_input(event: InputEvent) -> void:
238279 if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
239280 if _view_mode == ViewMode.GROUP_JOINED:
……@@ -333,7 +374,7 @@ func _build_joined_group_rooms() -> void:
333374
334375 # Show only MY rooms that are also in the group's discovery
335376 var shown: int = 0
336 for room: Variant in _rooms:
377 for room: Variant in _sorted_rooms(_rooms):
337378 if not room is Dictionary:
338379 continue
339380 var rid: String = room.get("roomId", "")
……@@ -395,7 +436,7 @@ func _build_discover_group_rooms() -> void:
395436 group_rooms_list.add_child(empty_label)
396437 return
397438
398 for room: Variant in _group_rooms:
439 for room: Variant in _sorted_rooms(_group_rooms):
399440 if not room is Dictionary:
400441 continue
401442 var title: String = room.get("title", "(untitled)")
……@@ -489,7 +530,7 @@ func _refresh_my_rooms() -> void:
489530 my_rooms_list.add_child(empty_label)
490531 return
491532
492 for room: Variant in _rooms:
533 for room: Variant in _sorted_rooms(_rooms):
493534 if not room is Dictionary:
494535 continue
495536 var title: String = room.get("title", "(untitled)")