@anymux/ui-kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ExplorerLayout-CSIJd7N4.js +105 -0
- package/dist/ExplorerLayout-CSIJd7N4.js.map +1 -0
- package/dist/FileBrowserContext-B6jixa2j.js +11 -0
- package/dist/FileBrowserContext-B6jixa2j.js.map +1 -0
- package/dist/calendar-DSlrbHoj.js +761 -0
- package/dist/calendar-DSlrbHoj.js.map +1 -0
- package/dist/calendar.d.ts +3 -0
- package/dist/calendar.js +3 -0
- package/dist/contacts-DQXTZzHc.js +539 -0
- package/dist/contacts-DQXTZzHc.js.map +1 -0
- package/dist/contacts.d.ts +3 -0
- package/dist/contacts.js +3 -0
- package/dist/file-browser-m5atC3kF.js +6755 -0
- package/dist/file-browser-m5atC3kF.js.map +1 -0
- package/dist/file-browser.d.ts +11 -0
- package/dist/file-browser.js +9 -0
- package/dist/git-B55e6LL-.js +561 -0
- package/dist/git-B55e6LL-.js.map +1 -0
- package/dist/git.d.ts +2 -0
- package/dist/git.js +3 -0
- package/dist/iconMap-V4B8P-Uh.js +206 -0
- package/dist/iconMap-V4B8P-Uh.js.map +1 -0
- package/dist/icons-CIsIOZXR.js +0 -0
- package/dist/icons.d.ts +2 -0
- package/dist/icons.js +4 -0
- package/dist/index-BNmNIWBL.d.ts +71 -0
- package/dist/index-BNmNIWBL.d.ts.map +1 -0
- package/dist/index-Bryv_GCG.d.ts +1481 -0
- package/dist/index-Bryv_GCG.d.ts.map +1 -0
- package/dist/index-CuQIjSXs.d.ts +134 -0
- package/dist/index-CuQIjSXs.d.ts.map +1 -0
- package/dist/index-DSu19mq0.d.ts +153 -0
- package/dist/index-DSu19mq0.d.ts.map +1 -0
- package/dist/index-DmsyeHFr.d.ts +149 -0
- package/dist/index-DmsyeHFr.d.ts.map +1 -0
- package/dist/index-DxnJ8FYM.d.ts +17 -0
- package/dist/index-DxnJ8FYM.d.ts.map +1 -0
- package/dist/index-DzfY1Tok.d.ts +32 -0
- package/dist/index-DzfY1Tok.d.ts.map +1 -0
- package/dist/index-Ml_SgiKa.d.ts +1847 -0
- package/dist/index-Ml_SgiKa.d.ts.map +1 -0
- package/dist/index-kHr9udZD.d.ts +1025 -0
- package/dist/index-kHr9udZD.d.ts.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +15 -0
- package/dist/layout-Ca_4r8ka.js +89 -0
- package/dist/layout-Ca_4r8ka.js.map +1 -0
- package/dist/layout.d.ts +2 -0
- package/dist/layout.js +5 -0
- package/dist/list-CxfT6hix.js +6831 -0
- package/dist/list-CxfT6hix.js.map +1 -0
- package/dist/list.d.ts +2 -0
- package/dist/list.js +5 -0
- package/dist/media-DZ292aKK.js +557 -0
- package/dist/media-DZ292aKK.js.map +1 -0
- package/dist/media.d.ts +3 -0
- package/dist/media.js +3 -0
- package/dist/tree-Dd9Z0Aso.js +3351 -0
- package/dist/tree-Dd9Z0Aso.js.map +1 -0
- package/dist/tree.d.ts +2 -0
- package/dist/tree.js +6 -0
- package/dist/types-common-CB3kRek8.d.ts +26 -0
- package/dist/types-common-CB3kRek8.d.ts.map +1 -0
- package/dist/utils-B4fdKKsy.js +3 -0
- package/package.json +109 -0
- package/src/calendar/AgendaView.tsx +37 -0
- package/src/calendar/CalendarBrowser.tsx +90 -0
- package/src/calendar/CalendarModel.ts +142 -0
- package/src/calendar/CalendarSidebar.tsx +81 -0
- package/src/calendar/DayView.tsx +76 -0
- package/src/calendar/EventCard.tsx +51 -0
- package/src/calendar/MockCalendarProvider.ts +98 -0
- package/src/calendar/MonthView.tsx +77 -0
- package/src/calendar/WeekView.tsx +129 -0
- package/src/calendar/index.ts +18 -0
- package/src/calendar/types.ts +25 -0
- package/src/contacts/ContactAvatar.tsx +35 -0
- package/src/contacts/ContactBrowser.tsx +56 -0
- package/src/contacts/ContactCard.tsx +37 -0
- package/src/contacts/ContactDetail.tsx +63 -0
- package/src/contacts/ContactGroupSidebar.tsx +40 -0
- package/src/contacts/ContactList.tsx +32 -0
- package/src/contacts/ContactListModel.ts +120 -0
- package/src/contacts/MockContactProvider.ts +77 -0
- package/src/contacts/index.ts +17 -0
- package/src/contacts/types.ts +26 -0
- package/src/demos/CalendarBrowserDemo.tsx +15 -0
- package/src/demos/ContactBrowserDemo.tsx +15 -0
- package/src/demos/MediaBrowserDemo.tsx +15 -0
- package/src/file-browser/adapters/DocumentViewerAdapter.ts +371 -0
- package/src/file-browser/adapters/FileSystemBridge.ts +168 -0
- package/src/file-browser/adapters/GitBrowserAdapter.ts +546 -0
- package/src/file-browser/adapters/README.md +504 -0
- package/src/file-browser/adapters/index.ts +27 -0
- package/src/file-browser/adapters/types.ts +70 -0
- package/src/file-browser/architecture.md +645 -0
- package/src/file-browser/components/CreateItemDialog.tsx +71 -0
- package/src/file-browser/components/DeleteConfirmDialog.tsx +58 -0
- package/src/file-browser/components/FileBrowser.tsx +473 -0
- package/src/file-browser/components/FileBrowserContent.tsx +209 -0
- package/src/file-browser/components/FileBrowserHeader.tsx +151 -0
- package/src/file-browser/components/FileBrowserToolbar.tsx +145 -0
- package/src/file-browser/components/LeftPanel/LeftPanel.tsx +103 -0
- package/src/file-browser/components/LeftPanel/LeftPanelTabs.tsx +70 -0
- package/src/file-browser/components/LeftPanel/TreeNavigationView.tsx +256 -0
- package/src/file-browser/components/PreviewPane.tsx +146 -0
- package/src/file-browser/components/RightPanel/FilePreview.tsx +219 -0
- package/src/file-browser/components/RightPanel/RightPanel.tsx +186 -0
- package/src/file-browser/components/RightPanel/RightPanelToolbar.tsx +113 -0
- package/src/file-browser/components/UploadProgress.tsx +123 -0
- package/src/file-browser/components/ViewerHost.tsx +208 -0
- package/src/file-browser/components/mobile/MobileNavigation.tsx +227 -0
- package/src/file-browser/components/navigation/NavigationButtons.tsx +171 -0
- package/src/file-browser/components/shared/ErrorBoundary.tsx +116 -0
- package/src/file-browser/components/shared/FileBrowserItem.tsx +195 -0
- package/src/file-browser/components/shared/FileIcon.tsx +169 -0
- package/src/file-browser/components/toolbar/ViewModeToggle.tsx +200 -0
- package/src/file-browser/components/views/ListView/ListView.tsx +484 -0
- package/src/file-browser/components/views/ThumbnailView/ThumbnailView.tsx +323 -0
- package/src/file-browser/components/views/TreeView/TreeNode.tsx +186 -0
- package/src/file-browser/components/views/TreeView/TreeNodeList.tsx +191 -0
- package/src/file-browser/components/views/TreeView/TreeView.tsx +200 -0
- package/src/file-browser/components/views/TreemapView/TreemapView.tsx +339 -0
- package/src/file-browser/context/FileBrowserContext.tsx +13 -0
- package/src/file-browser/examples/BasicUsage.tsx +20 -0
- package/src/file-browser/index.ts +98 -0
- package/src/file-browser/models/FileBrowserModel.ts +623 -0
- package/src/file-browser/models/LeftPanelManagerModel.ts +105 -0
- package/src/file-browser/models/NavigationManagerModel.ts +312 -0
- package/src/file-browser/models/ResponsiveLayoutManagerModel.ts +437 -0
- package/src/file-browser/models/RightPanelManagerModel.ts +190 -0
- package/src/file-browser/models/SelectionManagerModel.ts +252 -0
- package/src/file-browser/models/ToolbarManagerModel.ts +144 -0
- package/src/file-browser/models/UploadModel.ts +147 -0
- package/src/file-browser/models/ViewModeManagerModel.ts +185 -0
- package/src/file-browser/models/ViewerHostModel.ts +44 -0
- package/src/file-browser/models/ui/ListViewUIModel.ts +265 -0
- package/src/file-browser/models/ui/PreviewUIModel.ts +297 -0
- package/src/file-browser/models/ui/ThumbnailViewUIModel.ts +254 -0
- package/src/file-browser/models/ui/TreeViewUIModel.ts +128 -0
- package/src/file-browser/models/ui/TreemapViewUIModel.ts +350 -0
- package/src/file-browser/providers/FileSystemListProvider.ts +552 -0
- package/src/file-browser/providers/FileSystemProvider.ts +401 -0
- package/src/file-browser/providers/FileSystemTreeProvider.ts +231 -0
- package/src/file-browser/providers/GitProvider.ts +337 -0
- package/src/file-browser/providers/GitRepositoryProvider.ts +376 -0
- package/src/file-browser/providers/IFileBrowserProvider.ts +56 -0
- package/src/file-browser/providers/MemoryProvider.ts +303 -0
- package/src/file-browser/providers/index.ts +4 -0
- package/src/file-browser/registry/ViewerRegistry.ts +551 -0
- package/src/file-browser/registry/types.ts +144 -0
- package/src/file-browser/scripts/performanceBenchmark.ts +553 -0
- package/src/file-browser/services/ThumbnailCacheService.ts +128 -0
- package/src/file-browser/tasks.md +537 -0
- package/src/file-browser/types/FileBrowserTypes.ts +126 -0
- package/src/file-browser/types/ProviderTypes.ts +155 -0
- package/src/file-browser/types/UITypes.ts +235 -0
- package/src/file-browser/types/ViewModeTypes.ts +150 -0
- package/src/file-browser/utils/gestures.ts +327 -0
- package/src/file-browser/utils/performance.ts +563 -0
- package/src/file-browser/viewers/ImageViewer.tsx +163 -0
- package/src/file-browser/viewers/ImageViewerModel.ts +79 -0
- package/src/file-browser/viewers/TextViewer.tsx +95 -0
- package/src/file-browser/viewers/UnsupportedFileViewer.tsx +57 -0
- package/src/file-browser/viewers/index.ts +61 -0
- package/src/git/BranchList.tsx +128 -0
- package/src/git/CommitGraph.tsx +239 -0
- package/src/git/CommitList.tsx +258 -0
- package/src/git/DiffViewer.tsx +219 -0
- package/src/git/index.ts +4 -0
- package/src/icons/iconMap.ts +146 -0
- package/src/icons/index.ts +9 -0
- package/src/index.ts +13 -0
- package/src/layout/README.md +307 -0
- package/src/layout/components/ExplorerLayout/ExplorerLayout.tsx +178 -0
- package/src/layout/examples/SimpleExample.tsx +60 -0
- package/src/layout/index.ts +6 -0
- package/src/lib/utils.ts +1 -0
- package/src/list/README.md +303 -0
- package/src/list/architecture.md +807 -0
- package/src/list/components/CalculatedGridView.tsx +252 -0
- package/src/list/components/DragPreview.tsx +102 -0
- package/src/list/components/ListContextMenu.tsx +274 -0
- package/src/list/components/ListItem.tsx +761 -0
- package/src/list/components/ListItems.tsx +919 -0
- package/src/list/components/MasonryView.tsx +241 -0
- package/src/list/components/SearchFilter.tsx +44 -0
- package/src/list/components/TreemapView.tsx +709 -0
- package/src/list/components/ViewSizeControls.tsx +205 -0
- package/src/list/components/ViewTypeSelector.tsx +312 -0
- package/src/list/components/VirtualizedDetailsView.tsx +231 -0
- package/src/list/components/VirtualizedGrid.tsx +164 -0
- package/src/list/components/VirtualizedList.tsx +154 -0
- package/src/list/components/VirtualizedMasonryView.tsx +344 -0
- package/src/list/components/shared/EmptyState.tsx +103 -0
- package/src/list/components/shared/ErrorBoundary.tsx +123 -0
- package/src/list/components/shared/ErrorDisplay.tsx +100 -0
- package/src/list/components/shared/ListLoader.tsx +146 -0
- package/src/list/components/shared/LoadingIndicator.tsx +80 -0
- package/src/list/index.ts +92 -0
- package/src/list/models/ListItemsModel.ts +1301 -0
- package/src/list/models/TreemapModel.ts +204 -0
- package/src/list/providers/ListItemsProvider.ts +313 -0
- package/src/list/providers/TestListProvider.ts +604 -0
- package/src/list/tasks.md +937 -0
- package/src/list/types/ListTypes.ts +178 -0
- package/src/list/utils/BenchmarkLogger.ts +243 -0
- package/src/list/utils/DragDropManager.ts +320 -0
- package/src/list/utils/GridLayoutCalculator.ts +290 -0
- package/src/list/utils/ListAccessibility.ts +367 -0
- package/src/list/utils/ListKeyboard.ts +414 -0
- package/src/list/utils/MasonryLayoutCalculator.ts +302 -0
- package/src/list/utils/MasonryLayoutEngine.ts +401 -0
- package/src/list/utils/__tests__/MasonryLayoutEngine.test.ts +157 -0
- package/src/list/utils/__tests__/VirtualizedMasonryView.test.tsx +251 -0
- package/src/media/AlbumSidebar.tsx +48 -0
- package/src/media/MediaBrowser.tsx +92 -0
- package/src/media/MediaBrowserModel.ts +138 -0
- package/src/media/MediaGrid.tsx +50 -0
- package/src/media/MediaList.tsx +49 -0
- package/src/media/MediaPreview.tsx +63 -0
- package/src/media/MediaTimeline.tsx +38 -0
- package/src/media/MockMediaProvider.ts +70 -0
- package/src/media/index.ts +18 -0
- package/src/media/types.ts +21 -0
- package/src/styles/variables.css +60 -0
- package/src/tree/DEVELOPMENT_SUMMARY.md +170 -0
- package/src/tree/__tests__/TreeModel.test.ts +16 -0
- package/src/tree/architecture.md +530 -0
- package/src/tree/components/Tree.tsx +283 -0
- package/src/tree/components/TreeCheckbox.tsx +147 -0
- package/src/tree/components/TreeContextMenu.tsx +139 -0
- package/src/tree/components/TreeNodeList.tsx +329 -0
- package/src/tree/components/TreeTable.tsx +382 -0
- package/src/tree/index.ts +58 -0
- package/src/tree/models/TreeModel.ts +839 -0
- package/src/tree/providers/SimpleTreeProvider.ts +463 -0
- package/src/tree/providers/TestTreeProvider.ts +946 -0
- package/src/tree/providers/TreeProvider.ts +308 -0
- package/src/tree/tasks.md +2046 -0
- package/src/tree/types/TreeTypes.ts +279 -0
- package/src/tree/utils/SelectionTheme.ts +150 -0
- package/src/tree/utils/logger.ts +203 -0
- package/src/types-common.ts +21 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { makeAutoObservable } from 'mobx';
|
|
2
|
+
import type { IFileSystem, Dirent, Stats } from '@anymux/file-system';
|
|
3
|
+
|
|
4
|
+
export interface ScanProgress {
|
|
5
|
+
directoriesScanned: number;
|
|
6
|
+
filesFound: number;
|
|
7
|
+
totalSize: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface FileSystemItem {
|
|
11
|
+
id: string;
|
|
12
|
+
path: string;
|
|
13
|
+
name: string;
|
|
14
|
+
type: 'file' | 'directory';
|
|
15
|
+
size?: number;
|
|
16
|
+
modified?: Date;
|
|
17
|
+
isDirectory: boolean;
|
|
18
|
+
children?: FileSystemItem[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class FileSystemBridge {
|
|
22
|
+
constructor(private fileSystem: IFileSystem) {
|
|
23
|
+
makeAutoObservable(this, {
|
|
24
|
+
fileSystem: false,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Tree operations (directories only)
|
|
29
|
+
async loadDirectoryTree(path: string): Promise<FileSystemItem[]> {
|
|
30
|
+
const dirents = await this.fileSystem.readdir(path, { withFileTypes: true });
|
|
31
|
+
|
|
32
|
+
return dirents
|
|
33
|
+
.filter(dirent => dirent.isDirectory())
|
|
34
|
+
.map(dirent => ({
|
|
35
|
+
id: `${path}/${dirent.name}`.replace(/\/\//g, '/'),
|
|
36
|
+
path: `${path}/${dirent.name}`.replace(/\/\//g, '/'),
|
|
37
|
+
name: dirent.name,
|
|
38
|
+
type: 'directory' as const,
|
|
39
|
+
isDirectory: true
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// List operations (all items)
|
|
44
|
+
async loadDirectoryContents(path: string): Promise<FileSystemItem[]> {
|
|
45
|
+
const dirents = await this.fileSystem.readdir(path, { withFileTypes: true });
|
|
46
|
+
|
|
47
|
+
const items = await Promise.all(
|
|
48
|
+
dirents.map(async (dirent) => {
|
|
49
|
+
const itemPath = `${path}/${dirent.name}`.replace(/\/\//g, '/');
|
|
50
|
+
let stats: Stats | null = null;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
stats = await this.fileSystem.stat(itemPath);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
console.warn(`[FileSystemBridge] stat failed for ${itemPath}:`, err instanceof Error ? err.message : err);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
id: itemPath,
|
|
60
|
+
path: itemPath,
|
|
61
|
+
name: dirent.name,
|
|
62
|
+
type: dirent.isDirectory() ? 'directory' as const : 'file' as const,
|
|
63
|
+
size: stats?.size,
|
|
64
|
+
modified: stats?.mtime,
|
|
65
|
+
isDirectory: dirent.isDirectory()
|
|
66
|
+
};
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
// Sort: directories first, then files, both alphabetically
|
|
71
|
+
return items.sort((a, b) => {
|
|
72
|
+
if (a.type !== b.type) {
|
|
73
|
+
return a.type === 'directory' ? -1 : 1;
|
|
74
|
+
}
|
|
75
|
+
return a.name.localeCompare(b.name);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Recursive directory scan for treemap — returns nested FileSystemItem tree
|
|
80
|
+
async loadDirectoryRecursive(
|
|
81
|
+
path: string,
|
|
82
|
+
maxDepth = 3,
|
|
83
|
+
onProgress?: (progress: ScanProgress) => void,
|
|
84
|
+
_progress?: ScanProgress,
|
|
85
|
+
): Promise<FileSystemItem[]> {
|
|
86
|
+
const progress = _progress ?? { directoriesScanned: 0, filesFound: 0, totalSize: 0 };
|
|
87
|
+
const dirents = await this.fileSystem.readdir(path, { withFileTypes: true });
|
|
88
|
+
|
|
89
|
+
const items = await Promise.all(
|
|
90
|
+
dirents.map(async (dirent) => {
|
|
91
|
+
const itemPath = `${path}/${dirent.name}`.replace(/\/\//g, '/');
|
|
92
|
+
const isDir = dirent.isDirectory();
|
|
93
|
+
let stats: Stats | null = null;
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
stats = await this.fileSystem.stat(itemPath);
|
|
97
|
+
} catch {
|
|
98
|
+
// skip stat errors
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (isDir) {
|
|
102
|
+
progress.directoriesScanned++;
|
|
103
|
+
} else {
|
|
104
|
+
progress.filesFound++;
|
|
105
|
+
if (stats?.size) progress.totalSize += stats.size;
|
|
106
|
+
}
|
|
107
|
+
onProgress?.(progress);
|
|
108
|
+
|
|
109
|
+
const item: FileSystemItem = {
|
|
110
|
+
id: itemPath,
|
|
111
|
+
path: itemPath,
|
|
112
|
+
name: dirent.name,
|
|
113
|
+
type: isDir ? 'directory' : 'file',
|
|
114
|
+
size: stats?.size,
|
|
115
|
+
modified: stats?.mtime,
|
|
116
|
+
isDirectory: isDir,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Recursively load subdirectories
|
|
120
|
+
if (isDir && maxDepth > 0) {
|
|
121
|
+
try {
|
|
122
|
+
item.children = await this.loadDirectoryRecursive(itemPath, maxDepth - 1, onProgress, progress);
|
|
123
|
+
} catch {
|
|
124
|
+
item.children = [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return item;
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
return items;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// File operations
|
|
136
|
+
async readFile(path: string): Promise<Buffer | string> {
|
|
137
|
+
return this.fileSystem.readFile(path);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async writeFile(path: string, content: Buffer | string): Promise<void> {
|
|
141
|
+
return this.fileSystem.writeFile(path, content);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async deleteItem(path: string, isDirectory: boolean): Promise<void> {
|
|
145
|
+
if (isDirectory) {
|
|
146
|
+
return this.fileSystem.rmdir(path, { recursive: true });
|
|
147
|
+
} else {
|
|
148
|
+
return this.fileSystem.unlink(path);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async createDirectory(path: string): Promise<void> {
|
|
153
|
+
await this.fileSystem.mkdir(path, { recursive: true });
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async renameItem(oldPath: string, newPath: string): Promise<void> {
|
|
157
|
+
return this.fileSystem.rename(oldPath, newPath);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async exists(path: string): Promise<boolean> {
|
|
161
|
+
try {
|
|
162
|
+
await this.fileSystem.access(path);
|
|
163
|
+
return true;
|
|
164
|
+
} catch {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import { makeAutoObservable, reaction } from 'mobx';
|
|
2
|
+
import { FileBrowserModel } from '../models/FileBrowserModel';
|
|
3
|
+
import { FileBrowserItem } from '../types/FileBrowserTypes';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Example adapter demonstrating how to integrate Git repository functionality
|
|
7
|
+
* with the dual-panel FileBrowser coordination system.
|
|
8
|
+
*
|
|
9
|
+
* This adapter:
|
|
10
|
+
* - Extends FileBrowser with Git-specific features
|
|
11
|
+
* - Provides Git status information for files and directories
|
|
12
|
+
* - Coordinates Git operations with FileBrowser navigation
|
|
13
|
+
* - Maintains branch and commit selection across panels
|
|
14
|
+
* - Demonstrates advanced dual-panel coordination patterns
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export interface GitBrowserOptions {
|
|
18
|
+
repositoryPath?: string;
|
|
19
|
+
autoFetch?: boolean;
|
|
20
|
+
showHiddenFiles?: boolean;
|
|
21
|
+
defaultBranch?: string;
|
|
22
|
+
enableCoordination?: boolean;
|
|
23
|
+
statusRefreshInterval?: number; // ms
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface GitFileStatus {
|
|
27
|
+
staged: boolean;
|
|
28
|
+
modified: boolean;
|
|
29
|
+
untracked: boolean;
|
|
30
|
+
conflicted: boolean;
|
|
31
|
+
deleted: boolean;
|
|
32
|
+
added: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface GitCommit {
|
|
36
|
+
hash: string;
|
|
37
|
+
message: string;
|
|
38
|
+
author: string;
|
|
39
|
+
date: Date;
|
|
40
|
+
parents: string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface GitBranch {
|
|
44
|
+
name: string;
|
|
45
|
+
isRemote: boolean;
|
|
46
|
+
isCurrent: boolean;
|
|
47
|
+
commit: string;
|
|
48
|
+
upstream?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface GitRepositoryInfo {
|
|
52
|
+
path: string;
|
|
53
|
+
currentBranch: string;
|
|
54
|
+
branches: GitBranch[];
|
|
55
|
+
commits: GitCommit[];
|
|
56
|
+
status: Map<string, GitFileStatus>;
|
|
57
|
+
isClean: boolean;
|
|
58
|
+
hasUncommitted: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class GitBrowserAdapter {
|
|
62
|
+
// Configuration
|
|
63
|
+
private options: Required<GitBrowserOptions>;
|
|
64
|
+
|
|
65
|
+
// Git-specific state
|
|
66
|
+
repositoryInfo: GitRepositoryInfo | null = null;
|
|
67
|
+
selectedCommit: GitCommit | null = null;
|
|
68
|
+
selectedBranch: GitBranch | null = null;
|
|
69
|
+
isLoading = false;
|
|
70
|
+
error: string | null = null;
|
|
71
|
+
|
|
72
|
+
// File status cache for performance
|
|
73
|
+
private statusCache = new Map<string, GitFileStatus>();
|
|
74
|
+
private refreshTimer: number | null = null;
|
|
75
|
+
|
|
76
|
+
// Coordination
|
|
77
|
+
private fileBrowserModel: FileBrowserModel;
|
|
78
|
+
private disposers: Array<() => void> = [];
|
|
79
|
+
|
|
80
|
+
constructor(
|
|
81
|
+
fileBrowserModel: FileBrowserModel,
|
|
82
|
+
options: GitBrowserOptions = {}
|
|
83
|
+
) {
|
|
84
|
+
this.fileBrowserModel = fileBrowserModel;
|
|
85
|
+
this.options = {
|
|
86
|
+
repositoryPath: '',
|
|
87
|
+
autoFetch: false,
|
|
88
|
+
showHiddenFiles: false,
|
|
89
|
+
defaultBranch: 'main',
|
|
90
|
+
enableCoordination: true,
|
|
91
|
+
statusRefreshInterval: 5000, // 5 seconds
|
|
92
|
+
...options
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
makeAutoObservable(this);
|
|
96
|
+
|
|
97
|
+
if (this.options.enableCoordination) {
|
|
98
|
+
this.setupCoordination();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.setupStatusRefresh();
|
|
102
|
+
|
|
103
|
+
this.logInfo('GitBrowserAdapter initialized', {
|
|
104
|
+
repositoryPath: this.options.repositoryPath,
|
|
105
|
+
coordinationEnabled: this.options.enableCoordination,
|
|
106
|
+
refreshInterval: this.options.statusRefreshInterval
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private setupCoordination() {
|
|
111
|
+
// Listen for selection changes to provide Git context
|
|
112
|
+
const selectionDisposer = reaction(
|
|
113
|
+
() => ({
|
|
114
|
+
selectedItems: Array.from(this.fileBrowserModel.selectionManager.selectedItems.keys()),
|
|
115
|
+
focusedItem: this.fileBrowserModel.selectionManager.focusedItem
|
|
116
|
+
}),
|
|
117
|
+
({ selectedItems, focusedItem }) => {
|
|
118
|
+
this.handleSelectionChange(focusedItem);
|
|
119
|
+
},
|
|
120
|
+
{ fireImmediately: true }
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Listen for navigation changes to update Git context
|
|
124
|
+
const navigationDisposer = reaction(
|
|
125
|
+
() => this.fileBrowserModel.navigationManager.currentPath,
|
|
126
|
+
(currentPath) => {
|
|
127
|
+
this.handleNavigationChange(currentPath || '/');
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
// Listen for left panel mode changes (for Git-specific views)
|
|
132
|
+
const leftPanelDisposer = reaction(
|
|
133
|
+
() => this.fileBrowserModel.leftPanel.currentMode,
|
|
134
|
+
(mode) => {
|
|
135
|
+
this.handleLeftPanelModeChange(mode);
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
this.disposers.push(selectionDisposer, navigationDisposer, leftPanelDisposer);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private setupStatusRefresh() {
|
|
143
|
+
if (this.options.statusRefreshInterval > 0) {
|
|
144
|
+
this.refreshTimer = window.setInterval(() => {
|
|
145
|
+
this.refreshGitStatus();
|
|
146
|
+
}, this.options.statusRefreshInterval);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private async handleSelectionChange(item: FileBrowserItem | null) {
|
|
151
|
+
if (!item || !this.repositoryInfo) return;
|
|
152
|
+
|
|
153
|
+
// Provide Git status for the selected item
|
|
154
|
+
const status = this.getFileStatus(item.path);
|
|
155
|
+
if (status) {
|
|
156
|
+
this.logInfo(`Git status for ${item.name}`, status);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// If it's a commit file, load commit details
|
|
160
|
+
if (this.isCommitReference(item)) {
|
|
161
|
+
await this.loadCommitDetails(item);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private async handleNavigationChange(currentPath: string) {
|
|
166
|
+
if (!this.repositoryInfo) return;
|
|
167
|
+
|
|
168
|
+
// Check if we've navigated outside the repository
|
|
169
|
+
if (!this.isPathInRepository(currentPath)) {
|
|
170
|
+
this.logInfo('Navigated outside repository');
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Update Git status for the current directory
|
|
175
|
+
await this.refreshGitStatus();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private handleLeftPanelModeChange(mode: string | undefined) {
|
|
179
|
+
if (!mode) return;
|
|
180
|
+
|
|
181
|
+
switch (mode) {
|
|
182
|
+
case 'git-history':
|
|
183
|
+
this.loadRepositoryHistory();
|
|
184
|
+
break;
|
|
185
|
+
case 'git-branches':
|
|
186
|
+
this.loadBranches();
|
|
187
|
+
break;
|
|
188
|
+
case 'git-status':
|
|
189
|
+
this.loadWorkingTreeStatus();
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Git operations
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Initialize Git repository in the current path
|
|
198
|
+
*/
|
|
199
|
+
async initializeRepository(path: string): Promise<void> {
|
|
200
|
+
this.isLoading = true;
|
|
201
|
+
this.error = null;
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
// Simulate Git init operation
|
|
205
|
+
await this.simulateGitOperation('init', { path });
|
|
206
|
+
|
|
207
|
+
this.repositoryInfo = {
|
|
208
|
+
path,
|
|
209
|
+
currentBranch: this.options.defaultBranch,
|
|
210
|
+
branches: [{
|
|
211
|
+
name: this.options.defaultBranch,
|
|
212
|
+
isRemote: false,
|
|
213
|
+
isCurrent: true,
|
|
214
|
+
commit: 'initial'
|
|
215
|
+
}],
|
|
216
|
+
commits: [],
|
|
217
|
+
status: new Map(),
|
|
218
|
+
isClean: true,
|
|
219
|
+
hasUncommitted: false
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
this.logInfo('Repository initialized', { path });
|
|
223
|
+
|
|
224
|
+
} catch (error) {
|
|
225
|
+
this.setError(`Failed to initialize repository: ${error}`);
|
|
226
|
+
} finally {
|
|
227
|
+
this.isLoading = false;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Load repository information
|
|
233
|
+
*/
|
|
234
|
+
async loadRepository(path: string): Promise<void> {
|
|
235
|
+
this.isLoading = true;
|
|
236
|
+
this.error = null;
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
// Simulate loading repository data
|
|
240
|
+
const repoData = await this.simulateGitOperation('load', { path });
|
|
241
|
+
|
|
242
|
+
this.repositoryInfo = repoData as GitRepositoryInfo;
|
|
243
|
+
this.options.repositoryPath = path;
|
|
244
|
+
|
|
245
|
+
// Update FileBrowser to show Git-enhanced items
|
|
246
|
+
await this.enhanceFileBrowserItems();
|
|
247
|
+
|
|
248
|
+
this.logInfo('Repository loaded', {
|
|
249
|
+
path,
|
|
250
|
+
branch: this.repositoryInfo.currentBranch,
|
|
251
|
+
commits: this.repositoryInfo.commits.length
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
} catch (error) {
|
|
255
|
+
this.setError(`Failed to load repository: ${error}`);
|
|
256
|
+
} finally {
|
|
257
|
+
this.isLoading = false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Switch to a different branch
|
|
263
|
+
*/
|
|
264
|
+
async switchBranch(branchName: string): Promise<void> {
|
|
265
|
+
if (!this.repositoryInfo) return;
|
|
266
|
+
|
|
267
|
+
this.isLoading = true;
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
// Simulate git checkout
|
|
271
|
+
await this.simulateGitOperation('checkout', { branch: branchName });
|
|
272
|
+
|
|
273
|
+
// Update repository info
|
|
274
|
+
this.repositoryInfo.currentBranch = branchName;
|
|
275
|
+
this.repositoryInfo.branches.forEach(branch => {
|
|
276
|
+
branch.isCurrent = branch.name === branchName;
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
this.selectedBranch = this.repositoryInfo.branches.find(b => b.name === branchName) || null;
|
|
280
|
+
|
|
281
|
+
// Refresh file browser to show branch-specific content
|
|
282
|
+
await this.enhanceFileBrowserItems();
|
|
283
|
+
|
|
284
|
+
this.logInfo('Switched to branch', { branchName });
|
|
285
|
+
|
|
286
|
+
} catch (error) {
|
|
287
|
+
this.setError(`Failed to switch branch: ${error}`);
|
|
288
|
+
} finally {
|
|
289
|
+
this.isLoading = false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Get Git status for a specific file
|
|
295
|
+
*/
|
|
296
|
+
getFileStatus(filePath: string): GitFileStatus | null {
|
|
297
|
+
if (!this.repositoryInfo) return null;
|
|
298
|
+
return this.repositoryInfo.status.get(filePath) || null;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Stage file changes
|
|
303
|
+
*/
|
|
304
|
+
async stageFile(filePath: string): Promise<void> {
|
|
305
|
+
if (!this.repositoryInfo) return;
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
await this.simulateGitOperation('add', { files: [filePath] });
|
|
309
|
+
|
|
310
|
+
// Update status
|
|
311
|
+
const status = this.repositoryInfo.status.get(filePath);
|
|
312
|
+
if (status) {
|
|
313
|
+
status.staged = true;
|
|
314
|
+
this.repositoryInfo.status.set(filePath, status);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
this.logInfo('File staged', { filePath });
|
|
318
|
+
|
|
319
|
+
} catch (error) {
|
|
320
|
+
this.setError(`Failed to stage file: ${error}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Commit staged changes
|
|
326
|
+
*/
|
|
327
|
+
async commitChanges(message: string): Promise<void> {
|
|
328
|
+
if (!this.repositoryInfo) return;
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
const commitHash = await this.simulateGitOperation('commit', { message });
|
|
332
|
+
|
|
333
|
+
// Create new commit
|
|
334
|
+
const newCommit: GitCommit = {
|
|
335
|
+
hash: commitHash as string,
|
|
336
|
+
message,
|
|
337
|
+
author: 'User',
|
|
338
|
+
date: new Date(),
|
|
339
|
+
parents: this.repositoryInfo.commits.length > 0 ? [this.repositoryInfo.commits[0]!.hash] : []
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// Update repository state
|
|
343
|
+
this.repositoryInfo.commits.unshift(newCommit);
|
|
344
|
+
this.repositoryInfo.isClean = true;
|
|
345
|
+
this.repositoryInfo.hasUncommitted = false;
|
|
346
|
+
|
|
347
|
+
// Clear staged status
|
|
348
|
+
this.repositoryInfo.status.forEach((status, path) => {
|
|
349
|
+
if (status.staged) {
|
|
350
|
+
status.staged = false;
|
|
351
|
+
this.repositoryInfo!.status.set(path, status);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
this.logInfo('Changes committed', { message, hash: commitHash });
|
|
356
|
+
|
|
357
|
+
} catch (error) {
|
|
358
|
+
this.setError(`Failed to commit changes: ${error}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Coordination helpers
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Enhance FileBrowser items with Git information
|
|
366
|
+
*/
|
|
367
|
+
private async enhanceFileBrowserItems(): Promise<void> {
|
|
368
|
+
// This would add Git status icons, branch information, etc.
|
|
369
|
+
// to the FileBrowser items through the coordination system
|
|
370
|
+
|
|
371
|
+
if (this.repositoryInfo) {
|
|
372
|
+
this.logInfo('Enhanced FileBrowser items with Git data');
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Load repository history for left panel
|
|
378
|
+
*/
|
|
379
|
+
private async loadRepositoryHistory(): Promise<void> {
|
|
380
|
+
if (!this.repositoryInfo) return;
|
|
381
|
+
|
|
382
|
+
// This would populate the left panel with commit history
|
|
383
|
+
this.logInfo('Loading repository history for left panel');
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Load branches for left panel
|
|
388
|
+
*/
|
|
389
|
+
private async loadBranches(): Promise<void> {
|
|
390
|
+
if (!this.repositoryInfo) return;
|
|
391
|
+
|
|
392
|
+
// This would populate the left panel with branch list
|
|
393
|
+
this.logInfo('Loading branches for left panel');
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Load working tree status for left panel
|
|
398
|
+
*/
|
|
399
|
+
private async loadWorkingTreeStatus(): Promise<void> {
|
|
400
|
+
if (!this.repositoryInfo) return;
|
|
401
|
+
|
|
402
|
+
// This would populate the left panel with file status
|
|
403
|
+
this.logInfo('Loading working tree status for left panel');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Refresh Git status for current directory
|
|
408
|
+
*/
|
|
409
|
+
private async refreshGitStatus(): Promise<void> {
|
|
410
|
+
if (!this.repositoryInfo) return;
|
|
411
|
+
|
|
412
|
+
try {
|
|
413
|
+
// Simulate git status check
|
|
414
|
+
const statusData = await this.simulateGitOperation('status', {});
|
|
415
|
+
|
|
416
|
+
// Update status cache
|
|
417
|
+
if (statusData && typeof statusData === 'object') {
|
|
418
|
+
const statusMap = statusData as Map<string, GitFileStatus>;
|
|
419
|
+
this.repositoryInfo.status = statusMap;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
} catch (error) {
|
|
423
|
+
this.logError('Failed to refresh Git status', error);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Utility methods
|
|
428
|
+
|
|
429
|
+
private isCommitReference(item: FileBrowserItem): boolean {
|
|
430
|
+
// Check if item represents a commit (e.g., in history view)
|
|
431
|
+
return item.name.match(/^[a-f0-9]{7,40}$/) !== null;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private isPathInRepository(path: string): boolean {
|
|
435
|
+
if (!this.repositoryInfo) return false;
|
|
436
|
+
return path.startsWith(this.repositoryInfo.path);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
private async loadCommitDetails(item: FileBrowserItem): Promise<void> {
|
|
440
|
+
if (!this.repositoryInfo) return;
|
|
441
|
+
|
|
442
|
+
// Find commit by hash prefix
|
|
443
|
+
const commit = this.repositoryInfo.commits.find(c =>
|
|
444
|
+
c.hash.startsWith(item.name)
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
if (commit) {
|
|
448
|
+
this.selectedCommit = commit;
|
|
449
|
+
this.logInfo('Selected commit', { hash: commit.hash, message: commit.message });
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
private async simulateGitOperation(operation: string, params: any): Promise<any> {
|
|
454
|
+
// Simulate Git operations with realistic delays
|
|
455
|
+
await new Promise(resolve => setTimeout(resolve, 100 + Math.random() * 200));
|
|
456
|
+
|
|
457
|
+
switch (operation) {
|
|
458
|
+
case 'init':
|
|
459
|
+
return { success: true };
|
|
460
|
+
|
|
461
|
+
case 'load':
|
|
462
|
+
return {
|
|
463
|
+
path: params.path,
|
|
464
|
+
currentBranch: 'main',
|
|
465
|
+
branches: [
|
|
466
|
+
{ name: 'main', isRemote: false, isCurrent: true, commit: 'abc123' },
|
|
467
|
+
{ name: 'develop', isRemote: false, isCurrent: false, commit: 'def456' }
|
|
468
|
+
],
|
|
469
|
+
commits: [
|
|
470
|
+
{
|
|
471
|
+
hash: 'abc123',
|
|
472
|
+
message: 'Initial commit',
|
|
473
|
+
author: 'User',
|
|
474
|
+
date: new Date(),
|
|
475
|
+
parents: []
|
|
476
|
+
}
|
|
477
|
+
],
|
|
478
|
+
status: new Map(),
|
|
479
|
+
isClean: true,
|
|
480
|
+
hasUncommitted: false
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
case 'checkout':
|
|
484
|
+
return { success: true };
|
|
485
|
+
|
|
486
|
+
case 'add':
|
|
487
|
+
return { success: true };
|
|
488
|
+
|
|
489
|
+
case 'commit':
|
|
490
|
+
return `commit_${Date.now()}`;
|
|
491
|
+
|
|
492
|
+
case 'status':
|
|
493
|
+
return new Map();
|
|
494
|
+
|
|
495
|
+
default:
|
|
496
|
+
throw new Error(`Unknown Git operation: ${operation}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
private setError(message: string): void {
|
|
501
|
+
this.error = message;
|
|
502
|
+
this.logError('GitBrowser error', new Error(message));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
private logInfo(message: string, data?: any): void {
|
|
506
|
+
this.fileBrowserModel.logger?.info(`[GitBrowserAdapter] ${message}`, data);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
private logError(message: string, error: any): void {
|
|
510
|
+
this.fileBrowserModel.logger?.error(`[GitBrowserAdapter] ${message}`, error);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Public API
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Get adapter statistics
|
|
517
|
+
*/
|
|
518
|
+
get stats() {
|
|
519
|
+
return {
|
|
520
|
+
isLoaded: !!this.repositoryInfo,
|
|
521
|
+
repositoryPath: this.repositoryInfo?.path || null,
|
|
522
|
+
currentBranch: this.repositoryInfo?.currentBranch || null,
|
|
523
|
+
commitCount: this.repositoryInfo?.commits.length || 0,
|
|
524
|
+
isClean: this.repositoryInfo?.isClean || true,
|
|
525
|
+
statusCacheSize: this.statusCache.size
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Cleanup
|
|
530
|
+
dispose(): void {
|
|
531
|
+
this.disposers.forEach(dispose => dispose());
|
|
532
|
+
this.disposers = [];
|
|
533
|
+
|
|
534
|
+
if (this.refreshTimer) {
|
|
535
|
+
clearInterval(this.refreshTimer);
|
|
536
|
+
this.refreshTimer = null;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
this.statusCache.clear();
|
|
540
|
+
this.repositoryInfo = null;
|
|
541
|
+
this.selectedCommit = null;
|
|
542
|
+
this.selectedBranch = null;
|
|
543
|
+
|
|
544
|
+
this.logInfo('GitBrowserAdapter disposed');
|
|
545
|
+
}
|
|
546
|
+
}
|