@@ -8,6 +8,7 @@ var GuildScreen = (function() {
88
99 var t = Helpers . t ;
1010 var _seenGuildNotifications = { } ;
11+ var _listingFetchInProgress = { } ;
1112
1213 function render ( ) {
1314 var container = Helpers . $ ( 'screen-guild' ) ;
@@ -184,6 +185,10 @@ var GuildScreen = (function() {
184185
185186 html += '<button class="btn btn-secondary guild-btn" id="btn-guild-patronage" aria-label="' + t ( 'guild_patronage' ) + '">' ;
186187 html += '\uD83E\uDD1D ' + t ( 'guild_patronage' ) + '</button>' ;
188+
189+ html += '<button class="btn btn-secondary guild-btn" id="btn-guild-listing" aria-label="' + t ( 'guild_listing' ) + '">' ;
190+ html += '\uD83D\uDCE3 ' + t ( 'guild_listing' ) + '</button>' ;
191+ html += '<p class="guild-listing-hint">' + t ( 'guild_listing_hint' ) + '</p>' ;
187192 }
188193
189194 html += '<button class="btn btn-secondary guild-btn" id="btn-guild-treasury" aria-label="' + t ( 'guild_treasury' ) + '">' ;
@@ -211,6 +216,8 @@ var GuildScreen = (function() {
211216 * Render no-guild state: recommended guilds + create button
212217 */
213218 function _renderNoGuild ( container , state , user ) {
219+ // Kick off async hydration of guilds from listings
220+ _hydrateGuildListings ( state ) ;
214221 var html = '' ;
215222 var pendingInvites = _getPendingInvites ( state , user ) ;
216223 html += '<div class="guild-hall" role="region" aria-label="' + t ( 'guild_title' ) + '">' ;
@@ -293,6 +300,59 @@ var GuildScreen = (function() {
293300 return invites ;
294301 }
295302
303+ /**
304+ * Hydrate guilds from listings — fetch creation blocks for unknown guilds.
305+ * Runs asynchronously; re-renders guild screen when new data arrives.
306+ */
307+ function _hydrateGuildListings ( state ) {
308+ var listings = state . guildListings ;
309+ if ( ! listings || listings . length === 0 ) return ;
310+ for ( var i = 0 ; i < listings . length ; i ++ ) {
311+ var entry = listings [ i ] ;
312+ var gid = entry . guild_id ;
313+ var createdBlock = entry . created_block ;
314+ if ( ! gid || ! createdBlock ) continue ;
315+ // Skip if guild already in state and not a placeholder
316+ if ( state . guilds [ gid ] && ! state . guilds [ gid ] . isPlaceholder ) continue ;
317+ // Skip if already fetching
318+ if ( _listingFetchInProgress [ gid ] ) continue ;
319+ _listingFetchInProgress [ gid ] = true ;
320+ ( function ( guildId , block ) {
321+ viz . api . getBlock ( block , function ( err , blockData ) {
322+ delete _listingFetchInProgress [ guildId ] ;
323+ if ( err || ! blockData || ! blockData . transactions ) return ;
324+ // Find guild.create for this guild_id in the block
325+ for ( var ti = 0 ; ti < blockData . transactions . length ; ti ++ ) {
326+ var tx = blockData . transactions [ ti ] ;
327+ if ( ! tx . operations ) continue ;
328+ for ( var oi = 0 ; oi < tx . operations . length ; oi ++ ) {
329+ var op = tx . operations [ oi ] ;
330+ if ( op [ 0 ] !== 'custom' || op [ 1 ] . id !== 'VM' ) continue ;
331+ try {
332+ var parsed = JSON . parse ( op [ 1 ] . json ) ;
333+ if ( parsed . t !== 'guild.create' ) continue ;
334+ if ( parsed . d && parsed . d . id === guildId ) {
335+ var sender = ( op [ 1 ] . required_regular_auths && op [ 1 ] . required_regular_auths [ 0 ] ) || '' ;
336+ var currentState = StateEngine . getState ( ) ;
337+ var guild = GuildSystem . createGuild ( guildId , sender , parsed . d , block ) ;
338+ if ( guild ) {
339+ currentState . guilds [ guildId ] = guild ;
340+ // Re-render if guild screen is active
341+ var container = Helpers . $ ( 'screen-guild' ) ;
342+ if ( container && ! container . getAttribute ( 'aria-hidden' ) ) {
343+ render ( ) ;
344+ }
345+ }
346+ return ;
347+ }
348+ } catch ( e ) { }
349+ }
350+ }
351+ } ) ;
352+ } ) ( gid , createdBlock ) ;
353+ }
354+ }
355+
296356 /**
297357 * Get list of all guilds for display
298358 */
@@ -382,6 +442,23 @@ var GuildScreen = (function() {
382442 } ) ;
383443 }
384444
445+ // Listing (advertise) button
446+ var listingBtn = container . querySelector ( '#btn-guild-listing' ) ;
447+ if ( listingBtn ) {
448+ listingBtn . addEventListener ( 'click' , function ( ) {
449+ listingBtn . disabled = true ;
450+ GuildProtocol . broadcastGuildListing ( guild . id , guild . createdBlock || 0 , function ( err ) {
451+ listingBtn . disabled = false ;
452+ if ( err ) {
453+ Toast . error ( t ( 'error_network' ) ) ;
454+ } else {
455+ Toast . success ( t ( 'guild_listing_sent' ) ) ;
456+ SoundManager . play ( 'tap' ) ;
457+ }
458+ } ) ;
459+ } ) ;
460+ }
461+
385462 var settingsBtn = container . querySelector ( '#btn-guild-settings' ) ;
386463 if ( settingsBtn ) {
387464 settingsBtn . addEventListener ( 'click' , function ( ) {
@@ -766,7 +843,7 @@ var GuildScreen = (function() {
766843 * Called once when the screen module loads.
767844 */
768845 function init ( ) {
769- var events = [ 'guild_created' , 'guild_joined' , 'guild_left' , 'guild_promoted' , 'guild_invite' ] ;
846+ var events = [ 'guild_created' , 'guild_joined' , 'guild_left' , 'guild_promoted' , 'guild_invite' , 'guild_listing' ] ;
770847 for ( var i = 0 ; i < events . length ; i ++ ) {
771848 Helpers . EventBus . on ( events [ i ] , function ( ) {
772849 // Re-render only if guild screen is currently visible
0 commit comments