mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	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>
		
			
				
	
	
		
			86 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import {dirname, basename} from '../utils.ts';
 | |
| 
 | |
| export type FileStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'typechange';
 | |
| 
 | |
| export type File = {
 | |
|   Name: string;
 | |
|   NameHash: string;
 | |
|   Status: FileStatus;
 | |
|   IsViewed: boolean;
 | |
|   IsSubmodule: boolean;
 | |
| }
 | |
| 
 | |
| type DirItem = {
 | |
|     isFile: false;
 | |
|     name: string;
 | |
|     path: string;
 | |
| 
 | |
|     children: Item[];
 | |
| }
 | |
| 
 | |
| type FileItem = {
 | |
|     isFile: true;
 | |
|     name: string;
 | |
|     path: string;
 | |
|     file: File;
 | |
| }
 | |
| 
 | |
| export type Item = DirItem | FileItem;
 | |
| 
 | |
| export function pathListToTree(fileEntries: File[]): Item[] {
 | |
|   const pathToItem = new Map<string, DirItem>();
 | |
| 
 | |
|     // init root node
 | |
|   const root: DirItem = {name: '', path: '', isFile: false, children: []};
 | |
|   pathToItem.set('', root);
 | |
| 
 | |
|   for (const fileEntry of fileEntries) {
 | |
|     const [parentPath, fileName] = [dirname(fileEntry.Name), basename(fileEntry.Name)];
 | |
| 
 | |
|     let parentItem = pathToItem.get(parentPath);
 | |
|     if (!parentItem) {
 | |
|       parentItem = constructParents(pathToItem, parentPath);
 | |
|     }
 | |
| 
 | |
|     const fileItem: FileItem = {name: fileName, path: fileEntry.Name, isFile: true, file: fileEntry};
 | |
| 
 | |
|     parentItem.children.push(fileItem);
 | |
|   }
 | |
| 
 | |
|   return root.children;
 | |
| }
 | |
| 
 | |
| function constructParents(pathToItem: Map<string, DirItem>, dirPath: string): DirItem {
 | |
|   const [dirParentPath, dirName] = [dirname(dirPath), basename(dirPath)];
 | |
| 
 | |
|   let parentItem = pathToItem.get(dirParentPath);
 | |
|   if (!parentItem) {
 | |
|     // if the parent node does not exist, create it
 | |
|     parentItem = constructParents(pathToItem, dirParentPath);
 | |
|   }
 | |
| 
 | |
|   const dirItem: DirItem = {name: dirName, path: dirPath, isFile: false, children: []};
 | |
|   parentItem.children.push(dirItem);
 | |
|   pathToItem.set(dirPath, dirItem);
 | |
| 
 | |
|   return dirItem;
 | |
| }
 | |
| 
 | |
| export function mergeChildIfOnlyOneDir(nodes: Item[]): void {
 | |
|   for (const node of nodes) {
 | |
|     if (node.isFile) {
 | |
|       continue;
 | |
|     }
 | |
|     const dir = node as DirItem;
 | |
| 
 | |
|     mergeChildIfOnlyOneDir(dir.children);
 | |
| 
 | |
|     if (dir.children.length === 1 && dir.children[0].isFile === false) {
 | |
|       const child = dir.children[0];
 | |
|       dir.name = `${dir.name}/${child.name}`;
 | |
|       dir.path = child.path;
 | |
|       dir.children = child.children;
 | |
|     }
 | |
|   }
 | |
| }
 |