mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Use git diff-tree for DiffFileTree on diff pages (#33514)
				
					
				
			Modify Diff View FileTree to show all files ## Changes * removes Show Status button on diff * uses `git diff-tree` to generate the file tree for the diff * doesn't reload the diff tree each time we load more files in the preview * selecting and unloaded file will keep loading until that file is loaded * removes `DiffFileList.vue` and "Show Stats" in diff options ## Open Questions * selecting and unloaded file will keep loading until that file is loaded. Is this behaviour okay? It matches what github does. ### Demo In this demo I set `git.MAX_GIT_DIFF_FILES=1` in my `app.ini` to demonstrate a worst case example. In most cases the behaviour isn't nearly as jarring as we load a bunch of files at a time. https://github.com/user-attachments/assets/72f29663-d6fc-472d-94fa-7fb5950c2836 --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		| @@ -1,75 +1,18 @@ | ||||
| <script lang="ts" setup> | ||||
| import DiffFileTreeItem, {type Item} from './DiffFileTreeItem.vue'; | ||||
| import {loadMoreFiles} from '../features/repo-diff.ts'; | ||||
| import DiffFileTreeItem from './DiffFileTreeItem.vue'; | ||||
| import {toggleElem} from '../utils/dom.ts'; | ||||
| import {diffTreeStore} from '../modules/stores.ts'; | ||||
| import {setFileFolding} from '../features/file-fold.ts'; | ||||
| import {computed, onMounted, onUnmounted} from 'vue'; | ||||
| import {pathListToTree, mergeChildIfOnlyOneDir} from '../utils/filetree.ts'; | ||||
|  | ||||
| const LOCAL_STORAGE_KEY = 'diff_file_tree_visible'; | ||||
|  | ||||
| const store = diffTreeStore(); | ||||
|  | ||||
| const fileTree = computed(() => { | ||||
|   const result: Array<Item> = []; | ||||
|   for (const file of store.files) { | ||||
|     // Split file into directories | ||||
|     const splits = file.Name.split('/'); | ||||
|     let index = 0; | ||||
|     let parent = null; | ||||
|     let isFile = false; | ||||
|     for (const split of splits) { | ||||
|       index += 1; | ||||
|       // reached the end | ||||
|       if (index === splits.length) { | ||||
|         isFile = true; | ||||
|       } | ||||
|       let newParent: Item = { | ||||
|         name: split, | ||||
|         children: [], | ||||
|         isFile, | ||||
|       }; | ||||
|  | ||||
|       if (isFile === true) { | ||||
|         newParent.file = file; | ||||
|       } | ||||
|  | ||||
|       if (parent) { | ||||
|         // check if the folder already exists | ||||
|         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: Array<Record<string, any>>) => { | ||||
|     for (const entry of entries) { | ||||
|       if (entry.children) { | ||||
|         mergeChildIfOnlyOneDir(entry.children); | ||||
|       } | ||||
|       if (entry.children.length === 1 && entry.children[0].isFile === false) { | ||||
|         // Merge it to the parent | ||||
|         entry.name = `${entry.name}/${entry.children[0].name}`; | ||||
|         entry.children = entry.children[0].children; | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|   // Merge folders with just a folder as children in order to | ||||
|   // reduce the depth of our tree. | ||||
|   mergeChildIfOnlyOneDir(result); | ||||
|   const result = pathListToTree(store.files); | ||||
|   mergeChildIfOnlyOneDir(result); // mutation | ||||
|   return result; | ||||
| }); | ||||
|  | ||||
| @@ -121,19 +64,12 @@ function updateState(visible: boolean) { | ||||
|   toggleElem(toShow, !visible); | ||||
|   toggleElem(toHide, visible); | ||||
| } | ||||
|  | ||||
| function loadMoreData() { | ||||
|   loadMoreFiles(store.linkLoadMore); | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
|   <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 --> | ||||
|     <DiffFileTreeItem v-for="item in fileTree" :key="item.name" :item="item"/> | ||||
|     <div v-if="store.isIncomplete" class="tw-pt-1"> | ||||
|       <a :class="['ui', 'basic', 'tiny', 'button', store.isLoadingNewData ? 'disabled' : '']" @click.stop="loadMoreData">{{ store.showMoreMessage }}</a> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Alexander McRae
					Alexander McRae