@@ -92,6 +92,7 @@ var ChronicleScreen = (function() {
9292 if ( err ) {
9393 Toast . error ( Helpers . t ( 'error_network' ) ) ;
9494 } else {
95+ _injectLocalPost ( text ) ;
9596 Toast . success ( '\u2728 ' + Helpers . t ( 'chronicle_send' ) ) ;
9697 Helpers . $ ( 'chronicle-input' ) . value = '' ;
9798 Helpers . $ ( 'chronicle-char-count' ) . textContent = '0/' + MAX_POST_LENGTH ;
@@ -105,10 +106,45 @@ var ChronicleScreen = (function() {
105106 var feed = Helpers . $ ( 'chronicle-feed' ) ;
106107 if ( ! feed ) return ;
107108
109+ feed . innerHTML = '<p class="empty-state">' + Helpers . t ( 'loading' ) + '</p>' ;
110+
108111 var state = StateEngine . getState ( ) ;
112+ var entries = _collectStateEntries ( state ) ;
113+ var user = VizAccount . getCurrentUser ( ) ;
114+
115+ if ( ! user || typeof VoiceProtocol === 'undefined' || ! VoiceProtocol . loadChronicle ) {
116+ _renderFeedEntries ( _filterByTab ( entries , state ) ) ;
117+ return ;
118+ }
119+
120+ VoiceProtocol . loadChronicle ( user , 20 , function ( err , voiceEntries ) {
121+ if ( ! err && voiceEntries && voiceEntries . length ) {
122+ for ( var i = 0 ; i < voiceEntries . length ; i ++ ) {
123+ var voiceEntry = voiceEntries [ i ] ;
124+ var voiceText = '' ;
125+ if ( voiceEntry . message ) {
126+ if ( voiceEntry . message . type === 'text' ) voiceText = voiceEntry . message . text || '' ;
127+ else if ( voiceEntry . message . type === 'publication' ) voiceText = voiceEntry . message . title || voiceEntry . message . description || '' ;
128+ }
129+ if ( ! voiceText ) continue ;
130+ entries . push ( {
131+ type : 'voice' ,
132+ account : voiceEntry . sender ,
133+ text : voiceText ,
134+ actionType : 'chronicle_post' ,
135+ timestamp : voiceEntry . blockTime || null ,
136+ blockNum : voiceEntry . blockNum || 0
137+ } ) ;
138+ }
139+ }
140+
141+ _renderFeedEntries ( _filterByTab ( _dedupeEntries ( entries ) , state ) ) ;
142+ } ) ;
143+ }
144+
145+ function _collectStateEntries ( state ) {
109146 var entries = [ ] ;
110147
111- // Collect recent game actions as narrative entries
112148 if ( state . recentActions ) {
113149 for ( var i = state . recentActions . length - 1 ; i >= 0 && entries . length < 50 ; i -- ) {
114150 var action = state . recentActions [ i ] ;
@@ -126,7 +162,6 @@ var ChronicleScreen = (function() {
126162 }
127163 }
128164
129- // Collect duel history as narrative entries
130165 if ( state . duels && state . duels . history ) {
131166 for ( var j = state . duels . history . length - 1 ; j >= 0 && entries . length < 50 ; j -- ) {
132167 var duel = state . duels . history [ j ] ;
@@ -144,15 +179,17 @@ var ChronicleScreen = (function() {
144179 }
145180 }
146181
147- // Filter by tab
148- entries = _filterByTab ( entries , state ) ;
182+ return entries ;
183+ }
184+
185+ function _renderFeedEntries ( entries ) {
186+ var feed = Helpers . $ ( 'chronicle-feed' ) ;
187+ if ( ! feed ) return ;
149188
150- // Sort by blockNum descending
151189 entries . sort ( function ( a , b ) {
152190 return ( b . blockNum || 0 ) - ( a . blockNum || 0 ) ;
153191 } ) ;
154192
155- // Render
156193 if ( entries . length === 0 ) {
157194 feed . innerHTML = '<p class="empty-state">' + Helpers . t ( 'chronicle_empty' ) + '</p>' ;
158195 return ;
@@ -164,13 +201,39 @@ var ChronicleScreen = (function() {
164201 }
165202 feed . innerHTML = html ;
166203
167- // Bind bless buttons
168204 var blessBtns = feed . querySelectorAll ( '.bless-button' ) ;
169205 for ( var m = 0 ; m < blessBtns . length ; m ++ ) {
170206 blessBtns [ m ] . addEventListener ( 'click' , _onBless ) ;
171207 }
172208 }
173209
210+ function _dedupeEntries ( entries ) {
211+ var seen = { } ;
212+ var out = [ ] ;
213+ for ( var i = 0 ; i < entries . length ; i ++ ) {
214+ var key = ( entries [ i ] . account || '' ) + '|' + ( entries [ i ] . blockNum || 0 ) + '|' + ( entries [ i ] . actionType || '' ) + '|' + ( entries [ i ] . text || '' ) ;
215+ if ( seen [ key ] ) continue ;
216+ seen [ key ] = true ;
217+ out . push ( entries [ i ] ) ;
218+ }
219+ return out ;
220+ }
221+
222+ function _injectLocalPost ( text ) {
223+ var state = StateEngine . getState ( ) ;
224+ var user = VizAccount . getCurrentUser ( ) ;
225+ if ( ! state || ! user ) return ;
226+ state . recentActions . push ( {
227+ type : 'chronicle_post' ,
228+ sender : user ,
229+ blockNum : ( state . headBlock || 0 ) + 1 ,
230+ timestamp : Date . now ( ) ,
231+ text : text ,
232+ message : { type : 'text' , text : text } ,
233+ events : [ ]
234+ } ) ;
235+ }
236+
174237 function _renderEntry ( entry ) {
175238 var t = Helpers . t ;
176239 var charInfo = StateEngine . getCharacter ( entry . account ) ;
0 commit comments