Change:
open a multifile diff reload window while the diff editor stores and loads it says that there are no changes yet <img width="1178" alt="Screenshot 2024-06-21 at 09 16 43" src=""
Thanks for filing! Briefly looked into it, but fixing it is a little bit more complex than I thought. The model creation is what takes a while, and during that time the multi file diff editor just has no model. It would be better if the model creation is immediate, but it has some property, that the editor could then show.

Discussion:
import { ContextKeyValue } from '../../../../platform/contextkey/common/contextkey.js'; export interface IMultiDiffEditorModel { <del> readonly documents: IValueWithChangeEvent<readonly RefCounted<IDocumentDiffItem>[]>; </del> <ins> readonly documents: IValueWithChangeEvent<readonly RefCounted<IDocumentDiffItem>[] | 'loading'>; </ins> readonly contextKeys?: Record<string, ContextKeyValue>; }

import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; export class MultiDiffEditorViewModel extends Disposable { <del> private readonly _documents: IObservable<readonly RefCounted<IDocumentDiffItem>[]> = observableFromValueWithChangeEvent(this.model, this.model.documents); </del> <ins> private readonly _documents: IObservable<readonly RefCounted<IDocumentDiffItem>[] | 'loading'> = observableFromValueWithChangeEvent(this.model, this.model.documents); private readonly _documentsArr = derived(this, reader => { const result = this._documents.read(reader); if (result === 'loading') { return []; } return result; }); public readonly isLoading = derived(this, reader => this._documents.read(reader) === 'loading'); </ins> public readonly items: IObservable<readonly DocumentDiffItemViewModel[]> = mapObservableArrayCached( this, <del> this._documents, </del> <ins> this._documentsArr, </ins> (d, store) => store.add(this._instantiationService.createInstance(DocumentDiffItemViewModel, d, this)) <del> ) .recomputeInitiallyAndOnChange(this._store); </del> <ins> ).recomputeInitiallyAndOnChange(this._store); </ins> public readonly focusedDiffItem = derived(this, reader => this.items.read(reader).find(i => i.isFocused.read(reader))); public readonly activeDiffItem = derivedObservableWithWritableCache<DocumentDiffItemViewModel | undefined>(this,

private readonly _elements = h('div.monaco-component.multiDiffEditor', {}, [ h('div', {}, [this._scrollableElement.getDomNode()]), <del> h('div.placeholder@placeholder', {}, [h('div', [localize('noChangedFiles', 'No Changed Files') as any])]), </del> <ins> h('div.placeholder@placeholder', {}, [h('div')]), </ins> ]); private readonly _sizeObserver = this._register(new ObservableElementSizeObserver(this._element, undefined));

this._sizeObserver.observe(dimension); })); <del> this._register(autorun((reader) => { /** @description Update widget dimension */ </del> <ins> const placeholderMessage = derived(reader => { </ins> const items = this._viewItems.read(reader); <del> this._elements.placeholder.classList.toggle('visible', items.length === 0); </del> <ins> if (items.length > 0) { return undefined; } const vm = this._viewModel.read(reader); return (!vm || vm.isLoading.read(reader)) ? localize('loading', 'Loading...') : localize('noChangedFiles', 'No Changed Files'); }); this._register(autorun((reader) => { const message = placeholderMessage.read(reader); this._elements.placeholder.innerText = message ?? ''; this._elements.placeholder.classList.toggle('visible', !!message); </ins> })); this._scrollableElements.content.style.position = 'relative';

return store.add(RefCounted.createOfNonDisposable(result, multiDiffItemStore, this)); }, i => JSON.stringify([i.modifiedUri?.toString(), i.originalUri?.toString()])); <del> const documents = observableValue<readonly RefCounted<IDocumentDiffItem>[]>('documents', []); </del> <ins> const documents = observableValue<readonly RefCounted<IDocumentDiffItem>[] | 'loading'>('documents', 'loading'); </ins> const updateDocuments = derived(async reader => { /** @description Update documents */

import { IMultiDiffSourceResolver, IMultiDiffSourceResolverService, IResolvedMultiDiffSource, MultiDiffEditorItem } from './multiDiffSourceResolverService.js'; import { ISCMRepository, ISCMResourceGroup, ISCMService } from '../../scm/common/scm.js'; import { IEditorService } from '../../../services/editor/common/editorService.js'; <ins> import { IActivityService, ProgressBadge } from '../../../services/activity/common/activity.js'; </ins> export class ScmMultiDiffSourceResolver implements IMultiDiffSourceResolver { private static readonly _scheme = 'scm-multi-diff-source';

constructor( @ISCMService private readonly _scmService: ISCMService, <ins> @IActivityService private readonly _activityService: IActivityService, </ins> ) { }

async resolveDiffSource(uri: URI): Promise<IResolvedMultiDiffSource> { const { repositoryUri, groupId } = ScmMultiDiffSourceResolver.parseUri(uri)!; const repository = await waitForState(observableFromEvent(this, this._scmService.onDidAddRepository, () => [...this._scmService.repositories].find(r => r.provider.rootUri?.toString() === repositoryUri.toString()))

repository.provider.onDidChangeResourceGroups, () => repository.provider.groups.find(g => g.id === groupId) )); <ins> const scmActivities = observableFromEvent( this._activityService.onDidChangeActivity, () => [...this._activityService.getViewContainerActivities('workbench.view.scm')], ); const scmViewHasNoProgressBadge = scmActivities.map(activities => !activities.some(a => a.badge instanceof ProgressBadge)); await waitForState(scmViewHasNoProgressBadge, v => v); </ins> return new ScmResolvedMultiDiffSource(group, repository); } }