@ -38,6 +38,11 @@ function parseLineCommand(line: LogLine): LogLineCommand | null {
return null ;
}
function isLogElementInViewport ( el : HTMLElement ) : boolean {
const rect = el . getBoundingClientRect ( ) ;
return rect . top >= 0 && rect . bottom <= window . innerHeight ; / / o n l y c h e c k h e i g h t b u t n o t w i d t h
}
const sfc = {
name : 'RepoActionView' ,
components : {
@ -142,9 +147,14 @@ const sfc = {
} ,
methods : {
/ / g e t t h e a c t i v e c o n t a i n e r e l e m e n t , e i t h e r t h e ` j o b - s t e p - l o g s ` o r t h e ` j o b - l o g - l i s t ` i n t h e ` j o b - l o g - g r o u p `
getLogsContainer ( stepIndex : number ) {
const el = this . $refs . logs [ stepIndex ] ;
/ / g e t t h e j o b s t e p l o g s c o n t a i n e r ( ' . j o b - s t e p - l o g s ' )
getJobStepLogsContainer ( stepIndex : number ) : HTMLElement {
return this . $refs . logs [ stepIndex ] ;
} ,
/ / g e t t h e a c t i v e l o g s c o n t a i n e r e l e m e n t , e i t h e r t h e ` j o b - s t e p - l o g s ` o r t h e ` j o b - l o g - l i s t ` i n t h e ` j o b - l o g - g r o u p `
getActiveLogsContainer ( stepIndex : number ) : HTMLElement {
const el = this . getJobStepLogsContainer ( stepIndex ) ;
return el . _stepLogsActiveContainer ? ? el ;
} ,
/ / b e g i n a l o g g r o u p
@ -217,9 +227,15 @@ const sfc = {
) ;
} ,
shouldAutoScroll ( stepIndex : number ) : boolean {
const el = this . getJobStepLogsContainer ( stepIndex ) ;
if ( ! el . lastChild ) return false ;
return isLogElementInViewport ( el . lastChild ) ;
} ,
appendLogs ( stepIndex : number , startTime : number , logLines : LogLine [ ] ) {
for ( const line of logLines ) {
const el = this . getLogsContainer ( stepIndex ) ;
const el = this . getActive LogsContainer ( stepIndex ) ;
const cmd = parseLineCommand ( line ) ;
if ( cmd ? . name === 'group' ) {
this . beginLogGroup ( stepIndex , startTime , line , cmd ) ;
@ -278,6 +294,14 @@ const sfc = {
this . currentJobStepsStates [ i ] = { cursor : null , expanded : false } ;
}
}
/ / f i n d t h e s t e p i n d e x e s t h a t n e e d t o a u t o - s c r o l l
const autoScrollStepIndexes = new Map < number , boolean > ( ) ;
for ( const logs of job . logs . stepsLog ? ? [ ] ) {
if ( autoScrollStepIndexes . has ( logs . step ) ) continue ;
autoScrollStepIndexes . set ( logs . step , this . shouldAutoScroll ( logs . step ) ) ;
}
/ / a p p e n d l o g s t o t h e U I
for ( const logs of job . logs . stepsLog ? ? [ ] ) {
/ / s a v e t h e c u r s o r , i t w i l l b e p a s s e d t o b a c k e n d n e x t t i m e
@ -285,6 +309,15 @@ const sfc = {
this . appendLogs ( logs . step , logs . started , logs . lines ) ;
}
/ / a u t o - s c r o l l t o t h e l a s t l o g l i n e o f t h e l a s t s t e p
let autoScrollJobStepElement : HTMLElement ;
for ( let stepIndex = 0 ; stepIndex < this . currentJob . steps . length ; stepIndex ++ ) {
if ( ! autoScrollStepIndexes . get ( stepIndex ) ) continue ;
autoScrollJobStepElement = this . getJobStepLogsContainer ( stepIndex ) ;
}
autoScrollJobStepElement ? . lastElementChild . scrollIntoView ( { behavior : 'smooth' , block : 'nearest' } ) ;
/ / c l e a r t h e i n t e r v a l t i m e r i f t h e j o b i s d o n e
if ( this . run . done && this . intervalID ) {
clearInterval ( this . intervalID ) ;
this . intervalID = null ;