@@ -24,6 +24,7 @@ define(function (require, exports, module) {
2424 const CommandManager = require ( "command/CommandManager" ) ;
2525 const Commands = require ( "command/Commands" ) ;
2626 const DocumentManager = require ( "document/DocumentManager" ) ;
27+ const LanguageManager = require ( "language/LanguageManager" ) ;
2728 const MainViewManager = require ( "view/MainViewManager" ) ;
2829 const Metrics = require ( "utils/Metrics" ) ;
2930 const Strings = require ( "strings" ) ;
@@ -229,39 +230,89 @@ define(function (require, exports, module) {
229230 // Track cumulative session time in design mode and emit a metric the
230231 // first time the total crosses each of these minute buckets. A
231232 // 5-minute ticker rolls the in-progress stretch into the aggregate;
232- // an exit also flushes so a partial stretch isn't dropped.
233+ // an exit (or a switch away from a markdown file, for the MD stream)
234+ // also flushes so a partial stretch isn't dropped.
233235 const DESIGN_TIME_BUCKETS_MIN = [ 1 , 5 , 10 , 15 , 20 , 30 , 45 , 60 ] ;
234236 const MS_PER_MIN = 60 * 1000 ;
235237 const DESIGN_TIME_TICK_MS = 5 * MS_PER_MIN ;
236- let _designModeTimeFrom = null ;
237- let _aggregateDesignMs = 0 ;
238- let _lastDesignBucketEmittedIdx = - 1 ;
239238
240- function _emitCrossedDesignBuckets ( ) {
241- const minutes = Math . floor ( _aggregateDesignMs / MS_PER_MIN ) ;
239+ function _makeDesignTracker ( metricName ) {
240+ return {
241+ timeFrom : null ,
242+ aggregateMs : 0 ,
243+ lastEmittedIdx : - 1 ,
244+ metricName : metricName
245+ } ;
246+ }
247+
248+ function _emitCrossedBuckets ( tracker ) {
249+ const minutes = Math . floor ( tracker . aggregateMs / MS_PER_MIN ) ;
242250 // A single tick can cross more than one bucket (e.g. 0 → 5 min
243251 // crosses both 1M and 5M), so drain every bucket the aggregate
244252 // has now passed.
245- let checkIndex = _lastDesignBucketEmittedIdx + 1 ;
253+ let checkIndex = tracker . lastEmittedIdx + 1 ;
246254 while ( checkIndex < DESIGN_TIME_BUCKETS_MIN . length &&
247255 minutes >= DESIGN_TIME_BUCKETS_MIN [ checkIndex ] ) {
248- _lastDesignBucketEmittedIdx = checkIndex ;
249- Metrics . countEvent ( Metrics . EVENT_TYPE . UI , "designTime" ,
256+ tracker . lastEmittedIdx = checkIndex ;
257+ Metrics . countEvent ( Metrics . EVENT_TYPE . UI , tracker . metricName ,
250258 DESIGN_TIME_BUCKETS_MIN [ checkIndex ] + "M" ) ;
251259 checkIndex ++ ;
252260 }
253261 }
254262
255- function _onDesignTimeTick ( ) {
256- if ( _designModeTimeFrom == null ) {
263+ function _rollTracker ( tracker ) {
264+ if ( tracker . timeFrom == null ) {
257265 return ;
258266 }
259267 const now = Date . now ( ) ;
260- _aggregateDesignMs += now - _designModeTimeFrom ;
261- _designModeTimeFrom = now ;
262- _emitCrossedDesignBuckets ( ) ;
268+ tracker . aggregateMs += now - tracker . timeFrom ;
269+ tracker . timeFrom = now ;
270+ _emitCrossedBuckets ( tracker ) ;
271+ }
272+
273+ function _flushTracker ( tracker ) {
274+ if ( tracker . timeFrom == null ) {
275+ return ;
276+ }
277+ tracker . aggregateMs += Date . now ( ) - tracker . timeFrom ;
278+ tracker . timeFrom = null ;
279+ _emitCrossedBuckets ( tracker ) ;
263280 }
264- setInterval ( _onDesignTimeTick , DESIGN_TIME_TICK_MS ) ;
281+
282+ // Overall design-mode dwell, plus a sub-stream that only accrues
283+ // while the active file is markdown / GFM.
284+ const _designTracker = _makeDesignTracker ( "designTime" ) ;
285+ const _mdDesignTracker = _makeDesignTracker ( "designTimeMD" ) ;
286+
287+ function _activeFileIsMarkdown ( ) {
288+ const file = MainViewManager . getCurrentlyViewedFile ( MainViewManager . ACTIVE_PANE ) ;
289+ if ( ! file || ! file . fullPath ) {
290+ return false ;
291+ }
292+ const lang = LanguageManager . getLanguageForPath ( file . fullPath ) ;
293+ if ( ! lang ) {
294+ return false ;
295+ }
296+ const id = lang . getId ( ) ;
297+ return id === "markdown" || id === "gfm" ;
298+ }
299+
300+ function _syncMdTrackerToActiveFile ( ) {
301+ // Only ever runs while in design mode — the caller (the
302+ // currentFileChange handler) is a no-op otherwise.
303+ const isMd = _activeFileIsMarkdown ( ) ;
304+ const wasTracking = _mdDesignTracker . timeFrom != null ;
305+ if ( isMd && ! wasTracking ) {
306+ _mdDesignTracker . timeFrom = Date . now ( ) ;
307+ } else if ( ! isMd && wasTracking ) {
308+ _flushTracker ( _mdDesignTracker ) ;
309+ }
310+ }
311+
312+ setInterval ( function ( ) {
313+ _rollTracker ( _designTracker ) ;
314+ _rollTracker ( _mdDesignTracker ) ;
315+ } , DESIGN_TIME_TICK_MS ) ;
265316
266317 function _setEditorCollapsed ( collapsed , opts ) {
267318 const wantCollapsed = ! ! collapsed ;
@@ -285,12 +336,15 @@ define(function (require, exports, module) {
285336 }
286337 editorCollapsed = wantCollapsed ;
287338 if ( editorCollapsed ) {
288- _designModeTimeFrom = Date . now ( ) ;
289- } else if ( _designModeTimeFrom != null ) {
290- // Flush the in-progress stretch into the aggregate so the
339+ _designTracker . timeFrom = Date . now ( ) ;
340+ if ( _activeFileIsMarkdown ( ) ) {
341+ _mdDesignTracker . timeFrom = Date . now ( ) ;
342+ }
343+ } else {
344+ // Flush the in-progress stretch into each aggregate so the
291345 // sliver between the last tick and this exit isn't dropped.
292- _aggregateDesignMs += Date . now ( ) - _designModeTimeFrom ;
293- _designModeTimeFrom = null ;
346+ _flushTracker ( _designTracker ) ;
347+ _flushTracker ( _mdDesignTracker ) ;
294348 }
295349 $ ( "body" ) . toggleClass ( "ccb-editor-collapsed" , editorCollapsed ) ;
296350 const $collapseBtn = $ ( "#ccbCollapseEditorBtn" ) ;
@@ -540,7 +594,15 @@ define(function (require, exports, module) {
540594
541595 _updateSidebarToggleIcon ( ) ;
542596
543- MainViewManager . on ( "currentFileChange.ccb" , _updateFileLabel ) ;
597+ MainViewManager . on ( "currentFileChange.ccb" , function ( ) {
598+ _updateFileLabel ( ) ;
599+ // While in design mode, the MD-only timer should follow the
600+ // active file: start accruing on switch INTO markdown, flush
601+ // on switch OUT.
602+ if ( editorCollapsed ) {
603+ _syncMdTrackerToActiveFile ( ) ;
604+ }
605+ } ) ;
544606 DocumentManager . on ( "dirtyFlagChange.ccb" , _updateFileLabel ) ;
545607 DocumentManager . on ( "pathDeleted.ccb fileNameChange.ccb" , _updateFileLabel ) ;
546608 _updateFileLabel ( ) ;
0 commit comments