@@ -92,7 +92,7 @@ var onMessagesModified = function(type,msg) {
9292 }
9393 if ( msg && msg . id == "nav" && msg . t == "modify" && active != "map" )
9494 return ; // don't show an updated nav message if we're just in the menu
95- showMessageRouter ( msg , persist , "dependsOnActive" ) ;
95+ showMessageOverview ( msg && msg . id , false ) ;
9696} ;
9797Bangle . on ( "message" , onMessagesModified ) ;
9898
@@ -121,13 +121,13 @@ function showMessageRouter(msg, persist, explicitDestnation) {
121121 return showMessageOverview ( msg . id ) ;
122122 }
123123 if ( "scroller" === explicitDestnation ) {
124- return showMessageScroller ( msg ) ;
124+ return showMessagesScroller ( msg ) ;
125125 }
126126 if ( "overview" === explicitDestnation ) {
127127 return showMessageOverview ( msg . id ) ;
128128 }
129129 if ( "dependsOnActive" === explicitDestnation ) {
130- if ( "scroller" === active ) { return ; }
130+ if ( "scroller" === active ) { return showMessagesScroller ( msg ) ; } // reinit scroller with updated messages list.
131131 if ( "list" === active ) { return returnToMain ( ) ; }
132132 if ( "settings" === active || "overview" === active ) { return ; }
133133 }
@@ -281,32 +281,126 @@ function showMusicMessage(msg) {
281281 } , 400 ) ;
282282}
283283
284- function showMessageScroller ( msg ) {
285- cancelReloadTimeout ( ) ;
284+ function showMessagesScroller ( msg ) {
285+ const MSG_IDX = msg ? MESSAGES . findIndex ( ( m ) => m . id == msg . id ) : undefined ;
286+
287+ if ( replying ) { return ; }
286288 active = "scroller" ;
289+
290+ const WU = 1 !== process . env . HWVERSION ? require ( "widget_utils" ) : undefined ;
291+ WU && WU . hide ( ) ;
292+ const APP_RECT = Bangle . appRect ;
293+
287294 var bodyFont = fontBig ;
288295 g . setFont ( bodyFont ) ;
289- var lines = [ ] ;
290- if ( msg . title ) lines = g . wrapString ( msg . title , g . getWidth ( ) - 10 ) ;
291- var titleCnt = lines . length ;
292- if ( titleCnt ) lines . push ( "" ) ; // add blank line after title
293- lines = lines . concat ( g . wrapString ( msg . body , g . getWidth ( ) - 10 ) , [ "" , /*LANG*/ "< Back" ] ) ;
296+ const FONT_HEIGHT = g . getFontHeight ( ) ;
297+ let initScroll ;
298+ var titleLines = [ ] ;
299+ let allLines = [ ] ;
300+ let firstTitleLinePerMsg = [ ] ;
301+ for ( let i = 0 ; i < MESSAGES . length ; i ++ ) {
302+ if ( MSG_IDX === i ) { initScroll = allLines . length * FONT_HEIGHT ; }
303+ let msgIter = MESSAGES [ i ] ;
304+
305+ var lines = [ ] ;
306+ const TITLE_STRING = msgIter . title || msgIter . sender || msgIter . subject || msgIter . src || /*LANG*/ "No Title" ;
307+ lines = g . wrapString ( TITLE_STRING , APP_RECT . w - 10 ) ;
308+ firstTitleLinePerMsg . push ( allLines . length ) ;
309+ for ( let i = 0 ; i < lines . length ; i ++ ) {
310+ titleLines . push ( i + allLines . length ) ;
311+ }
312+ lines = lines . concat ( g . wrapString ( msgIter . body , APP_RECT . w - 10 ) ,
313+ [ "-" . repeat ( 12 ) ] ) ;
314+ allLines = allLines . concat ( lines ) ;
315+ }
316+
317+ if ( allLines . length == 0 ) {
318+ cancelReloadTimeout ( ) ;
319+ returnToClockIfEmpty ( ) ;
320+ }
321+
322+ let shownScrollIdxFirst = allLines . length ;
323+ let shownScrollIdxLast = 0 ;
324+
294325 E . showScroller ( {
295- h : g . getFontHeight ( ) , // height of each menu item in pixels
296- c : lines . length , // number of menu items
326+ scroll : initScroll ,
327+ h : FONT_HEIGHT , // height of each menu item in pixels
328+ c : allLines . length , // number of menu items
297329 // a function to draw a menu item
298- draw : function ( idx , r ) {
299- // FIXME: in 2v13 onwards, clearRect(r) will work fine. There's a bug in 2v12
300- g . setBgColor ( idx < titleCnt ? g . theme . bg2 : g . theme . bg ) .
301- setColor ( idx < titleCnt ? g . theme . fg2 : g . theme . fg ) .
302- clearRect ( r . x , r . y , r . x + r . w , r . y + r . h ) ;
303- g . setFont ( bodyFont ) . setFontAlign ( 0 , - 1 ) . drawString ( lines [ idx ] , r . x + r . w / 2 , r . y ) ;
304- } , select : function ( idx ) {
305- if ( idx >= lines . length - 2 )
306- showMessageOverview ( msg . id , true ) ;
330+ draw : function ( scrollIdx , r ) { "ram" ;
331+ //print(scrollIdx)
332+ g . setBgColor ( titleLines . find ( e => e == scrollIdx ) !== undefined ? g . theme . bg2 : g . theme . bg ) .
333+ setColor ( titleLines . find ( e => e == scrollIdx ) !== undefined ? g . theme . fg2 : g . theme . fg ) .
334+ clearRect ( r ) ;
335+ g . setFont ( bodyFont ) . setFontAlign ( 0 , - 1 ) . drawString ( allLines [ scrollIdx ] , r . x + r . w / 2 , r . y ) ;
336+ if ( scrollIdx < shownScrollIdxFirst ) { shownScrollIdxFirst = scrollIdx ; }
337+ if ( scrollIdx > shownScrollIdxLast ) { shownScrollIdxLast = scrollIdx ; }
307338 } ,
308- back : ( ) => showMessageOverview ( msg . id , true )
339+ select : function ( scrollIdx , touch ) {
340+ for ( let i = firstTitleLinePerMsg . length - 1 ; i >= 0 ; i -- ) {
341+ if ( scrollIdx >= firstTitleLinePerMsg [ i ] ) {
342+ if ( ! touch || touch . type === 0 ) {
343+ WU && WU . show ( ) ;
344+ delete titleLines , allLines ;
345+ //E.showScroller();
346+ updateReadMessages ( ) ;
347+ setTimeout ( ( ) => showMessageRouter ( MESSAGES [ i ] , true , "overview" ) , 0 ) ;
348+ }
349+ break ;
350+ }
351+ }
352+ }
309353 } ) ;
354+
355+ // If Bangle.js 2 add an external select hw button handler.
356+ if ( 2 === process . env . HWVERSION ) {
357+ setWatch ( ( ) => {
358+ if ( "scroller" !== active ) { return ; }
359+ Bangle . emit ( "drag" , { dy :0 } ) ; // Compatibility with `kineticscroll`, stopping the scroller so it doesn't continue scrolling when the `showMessageOverview` screen is loaded.
360+ // Zero ms timeout as to not move on before the scroller has registered the emitted drag event.
361+ setTimeout ( ( ) => {
362+ if ( ! persist ) { return load ( ) ; }
363+ Bangle . emit ( "touch" , 1 , { x :APP_RECT . x2 / 2 , y :APP_RECT . y2 / 2 , type :0 } ) ;
364+ } , 0 ) ;
365+ } , BTN ) ;
366+ }
367+
368+ function updateReadMessages ( ) {
369+ let shownMsgIdxFirst , shownMsgIdxLast ;
370+ const LINES_PER_SCREEN = APP_RECT . h / FONT_HEIGHT ;
371+ //print(firstTitleLinePerMsg)
372+ //print(shownIdxFirst, shownIdxLast)
373+
374+ for ( let i = 0 ; i < firstTitleLinePerMsg . length - 1 ; i ++ ) {
375+ const FIRST_LINE_OF_MSG = firstTitleLinePerMsg [ i ] ;
376+ const LAST_LINE_OF_MSG = firstTitleLinePerMsg [ i + 1 ] - 1 ?? allLines . length - 1 ;
377+
378+ if (
379+ shownScrollIdxFirst
380+ <= FIRST_LINE_OF_MSG && FIRST_LINE_OF_MSG
381+ < shownScrollIdxFirst + LINES_PER_SCREEN
382+ ) {
383+ shownMsgIdxFirst = i ;
384+ }
385+
386+ if (
387+ shownScrollIdxLast - LINES_PER_SCREEN
388+ < LAST_LINE_OF_MSG && LAST_LINE_OF_MSG
389+ <= shownScrollIdxLast
390+ ) {
391+ shownMsgIdxLast = i ;
392+ //print(i)
393+ }
394+ }
395+
396+ //print(shownIdxFirst, shownIdxLast)
397+ //print(shownMsgIdxFirst, shownMsgIdxLast)
398+ //print(MESSAGES)
399+ for ( let i = shownMsgIdxFirst ; i < shownMsgIdxLast + 1 ; i ++ ) {
400+ MESSAGES [ i ] . new = false ;
401+ }
402+ //print(MESSAGES)
403+ }
310404}
311405
312406function showMessageSettings ( msg ) {
@@ -318,7 +412,7 @@ function showMessageSettings(msg) {
318412 } ;
319413
320414 if ( msg . id != "music" )
321- menu [ /*LANG*/ "View Message" ] = ( ) => showMessageScroller ( msg ) ;
415+ menu [ /*LANG*/ "View Message" ] = ( ) => showMessagesScroller ( msg ) ;
322416
323417 if ( msg . reply && reply ) {
324418 menu [ /*LANG*/ "Reply" ] = ( ) => {
@@ -491,7 +585,7 @@ function showMessageOverview(msgid, persist) {
491585 ] } ,
492586 { type :"txt" , font :bodyFont , label :body , fillx :1 , filly :1 , pad :2 , cb :( ) => {
493587 // allow tapping to show a larger version
494- showMessageScroller ( msg ) ;
588+ showMessagesScroller ( msg ) ;
495589 } } ,
496590 { type :"h" , fillx :1 , c : footer }
497591 ] } , { back :goBack } ) ;
@@ -537,8 +631,8 @@ function checkMessages(options) {
537631 // If we have a new message, show it
538632 if ( ! options . ignoreUnread && newMessages . length ) {
539633 delete newMessages [ 0 ] . show ; // stop us getting stuck here if we're called a second time
540- showMessageOverview ( newMessages [ 0 ] . id , false ) ;
541- // buzz after showMessage , so being busy during layout doesn't affect the buzz pattern
634+ showMessagesScroller ( newMessages [ 0 ] ) ;
635+ // buzz after showMessagesScroller , so being busy during scroller setup doesn't affect the buzz pattern
542636 if ( globalThis . BUZZ_ON_NEW_MESSAGE ) {
543637 // this is set if we entered the messages app by loading `messagegui.new.js`
544638 // ... but only buzz the first time we view a new message
0 commit comments