Editor/LibraryImporterDock.cs
using Editor;
using System;
using System.IO;

namespace Editor.LibraryManager;

[Dock( "Editor", "Library Importer", "extension" )]
public class LibraryImporterDock : Widget
{
	internal Action<string> OnValueChanged;

	public LibraryImporterDock( Widget parent ) : base( parent )
	{
		Layout = Layout.Row();
		Layout.Margin = 4;
		Layout.Spacing = 4;

		FocusMode = FocusMode.TabOrClickOrWheel;
	}

	[EditorEvent.Hotload]
	void Rebuild()
	{
		Layout.Clear( true );
		Layout.Add( new InstalledLibrariesWidgetProxy( this ) );
	}

	static void CopyFolder( string sourceDir, string targetDir, string libraryName, string libraryFolder )
	{
		if ( sourceDir.Contains( "\\.", StringComparison.OrdinalIgnoreCase ) )
		{
			return;
		}

		System.IO.Directory.CreateDirectory( targetDir );

		foreach ( var file in Directory.GetFiles( sourceDir ) )
		{
			CopyAndProcessFile( file, targetDir, libraryName, libraryFolder );
		}

		foreach ( var directory in Directory.GetDirectories( sourceDir ) )
		{
			CopyFolder( directory, Path.Combine( targetDir, Path.GetFileName( directory ) ), libraryName, libraryFolder );
		}
	}

	static void CopyAndProcessFile( string file, string targetDir, string libraryName, string libraryFolder )
	{
		var targetname = Path.Combine( targetDir, Path.GetFileName( file ) );

		// Replace $ident with our ident in file name
		targetname = targetname.Replace( "$title", libraryName );
		targetname = targetname.Replace( "$ident", libraryFolder );

		if ( file.EndsWith( ".cs" ) || file.EndsWith( ".json" ) || file.EndsWith( ".sbproj" ) )
		{
			var txt = System.IO.File.ReadAllText( file );
			txt = txt.Replace( "$title", libraryName );
			txt = txt.Replace( "$ident", libraryFolder );
			System.IO.File.WriteAllText( targetname, txt );
		}
		else
		{
			File.Copy( file, targetname );
		}
	}

	[EditorEvent.Frame]
	public void Frame()
	{
		if ( SetContentHash( ContentHash, 0.5f ) )
		{
			Rebuild();
		}
	}

	int ContentHash() => HashCode.Combine( 0 );

}

public class InstalledLibrariesWidgetProxy : Widget
{
	Layout ContentLayout;

	public InstalledLibrariesWidgetProxy( LibraryImporterDock manager )
	{
		Layout = Layout.Row();

		var left = new LibraryListProxy( null )
		{
			ShowInstalled = true
		};

		Layout.Add( left, 1 );
		ContentLayout = Layout.AddColumn();

		left.OnLibrarySelected = ( library ) =>
		{
			ContentLayout.Clear( true );
			ContentLayout.Add( new LibraryDetailProxy( library ) );
		};

		manager.OnValueChanged = ( txt ) =>
		{
			left.Filter = txt;
		};
	}
}