Skip to content

API support for Timeline view #84297

Open
@eamodio

Description

@eamodio

Goals

Add support for a unified file-based timeline view to be added to the Explorer sidebar which will track the active document (similar to the Outline view). This new view can be contributed by multiple sources, e.g. save/undo points, source control commits, test runs/failures, etc. Events from all sources will be aggregated into a single chronologically-ordered view.

Proposal

	export class TimelineItem {
		/**
		 * A date for when the timeline item occurred
		 */
		date: Date;

		/**
		 * A human-readable string describing the source of the timeline item. This can be used for filtering by sources so keep it consistent across timeline item types.
		 */
		source: string;

		/**
		 * Optional method to get the children of the timeline item (if any).
		 *
		 * @return Children of the timeline item (if any).
		 */
		getChildren?(): ProviderResult<TreeItem[]>;

		/**
		 * A human-readable string describing the timeline item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri).
		 */
		label: string;

		/**
		 * Optional id for the timeline item. See [TreeItem.id](#TreeItem.id) for more details.
		 */
		id?: string;

		/**
		 * The icon path or [ThemeIcon](#ThemeIcon) for the timeline item. See [TreeItem.iconPath](#TreeItem.iconPath) for more details.
		 */
		iconPath?: string | Uri | { light: string | Uri; dark: string | Uri } | ThemeIcon;

		/**
		 * A human readable string describing less prominent details of the timeline item. See [TreeItem.description](#TreeItem.description) for more details.
		 */
		description?: string | boolean;

		/**
		 * The [uri](#Uri) of the resource representing the timeline item (if any). See [TreeItem.resourceUri](#TreeItem.resourceUri) for more details.
		 */
		resourceUri?: Uri;

		/**
		 * The tooltip text when you hover over the timeline item.
		 */
		tooltip?: string | undefined;

		/**
		 * The [command](#Command) that should be executed when the timeline item is selected.
		 */
		command?: Command;

		/**
		 * [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the timeline item.
		 */
		collapsibleState?: TreeItemCollapsibleState;

		/**
		 * Context value of the timeline item.  See [TreeItem.contextValue](#TreeItem.contextValue) for more details.
		 */
		contextValue?: string;

		/**
		 * @param label A human-readable string describing the timeline item
		 * @param date A date for when the timeline item occurred
		 * @param source A human-readable string describing the source of the timeline item
		 * @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the timeline item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None)
		 */
		constructor(label: string, date: Date, source: string, collapsibleState?: TreeItemCollapsibleState);
	}

	export interface TimelimeAddEvent {

		/**
		 * An array of timeline items which have been added.
		 */
		readonly items: readonly TimelineItem[];

		/**
		 * The uri of the file to which the timeline items belong.
		 */
		readonly uri: Uri;
	}

	export interface TimelimeChangeEvent {

		/**
		 * The date after which the timeline has changed. If `undefined` the entire timeline will be reset.
		 */
		readonly since?: Date;

		/**
		 * The uri of the file to which the timeline changed.
		 */
		readonly uri: Uri;
	}

	export interface TimelineProvider {
		onDidAdd?: Event<TimelimeAddEvent>;
		onDidChange?: Event<TimelimeChangeEvent>;

		/**
		 * Provide [timeline items](#TimelineItem) for a [Uri](#Uri) after a particular date.
		 *
		 * @param uri The uri of the file to provide the timeline for.
		 * @param since A date after which timeline items should be provided.
		 * @param token A cancellation token.
		 * @return An array of timeline items or a thenable that resolves to such. The lack of a result
		 * can be signaled by returning `undefined`, `null`, or an empty array.
		 */
		provideTimeline(uri: Uri, since: Date, token: CancellationToken): ProviderResult<TimelineItem[]>;
	}

	export namespace workspace {
		/**
		 * Register a timeline provider.
		 *
		 * Multiple providers can be registered. In that case, providers are asked in
		 * parallel and the results are merged. A failing provider (rejected promise or exception) will
		 * not cause a failure of the whole operation.
		 *
		 * @param selector A selector that defines the documents this provider is applicable to.
		 * @param provider A timeline provider.
		 * @return A [disposable](#Disposable) that unregisters this provider when being disposed.
		 */
		export function registerTimelineProvider(selector: DocumentSelector, provider: TimelineProvider): Disposable;
	}

A timeline source (e.g. an extension) registers a TimelineProvider for a set of documents. VS Code will then call the all the registered TimelineProvider.provideTimeline callbacks (in parallel) when the active editor changes and matches those registrations. The results will be merged into a unified set ordered by the TimelineItem.date and displayed in a new File Timeline view in the Explorer sidebar.

A timeline provider can signal that new events have occurred via the onDidAdd event, providing the set of additional timeline items. A provider can also signal a refresh of its timeline items via the onDidChange event.

Questions & Challenges

API

  • Should we provides a model/signal that a timeline provider should not be cached or more accurately flushed when the file is no longer the active editor? Basically an alternative to sending events, just call provideTimeline again
  • Caching will be a bit challenging
    • How much do we keep around? And for how long?
  • Should the TimelimeChangeEvent event provide a way to signal that an individual item(s) should be updated?
  • Do we need a throttle on onDidAdd?
  • Need to be careful with ids for the tree items, since they can come from multiple extensions. Probably should ensure a prefix or something per provider for any provided ids (or not give control over the ids at all)

Behavior

  • Should tracking the active document be a toggle (like in GitLens where you can turn on/off tracking in the file history view on demand).
  • Should there be a way to trigger a specific file/folder/uri timelime to be shown (which would also turn off active file tracking) -- again similar to GitLens
  • Should the view support a refresh action that will drop timeline caches and re-request the timeline from all providers? (Hopefully we don't really need this)
  • Should we support filtering based on the source of the timeline items?
    /cc @jrieken

Refs: #83995

Metadata

Metadata

Assignees

Labels

apiapi-proposalfeature-requestRequest for new features or functionalityscmGeneral SCM compound issuestimelineTimeline view issuestree-viewsExtension tree view issues

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions