@@ -107,6 +107,11 @@ const MatrixIndicator = GObject.registerClass(
107107 Gio . AppInfo . launch_default_for_uri ( uri , null ) ;
108108 }
109109
110+ _copyToClipboard ( text ) {
111+ const clipboard = St . Clipboard . get_default ( ) ;
112+ clipboard . set_text ( St . ClipboardType . CLIPBOARD , text ) ;
113+ }
114+
110115 _buildMenu ( rooms = [ ] ) {
111116 this . menu . removeAll ( ) ;
112117 if ( rooms . length === 0 ) {
@@ -133,6 +138,25 @@ const MatrixIndicator = GObject.registerClass(
133138
134139 let labelText = room . unread > 0 ? `<b>(${ room . unread } ) ${ room . name } </b>` : room . name ;
135140 item . label . get_clutter_text ( ) . set_markup ( labelText ) ;
141+ item . label . x_expand = true ;
142+
143+ // Copy ID button
144+ const copyButton = new St . Button ( {
145+ child : new St . Icon ( {
146+ icon_name : 'edit-copy-symbolic' ,
147+ icon_size : 14 ,
148+ } ) ,
149+ style_class : 'matrix-copy-button' ,
150+ can_focus : true ,
151+ } ) ;
152+
153+ copyButton . connect ( 'clicked' , ( ) => {
154+ this . _copyToClipboard ( room . dmPartnerId || room . id ) ;
155+ this . menu . close ( ) ;
156+ return Clutter . EVENT_STOP ;
157+ } ) ;
158+
159+ item . add_child ( copyButton ) ;
136160
137161 item . connect ( 'activate' , ( ) => {
138162 this . _openMatrixClient ( room . id ) ;
@@ -236,17 +260,27 @@ const MatrixIndicator = GObject.registerClass(
236260 // Show room if it has unread messages OR it's a favorite
237261 if ( unread > 0 || hasFavTag ) {
238262 let name = null ;
263+ let dmPartnerId = null ;
264+
239265 const nameEv = roomData . state ?. events ?. find ( e => e . type === 'm.room.name' ) ;
240266 if ( nameEv ?. content ?. name )
241267 name = nameEv . content . name ;
242268
243- if ( ! name && roomData . summary ?. [ 'm.heroes' ] ?. length > 0 ) {
269+ if ( roomData . summary ?. [ 'm.heroes' ] ?. length > 0 ) {
244270 const heroes = roomData . summary [ 'm.heroes' ] ;
245- const heroNames = heroes . map ( ( h ) => {
246- const m = roomData . state ?. events ?. find ( e => e . type === 'm.room.member' && e . state_key === h ) ;
247- return m ?. content ?. displayname || h . split ( ':' ) [ 0 ] . replace ( '@' , '' ) ;
248- } ) ;
249- name = heroNames . join ( ', ' ) ;
271+
272+ // If it's a DM (no explicit room name and usually 1 hero)
273+ if ( ! name && heroes . length === 1 ) {
274+ dmPartnerId = heroes [ 0 ] ;
275+ }
276+
277+ if ( ! name ) {
278+ const heroNames = heroes . map ( ( h ) => {
279+ const m = roomData . state ?. events ?. find ( e => e . type === 'm.room.member' && e . state_key === h ) ;
280+ return m ?. content ?. displayname || h . split ( ':' ) [ 0 ] . replace ( '@' , '' ) ;
281+ } ) ;
282+ name = heroNames . join ( ', ' ) ;
283+ }
250284 }
251285
252286 // Get timestamp from the last event for sorting
@@ -258,6 +292,7 @@ const MatrixIndicator = GObject.registerClass(
258292 roomList . push ( {
259293 name : name || 'Unnamed Room' ,
260294 id : roomId ,
295+ dmPartnerId,
261296 unread,
262297 timestamp,
263298 encrypted : isEncrypted ,
0 commit comments