@ -1,130 +1,137 @@
< script lang = "ts" >
< script lang = "ts" setup >
import DiffFileTreeItem from './DiffFileTreeItem.vue' ;
import DiffFileTreeItem from './DiffFileTreeItem.vue' ;
import { loadMoreFiles } from '../features/repo-diff.ts' ;
import { loadMoreFiles } from '../features/repo-diff.ts' ;
import { toggleElem } from '../utils/dom.ts' ;
import { toggleElem } from '../utils/dom.ts' ;
import { diffTreeStore } from '../modules/stores.ts' ;
import { diffTreeStore } from '../modules/stores.ts' ;
import { setFileFolding } from '../features/file-fold.ts' ;
import { setFileFolding } from '../features/file-fold.ts' ;
import { computed , onMounted , onUnmounted } from 'vue' ;
const LOCAL _STORAGE _KEY = 'diff_file_tree_visible' ;
const LOCAL _STORAGE _KEY = 'diff_file_tree_visible' ;
export default {
const store = diffTreeStore ( ) ;
components : { DiffFileTreeItem } ,
data : ( ) => {
const fileTree = computed ( ( ) => {
return { store : diffTreeStore ( ) } ;
const result = [ ] ;
} ,
for ( const file of store . files ) {
computed : {
/ / S p l i t f i l e i n t o d i r e c t o r i e s
fileTree ( ) {
const splits = file . Name . split ( '/' ) ;
const result = [ ] ;
let index = 0 ;
for ( const file of this . store . files ) {
let parent = null ;
/ / S p l i t f i l e i n t o d i r e c t o r i e s
let isFile = false ;
const splits = file . Name . split ( '/' ) ;
for ( const split of splits ) {
let index = 0 ;
index += 1 ;
let parent = null ;
/ / r e a c h e d t h e e n d
let isFile = false ;
if ( index === splits . length ) {
for ( const split of splits ) {
isFile = true ;
index += 1 ;
/ / r e a c h e d t h e e n d
if ( index === splits . length ) {
isFile = true ;
}
let newParent = {
name : split ,
children : [ ] ,
isFile ,
} ;
if ( isFile === true ) {
newParent . file = file ;
}
if ( parent ) {
/ / c h e c k i f t h e f o l d e r a l r e a d y e x i s t s
const existingFolder = parent . children . find (
( x ) => x . name === split ,
) ;
if ( existingFolder ) {
newParent = existingFolder ;
} else {
parent . children . push ( newParent ) ;
}
} else {
const existingFolder = result . find ( ( x ) => x . name === split ) ;
if ( existingFolder ) {
newParent = existingFolder ;
} else {
result . push ( newParent ) ;
}
}
parent = newParent ;
}
}
}
const mergeChildIfOnlyOneDir = ( entries ) => {
let newParent = {
for ( const entry of entries ) {
name : split ,
if ( entry . children ) {
children : [ ] ,
mergeChildIfOnlyOneDir ( entry . children ) ;
isFile ,
}
} as {
if ( entry . children . length === 1 && entry . children [ 0 ] . isFile === false ) {
name : string ,
/ / M e r g e i t t o t h e p a r e n t
children : any [ ] ,
entry . name = ` ${ entry . name } / ${ entry . children [ 0 ] . name } ` ;
isFile : boolean ,
entry . children = entry . children [ 0 ] . children ;
file ? : any ,
}
}
} ;
} ;
/ / M e r g e f o l d e r s w i t h j u s t a f o l d e r a s c h i l d r e n i n o r d e r t o
/ / r e d u c e t h e d e p t h o f o u r t r e e .
if ( isFile === true ) {
mergeChildIfOnlyOneDir ( result ) ;
newParent . file = file ;
return result ;
}
} ,
} ,
if ( parent ) {
mounted ( ) {
/ / c h e c k i f t h e f o l d e r a l r e a d y e x i s t s
/ / D e f a u l t t o t r u e i f u n s e t
const existingFolder = parent . children . find (
this . store . fileTreeIsVisible = localStorage . getItem ( LOCAL _STORAGE _KEY ) !== 'false' ;
( x ) => x . name === split ,
document . querySelector ( '.diff-toggle-file-tree-button' ) . addEventListener ( 'click' , this . toggleVisibility ) ;
) ;
if ( existingFolder ) {
this . hashChangeListener = ( ) => {
newParent = existingFolder ;
this . store . selectedItem = window . location . hash ;
} else {
this . expandSelectedFile ( ) ;
parent . children . push ( newParent ) ;
} ;
}
this . hashChangeListener ( ) ;
} else {
window . addEventListener ( 'hashchange' , this . hashChangeListener ) ;
const existingFolder = result . find ( ( x ) => x . name === split ) ;
} ,
if ( existingFolder ) {
unmounted ( ) {
newParent = existingFolder ;
document . querySelector ( '.diff-toggle-file-tree-button' ) . removeEventListener ( 'click' , this . toggleVisibility ) ;
} else {
window . removeEventListener ( 'hashchange' , this . hashChangeListener ) ;
result . push ( newParent ) ;
} ,
}
methods : {
}
expandSelectedFile ( ) {
parent = newParent ;
/ / e x p a n d f i l e i f t h e s e l e c t e d f i l e i s f o l d e d
}
if ( this . store . selectedItem ) {
}
const box = document . querySelector ( this . store . selectedItem ) ;
const mergeChildIfOnlyOneDir = ( entries ) => {
const folded = box ? . getAttribute ( 'data-folded' ) === 'true' ;
for ( const entry of entries ) {
if ( folded ) setFileFolding ( box , box . querySelector ( '.fold-file' ) , false ) ;
if ( entry . children ) {
mergeChildIfOnlyOneDir ( entry . children ) ;
}
}
} ,
if ( entry . children . length === 1 && entry . children [ 0 ] . isFile === false ) {
toggleVisibility ( ) {
/ / M e r g e i t t o t h e p a r e n t
this . updateVisibility ( ! this . store . fileTreeIsVisible ) ;
entry . name = ` ${ entry . name } / ${ entry . children [ 0 ] . name } ` ;
} ,
entry . children = entry . children [ 0 ] . children ;
updateVisibility ( visible ) {
}
this . store . fileTreeIsVisible = visible ;
}
localStorage . setItem ( LOCAL _STORAGE _KEY , this . store . fileTreeIsVisible ) ;
} ;
this . updateState ( this . store . fileTreeIsVisible ) ;
/ / M e r g e f o l d e r s w i t h j u s t a f o l d e r a s c h i l d r e n i n o r d e r t o
} ,
/ / r e d u c e t h e d e p t h o f o u r t r e e .
updateState ( visible ) {
mergeChildIfOnlyOneDir ( result ) ;
const btn = document . querySelector ( '.diff-toggle-file-tree-button' ) ;
return result ;
const [ toShow , toHide ] = btn . querySelectorAll ( '.icon' ) ;
} ) ;
const tree = document . querySelector ( '#diff-file-tree' ) ;
const newTooltip = btn . getAttribute ( visible ? 'data-hide-text' : 'data-show-text' ) ;
onMounted ( ( ) => {
btn . setAttribute ( 'data-tooltip-content' , newTooltip ) ;
/ / D e f a u l t t o t r u e i f u n s e t
toggleElem ( tree , visible ) ;
store . fileTreeIsVisible = localStorage . getItem ( LOCAL _STORAGE _KEY ) !== 'false' ;
toggleElem ( toShow , ! visible ) ;
document . querySelector ( '.diff-toggle-file-tree-button' ) . addEventListener ( 'click' , toggleVisibility ) ;
toggleElem ( toHide , visible ) ;
} ,
hashChangeListener ( ) ;
loadMoreData ( ) {
window . addEventListener ( 'hashchange' , hashChangeListener ) ;
loadMoreFiles ( this . store . linkLoadMore ) ;
} ) ;
} ,
} ,
onUnmounted ( ( ) => {
} ;
document . querySelector ( '.diff-toggle-file-tree-button' ) . removeEventListener ( 'click' , toggleVisibility ) ;
window . removeEventListener ( 'hashchange' , hashChangeListener ) ;
} ) ;
function hashChangeListener ( ) {
store . selectedItem = window . location . hash ;
expandSelectedFile ( ) ;
}
function expandSelectedFile ( ) {
/ / e x p a n d f i l e i f t h e s e l e c t e d f i l e i s f o l d e d
if ( store . selectedItem ) {
const box = document . querySelector ( store . selectedItem ) ;
const folded = box ? . getAttribute ( 'data-folded' ) === 'true' ;
if ( folded ) setFileFolding ( box , box . querySelector ( '.fold-file' ) , false ) ;
}
}
function toggleVisibility ( ) {
updateVisibility ( ! store . fileTreeIsVisible ) ;
}
function updateVisibility ( visible ) {
store . fileTreeIsVisible = visible ;
localStorage . setItem ( LOCAL _STORAGE _KEY , store . fileTreeIsVisible ) ;
updateState ( store . fileTreeIsVisible ) ;
}
function updateState ( visible ) {
const btn = document . querySelector ( '.diff-toggle-file-tree-button' ) ;
const [ toShow , toHide ] = btn . querySelectorAll ( '.icon' ) ;
const tree = document . querySelector ( '#diff-file-tree' ) ;
const newTooltip = btn . getAttribute ( visible ? 'data-hide-text' : 'data-show-text' ) ;
btn . setAttribute ( 'data-tooltip-content' , newTooltip ) ;
toggleElem ( tree , visible ) ;
toggleElem ( toShow , ! visible ) ;
toggleElem ( toHide , visible ) ;
}
function loadMoreData ( ) {
loadMoreFiles ( store . linkLoadMore ) ;
}
< / script >
< / script >
< template >
< template >
< div v-if ="store.fileTreeIsVisible" class="diff-file-tree-items" >
< div v-if ="store.fileTreeIsVisible" class="diff-file-tree-items" >
<!-- only render the tree if we 're visible. in many cases this is something that doesn' t change very often -- >
<!-- only render the tree if we 're visible. in many cases this is something that doesn' t change very often -- >
@ -134,6 +141,7 @@ export default {
< / div >
< / div >
< / div >
< / div >
< / template >
< / template >
< style scoped >
< style scoped >
. diff - file - tree - items {
. diff - file - tree - items {
display : flex ;
display : flex ;