mirror of
https://github.com/dnwSilver/tld.git
synced 2024-11-25 08:32:08 +00:00
Merge pull request #1 from dnwSilver/feature/command-line
Feature/command line
This commit is contained in:
commit
d01491f5cd
18
TLD.sln
18
TLD.sln
@ -2,6 +2,12 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI", "src\TUI\TUI.csproj", "{F92C03F7-2A65-4D0A-9736-13E749AF6903}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Engine.Tests", "tests\TUI.Engine.Tests\TUI.Engine.Tests.csproj", "{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Engine", "src\TUI.Engine\TUI.Engine.csproj", "{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Controls.Tests", "tests\TUI.Controls.Tests\TUI.Controls.Tests.csproj", "{59A0E843-8664-45B9-AD0C-52B8FE38986A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -16,5 +22,17 @@ Global
|
||||
{F92C03F7-2A65-4D0A-9736-13E749AF6903}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F92C03F7-2A65-4D0A-9736-13E749AF6903}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F92C03F7-2A65-4D0A-9736-13E749AF6903}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{59A0E843-8664-45B9-AD0C-52B8FE38986A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{59A0E843-8664-45B9-AD0C-52B8FE38986A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{59A0E843-8664-45B9-AD0C-52B8FE38986A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{59A0E843-8664-45B9-AD0C-52B8FE38986A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
76
docs/Features.txt
Normal file
76
docs/Features.txt
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
1 releases select prev
|
||||
2 competencies select next
|
||||
3 dependencies toggle head
|
||||
4 quit
|
||||
|
||||
too new Auth package
|
||||
so good WWW image
|
||||
be nice SEO site
|
||||
too old VCS api
|
||||
|
||||
releases Fact 2023
|
||||
releases Fact
|
||||
releases Planned
|
||||
releases Planned 2024-12-31 xfirm
|
||||
competencies
|
||||
growth zone
|
||||
dependencies
|
||||
tools
|
||||
|
||||
|
||||
|
||||
wait build
|
||||
reopen testing
|
||||
in progress done
|
||||
review cancel
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────── Planned release ─────────────────────────────────────────────────────────────────┐
|
||||
│ Planned application Tasks
|
||||
│ 2024-12-31 1d elk-site 4/11
|
||||
│ elk-site 2/5
|
||||
│ elk-site 22/22
|
||||
│ 2024-12-31 12d xfirm 4/12
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
show stopper wait build feature
|
||||
first of all reopen testing bug
|
||||
just do it in progress done
|
||||
doesn't rush review cancel
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────── checkperson-site ────────────────────────────────────────────────────────────────┐
|
||||
│ ELK-3628 Create new menu. Anna P. Petrov A. Ivanov I.
|
||||
│ XF-12 Change input hover. Alex K. Ivanov I. Petrov A., Petrov B.
|
||||
│ ELK-3628 Crete new project with menu, profile, issues and # Anna P. Ivanov I. Petrov A., Petrov B.
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
publish
|
||||
release
|
||||
hotfix
|
||||
release candidate
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────── Actual releases 2023 ─────────────────────────────────────────────────────────┐
|
||||
│ Jan Feb Mar Apl May Jun Jul Aug Sep Oct Nov Dec
|
||||
│ ├─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
|
||||
│ LK
|
||||
│ CP
|
||||
│ RR
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
|
||||
|
||||
GA4 Jaeger Fallback Screenshots Connected Auth
|
||||
Я YM Prometheus Renovate End2End Disconnected WWW
|
||||
Husky Sentry Lighthouse Unit Not implemented SEO
|
||||
Probs Grafana Kibana Coverage No need
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────── Tools ──────────────────────────────────┐
|
||||
│ Я
|
||||
│ elk-site
|
||||
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
51
docs/RENDER.md
Normal file
51
docs/RENDER.md
Normal file
@ -0,0 +1,51 @@
|
||||
# RENDER
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
%% Application layer
|
||||
class ViewPort{
|
||||
+ GetCanvas()
|
||||
+ string: Content
|
||||
}
|
||||
|
||||
%% Хранит данные
|
||||
class Store {
|
||||
Reload()
|
||||
}
|
||||
|
||||
%% Хранит разметку
|
||||
class View {
|
||||
Store
|
||||
SetWidgets()
|
||||
SetCanvas()
|
||||
Render()
|
||||
}
|
||||
|
||||
%% Подгатавливает текст
|
||||
class Painter {
|
||||
+ SetGrid()
|
||||
+ SetView()
|
||||
}
|
||||
|
||||
%% Composition
|
||||
class Widget {
|
||||
+ State
|
||||
~ Bind()
|
||||
~ Render()
|
||||
}
|
||||
|
||||
class WidgetState
|
||||
<<Enum>> WidgetState
|
||||
WidgetState : Loading
|
||||
WidgetState : Mounted
|
||||
WidgetState : BindingError
|
||||
WidgetState : RenderError
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Change_Store --> Binding_Widgets
|
||||
Binding_Widgets --> Render_Widgets
|
||||
Render_Widgets --> Create_View
|
||||
Create_View --> Fill_View_Port
|
||||
```
|
3
src/TUI.Engine/Attributes/Alignments/Alignment.cs
Normal file
3
src/TUI.Engine/Attributes/Alignments/Alignment.cs
Normal file
@ -0,0 +1,3 @@
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public record Alignment(Horizontal Horizontal, Vertical Vertical);
|
8
src/TUI.Engine/Attributes/Alignments/Horizontal.cs
Normal file
8
src/TUI.Engine/Attributes/Alignments/Horizontal.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public enum Horizontal
|
||||
{
|
||||
Left = 0,
|
||||
Center = 1,
|
||||
Right = 2,
|
||||
}
|
10
src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs
Normal file
10
src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public interface IWithAlignment
|
||||
{
|
||||
internal Alignment Alignment { get; }
|
||||
|
||||
void SetAlignment(Vertical vertical);
|
||||
|
||||
void SetAlignment(Horizontal horizontal);
|
||||
}
|
8
src/TUI.Engine/Attributes/Alignments/Vertical.cs
Normal file
8
src/TUI.Engine/Attributes/Alignments/Vertical.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public enum Vertical
|
||||
{
|
||||
Top,
|
||||
Center,
|
||||
Bottom,
|
||||
}
|
10
src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs
Normal file
10
src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace TUI.Engine.Attributes.Orientations;
|
||||
|
||||
public interface IWithOrientation
|
||||
{
|
||||
internal Orientation Orientation { get; }
|
||||
|
||||
public void SetOrientationHorizontal();
|
||||
|
||||
public void SetOrientationVertical();
|
||||
}
|
7
src/TUI.Engine/Attributes/Orientations/Orientation.cs
Normal file
7
src/TUI.Engine/Attributes/Orientations/Orientation.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace TUI.Engine.Attributes.Orientations;
|
||||
|
||||
public enum Orientation
|
||||
{
|
||||
Horizontal,
|
||||
Vertical,
|
||||
}
|
14
src/TUI.Engine/Attributes/Paddings/IWithPadding.cs
Normal file
14
src/TUI.Engine/Attributes/Paddings/IWithPadding.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Attributes.Paddings;
|
||||
|
||||
public interface IWithPadding
|
||||
{
|
||||
Padding Padding { get; }
|
||||
|
||||
void SetPadding(Level level);
|
||||
void SetPaddingLeft(Level level);
|
||||
void SetPaddingTop(Level level);
|
||||
void SetPaddingBottom(Level level);
|
||||
void SetPaddingRight(Level level);
|
||||
}
|
15
src/TUI.Engine/Attributes/Paddings/Padding.cs
Normal file
15
src/TUI.Engine/Attributes/Paddings/Padding.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Attributes.Paddings;
|
||||
|
||||
public record Padding(
|
||||
Level Left = Level.None,
|
||||
Level Top = Level.None,
|
||||
Level Right = Level.None,
|
||||
Level Bottom = Level.None
|
||||
)
|
||||
{
|
||||
public Padding(Level padding) : this(Left: padding, Top: padding, Right: padding, Bottom: padding)
|
||||
{
|
||||
}
|
||||
}
|
16
src/TUI.Engine/Attributes/Resizings/IResizable.cs
Normal file
16
src/TUI.Engine/Attributes/Resizings/IResizable.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
|
||||
namespace TUI.Engine.Attributes.Resizings;
|
||||
|
||||
public interface IResizable
|
||||
{
|
||||
internal Resizing ResizingHorizontal { get; }
|
||||
|
||||
internal Resizing ResizingVertical { get; }
|
||||
|
||||
internal Size GetFixedSize();
|
||||
|
||||
void SetAdaptive(Orientation orientation);
|
||||
|
||||
void SetFixed(Orientation orientation, int value);
|
||||
}
|
7
src/TUI.Engine/Attributes/Resizings/Resizing.cs
Normal file
7
src/TUI.Engine/Attributes/Resizings/Resizing.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace TUI.Engine.Attributes.Resizings;
|
||||
|
||||
public enum Resizing
|
||||
{
|
||||
Adaptive,
|
||||
Fixed
|
||||
}
|
60
src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs
Normal file
60
src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Containers;
|
||||
|
||||
namespace TUI.Engine.Attributes.Resizings;
|
||||
|
||||
internal static class ResizingExtensions
|
||||
{
|
||||
internal static int GetHeight(this IResizable node, IContainer container, int maxHeight, int nodeIndex)
|
||||
{
|
||||
if (node.ResizingVertical == Resizing.Fixed)
|
||||
{
|
||||
return node.GetFixedSize().Height;
|
||||
}
|
||||
|
||||
if (container.Orientation == Orientation.Horizontal)
|
||||
{
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
var fixedNodes = container.GetFixedNodes().ToArray();
|
||||
var absoluteNodes = container.GetAbsoluteNodes().ToArray();
|
||||
|
||||
var fixedHeight = fixedNodes.Sum(s => s.GetFixedSize().Height);
|
||||
var allowableHeight = maxHeight - fixedHeight;
|
||||
|
||||
var allowableCount = container.GetNodes().Count - fixedNodes.Length - absoluteNodes.Length;
|
||||
var nodeHeight = (allowableHeight / allowableCount).Min(1);
|
||||
var nodeNumber = nodeIndex + 1 - container.GetFixedNodes(nodeIndex).Count() -
|
||||
container.GetAbsoluteNodes(nodeIndex).Count();
|
||||
|
||||
if (allowableHeight - nodeNumber * nodeHeight < nodeHeight)
|
||||
{
|
||||
return allowableHeight + nodeHeight - nodeNumber * nodeHeight;
|
||||
}
|
||||
|
||||
return nodeHeight;
|
||||
}
|
||||
|
||||
internal static int GetWidth(this IResizable node, IContainer container, int maxWidth)
|
||||
{
|
||||
if (node.ResizingHorizontal == Resizing.Fixed)
|
||||
{
|
||||
return node.GetFixedSize().Width;
|
||||
}
|
||||
|
||||
if (container.Orientation == Orientation.Vertical)
|
||||
{
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
var fixedNodes = container
|
||||
.GetNodes()
|
||||
.Where(n => n.ResizingHorizontal == Resizing.Fixed).ToArray();
|
||||
|
||||
var allowableWidth = maxWidth - fixedNodes.Sum(s => s.GetFixedSize().Width);
|
||||
var allowableCount = container.GetNodes().Count - fixedNodes.Length;
|
||||
|
||||
return allowableWidth / allowableCount;
|
||||
}
|
||||
}
|
10
src/TUI.Engine/Attributes/Size.cs
Normal file
10
src/TUI.Engine/Attributes/Size.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Attributes;
|
||||
|
||||
public readonly record struct Size(int Width, int Height)
|
||||
{
|
||||
public static Size operator -(Size a, Position b) => new(a.Width - b.Left, a.Height - b.Top);
|
||||
|
||||
public override string ToString() => $"W[{Width}] H[{Height}]";
|
||||
}
|
56
src/TUI.Engine/Components/ComponentBase.cs
Normal file
56
src/TUI.Engine/Components/ComponentBase.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Paddings;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public abstract class ComponentBase : NodeBase, IComponent
|
||||
{
|
||||
protected abstract Sketch DrawComponent(Size minSize);
|
||||
|
||||
public bool IsRelative { get; private set; } = true;
|
||||
|
||||
public void SetRelative()
|
||||
{
|
||||
IsRelative = true;
|
||||
}
|
||||
|
||||
public void SetAbsolute()
|
||||
{
|
||||
IsRelative = false;
|
||||
}
|
||||
|
||||
Sketch IComponent.MakeSketch(Size minSize) => DrawComponent(minSize);
|
||||
|
||||
#region Alignments
|
||||
|
||||
Alignment IWithAlignment.Alignment => Alignment;
|
||||
|
||||
internal Alignment Alignment { get; private set; } = new(Defaults.HorizontalAlignment, Defaults.VerticalAlignment);
|
||||
|
||||
public void SetAlignment(Vertical vertical) => Alignment = Alignment with { Vertical = vertical };
|
||||
|
||||
public void SetAlignment(Horizontal horizontal) => Alignment = Alignment with { Horizontal = horizontal };
|
||||
|
||||
#endregion
|
||||
|
||||
#region Paddings
|
||||
|
||||
Padding IWithPadding.Padding => Padding;
|
||||
|
||||
internal Padding Padding { get; private set; } = new(Defaults.Padding);
|
||||
|
||||
public void SetPadding(Level level) => Padding = new Padding(level);
|
||||
|
||||
public void SetPaddingTop(Level level) => Padding = Padding with { Top = level };
|
||||
|
||||
public void SetPaddingRight(Level level) => Padding = Padding with { Right = level };
|
||||
|
||||
public void SetPaddingBottom(Level level) => Padding = Padding with { Bottom = level };
|
||||
|
||||
public void SetPaddingLeft(Level level) => Padding = Padding with { Left = level };
|
||||
|
||||
#endregion
|
||||
}
|
40
src/TUI.Engine/Components/ComponentExtensions.cs
Normal file
40
src/TUI.Engine/Components/ComponentExtensions.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
internal static class ComponentExtensions
|
||||
{
|
||||
internal static Position CorrectContentPosition(this IComponent component,
|
||||
Position pencil,
|
||||
Size maxSize,
|
||||
Size sketchSize)
|
||||
{
|
||||
var padding = component.Padding;
|
||||
var alignment = component.Alignment;
|
||||
var alignmentCompensationLeft = GetAlignmentCompensationLeft(alignment.Horizontal, maxSize, sketchSize);
|
||||
var alignmentCompensationTop = GetAlignmentCompensationTop(alignment.Vertical, maxSize, sketchSize);
|
||||
var left = pencil.Left + (int)padding.Left + alignmentCompensationLeft;
|
||||
var top = pencil.Top + (int)padding.Top + alignmentCompensationTop;
|
||||
return new Position(left, top);
|
||||
}
|
||||
|
||||
private static int GetAlignmentCompensationLeft(Horizontal alignment, Size maxSize, Size sketchSize) =>
|
||||
alignment switch
|
||||
{
|
||||
Horizontal.Left => 0,
|
||||
Horizontal.Center => (maxSize.Width - sketchSize.Width) / 2,
|
||||
Horizontal.Right => maxSize.Width - sketchSize.Width,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
private static int GetAlignmentCompensationTop(Vertical alignment, Size maxSize, Size sketchSize) =>
|
||||
alignment switch
|
||||
{
|
||||
Vertical.Top => 0,
|
||||
Vertical.Center => (maxSize.Height - sketchSize.Height) / 2,
|
||||
Vertical.Bottom => maxSize.Height - sketchSize.Height,
|
||||
_ => 0
|
||||
};
|
||||
}
|
17
src/TUI.Engine/Components/IComponent.cs
Normal file
17
src/TUI.Engine/Components/IComponent.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Paddings;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public interface IComponent : INode, IWithAlignment, IWithPadding
|
||||
{
|
||||
internal bool IsRelative { get; }
|
||||
|
||||
public void SetRelative();
|
||||
|
||||
public void SetAbsolute();
|
||||
|
||||
internal Sketch MakeSketch(Size minSize);
|
||||
}
|
31
src/TUI.Engine/Components/Sketch.cs
Normal file
31
src/TUI.Engine/Components/Sketch.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System.Text;
|
||||
using TUI.Engine.Attributes;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public sealed class Sketch : IEnumerable<string>
|
||||
{
|
||||
private IEnumerable<string> ContentRows { get; }
|
||||
|
||||
public Sketch(string content) => ContentRows = content.Split(Symbols.LineBreak);
|
||||
|
||||
public Sketch(StringBuilder builder) => ContentRows = builder.ToString().Split(Symbols.LineBreak);
|
||||
|
||||
public IEnumerator<string> GetEnumerator() => ContentRows.GetEnumerator();
|
||||
|
||||
public IEnumerable<string> Crop(Size maxSize) => ContentRows
|
||||
.Select(row => maxSize.Width < row.GetWidth() ? row[..maxSize.Width] : row)
|
||||
.Take(maxSize.Height)
|
||||
.ToArray();
|
||||
|
||||
public Size GetSize()
|
||||
{
|
||||
var width = ContentRows.Select(row => row.GetWidth()).DefaultIfEmpty(0).Max();
|
||||
var height = ContentRows.Count();
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
public override string ToString() => string.Join(Symbols.LineBreak, ContentRows);
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
27
src/TUI.Engine/Components/StaticComponentBase.cs
Normal file
27
src/TUI.Engine/Components/StaticComponentBase.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Text;
|
||||
using TUI.Engine.Attributes;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public abstract class StaticComponentBase : ComponentBase
|
||||
{
|
||||
private Sketch? _cache;
|
||||
|
||||
protected abstract void RenderWithCache(StringBuilder builder);
|
||||
|
||||
protected override Sketch DrawComponent(Size sketchMinSize)
|
||||
{
|
||||
if (_cache is not null)
|
||||
{
|
||||
return _cache;
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
RenderWithCache(builder);
|
||||
|
||||
_cache = new Sketch(builder.ToString());
|
||||
|
||||
return _cache;
|
||||
}
|
||||
}
|
24
src/TUI.Engine/Containers/ContainerBase.cs
Normal file
24
src/TUI.Engine/Containers/ContainerBase.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Containers;
|
||||
|
||||
public abstract class ContainerBase : NodeBase, IContainer
|
||||
{
|
||||
private Orientation _orientation = Defaults.Orientation;
|
||||
|
||||
Orientation IWithOrientation.Orientation => _orientation;
|
||||
|
||||
public void SetOrientationHorizontal()
|
||||
{
|
||||
_orientation = Orientation.Horizontal;
|
||||
}
|
||||
|
||||
public void SetOrientationVertical()
|
||||
{
|
||||
_orientation = Orientation.Vertical;
|
||||
}
|
||||
|
||||
public abstract Nodes.Nodes GetNodes();
|
||||
}
|
42
src/TUI.Engine/Containers/ContainerExtensions.cs
Normal file
42
src/TUI.Engine/Containers/ContainerExtensions.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Containers;
|
||||
|
||||
internal static class ContainerExtensions
|
||||
{
|
||||
private static readonly Func<INode, bool> AbsoluteNodes = node => node is IComponent { IsRelative: false };
|
||||
|
||||
private static readonly Func<INode, bool> FixedNodes = node => node.ResizingVertical == Resizing.Fixed;
|
||||
|
||||
internal static IEnumerable<INode> GetAbsoluteNodes(this IContainer container, int? takeNodeNumber = null)
|
||||
{
|
||||
if (takeNodeNumber is not null)
|
||||
{
|
||||
return container
|
||||
.GetNodes()
|
||||
.Take(takeNodeNumber.Value + 1)
|
||||
.Where(AbsoluteNodes);
|
||||
}
|
||||
|
||||
return container
|
||||
.GetNodes()
|
||||
.Where(AbsoluteNodes);
|
||||
}
|
||||
|
||||
internal static IEnumerable<INode> GetFixedNodes(this IContainer container, int? takeNodeNumber = null)
|
||||
{
|
||||
if (takeNodeNumber is not null)
|
||||
{
|
||||
return container
|
||||
.GetNodes()
|
||||
.Take(takeNodeNumber.Value + 1)
|
||||
.Where(FixedNodes);
|
||||
}
|
||||
|
||||
return container
|
||||
.GetNodes()
|
||||
.Where(FixedNodes);
|
||||
}
|
||||
}
|
9
src/TUI.Engine/Containers/IContainer.cs
Normal file
9
src/TUI.Engine/Containers/IContainer.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Containers;
|
||||
|
||||
public interface IContainer : INode, IWithOrientation
|
||||
{
|
||||
public Nodes.Nodes GetNodes();
|
||||
}
|
51
src/TUI.Engine/Extensions.cs
Normal file
51
src/TUI.Engine/Extensions.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TUI.Engine;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static int Max(this int value, int maxValue)
|
||||
{
|
||||
return value <= maxValue ? value : maxValue;
|
||||
}
|
||||
|
||||
public static int Min(this int value, int minValue)
|
||||
{
|
||||
return value > minValue ? value : minValue;
|
||||
}
|
||||
|
||||
public static bool Have(this IEnumerable<string> array, string findValue)
|
||||
{
|
||||
return array.Any(item => item == findValue);
|
||||
}
|
||||
|
||||
public static string Repeat(this string value, int count)
|
||||
{
|
||||
return count < 0 ? string.Empty : new StringBuilder(value.Length * count).Insert(0, value, count).ToString();
|
||||
}
|
||||
|
||||
public static string RemoveColors(this string text)
|
||||
{
|
||||
return Regex.Replace(text, @"\S\[(\d{0,3}[;m]_?){0,5}", "");
|
||||
}
|
||||
|
||||
public static int GetWidth(this string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return 0;
|
||||
|
||||
var clearText = text.RemoveColors();
|
||||
var stringInfo = new StringInfo(clearText);
|
||||
return stringInfo.LengthInTextElements;
|
||||
}
|
||||
|
||||
public static Version ToVersion(this string textVersion)
|
||||
{
|
||||
var version = textVersion.Replace("^", "").Replace("~", "").Split(".");
|
||||
var major = Convert.ToInt32(version[0]);
|
||||
var minor = Convert.ToInt32(version[1]);
|
||||
var patch = Convert.ToInt32(version[2].Split('-')[0]);
|
||||
return new Version(major, minor, patch);
|
||||
}
|
||||
}
|
55
src/TUI.Engine/Helper.cs
Normal file
55
src/TUI.Engine/Helper.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Pastel;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
[assembly: InternalsVisibleTo("TUI.Engine.Tests", AllInternalsVisible = true)]
|
||||
|
||||
namespace TUI.Engine;
|
||||
|
||||
public static class Helper
|
||||
{
|
||||
private static readonly Queue<ConsoleColor> Colors = new();
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
Colors.Enqueue(ConsoleColor.DarkYellow);
|
||||
Colors.Enqueue(ConsoleColor.DarkMagenta);
|
||||
Colors.Enqueue(ConsoleColor.DarkGreen);
|
||||
Colors.Enqueue(ConsoleColor.DarkCyan);
|
||||
Colors.Enqueue(ConsoleColor.DarkBlue);
|
||||
Colors.Enqueue(ConsoleColor.DarkRed);
|
||||
Colors.Enqueue(ConsoleColor.Cyan);
|
||||
Colors.Enqueue(ConsoleColor.Yellow);
|
||||
}
|
||||
|
||||
public static void ShowBackground(Position position, Size size)
|
||||
{
|
||||
return;
|
||||
if (!Colors.Any())
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
var color = Colors.Dequeue();
|
||||
|
||||
var top = position.Top;
|
||||
var height = 0;
|
||||
|
||||
while (height < size.Height)
|
||||
{
|
||||
var left = position.Left;
|
||||
var width = 0;
|
||||
while (width < size.Width)
|
||||
{
|
||||
Console.SetCursorPosition(left, top);
|
||||
Console.Write(Symbols.Space.ToString().PastelBg(color));
|
||||
width++;
|
||||
left++;
|
||||
}
|
||||
|
||||
height++;
|
||||
top++;
|
||||
}
|
||||
}
|
||||
}
|
15
src/TUI.Engine/Nodes/INode.cs
Normal file
15
src/TUI.Engine/Nodes/INode.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
||||
public interface INode : IResizable
|
||||
{
|
||||
DrawContext DrawContext { get; set; }
|
||||
StyleContext StyleContext { get; set; }
|
||||
}
|
||||
|
||||
public record DrawContext(ICanvas Canvas, Position Pencil, Size MaxSize);
|
||||
|
||||
public record StyleContext(string? Foreground, string? Background = null);
|
62
src/TUI.Engine/Nodes/NodeBase.cs
Normal file
62
src/TUI.Engine/Nodes/NodeBase.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
||||
public abstract class NodeBase : INode
|
||||
{
|
||||
private int _fixedWidth;
|
||||
private int _fixedHeight;
|
||||
|
||||
Size IResizable.GetFixedSize() => new(_fixedWidth, _fixedHeight);
|
||||
|
||||
#region Resizing
|
||||
|
||||
private Resizing ResizingHorizontal { get; set; } = Defaults.HorizontalResizing;
|
||||
|
||||
Resizing IResizable.ResizingHorizontal => ResizingHorizontal;
|
||||
|
||||
private Resizing ResizingVertical { get; set; } = Defaults.VerticalResizing;
|
||||
|
||||
Resizing IResizable.ResizingVertical => ResizingVertical;
|
||||
|
||||
public void SetAdaptive(Orientation orientation)
|
||||
{
|
||||
switch (orientation)
|
||||
{
|
||||
case Orientation.Horizontal:
|
||||
ResizingHorizontal = Resizing.Adaptive;
|
||||
break;
|
||||
case Orientation.Vertical:
|
||||
ResizingVertical = Resizing.Adaptive;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFixed(Orientation orientation, int value)
|
||||
{
|
||||
switch (orientation)
|
||||
{
|
||||
case Orientation.Horizontal:
|
||||
ResizingHorizontal = Resizing.Fixed;
|
||||
_fixedWidth = value;
|
||||
break;
|
||||
case Orientation.Vertical:
|
||||
ResizingVertical = Resizing.Fixed;
|
||||
_fixedHeight = value;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Resizing
|
||||
|
||||
public DrawContext? DrawContext { get; set; }
|
||||
|
||||
public StyleContext? StyleContext { get; set; }
|
||||
}
|
15
src/TUI.Engine/Nodes/NodeExtensions.cs
Normal file
15
src/TUI.Engine/Nodes/NodeExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Containers;
|
||||
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
||||
internal static class NodeExtensions
|
||||
{
|
||||
internal static Size GetSize(this INode node, IContainer parentContainer, int nodeNumber, Size allowableSize)
|
||||
{
|
||||
var width = node.GetWidth(parentContainer, allowableSize.Width);
|
||||
var height = node.GetHeight(parentContainer, allowableSize.Height, nodeNumber);
|
||||
return new Size(width, height);
|
||||
}
|
||||
}
|
5
src/TUI.Engine/Nodes/Nodes.cs
Normal file
5
src/TUI.Engine/Nodes/Nodes.cs
Normal file
@ -0,0 +1,5 @@
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
||||
public class Nodes : List<INode>
|
||||
{
|
||||
}
|
8
src/TUI.Engine/Nodes/Position.cs
Normal file
8
src/TUI.Engine/Nodes/Position.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
||||
public record Position(int Left, int Top)
|
||||
{
|
||||
public static readonly Position Default = new(0, 0);
|
||||
|
||||
public override string ToString() => $"L[{Left}] T[{Top}]";
|
||||
}
|
35
src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs
Normal file
35
src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering.Canvas;
|
||||
|
||||
public class ConsoleCanvas : ICanvas
|
||||
{
|
||||
private readonly DrawCraftsman _drawCraftsman;
|
||||
|
||||
public Size Size { get; } = new(Console.WindowWidth, Console.WindowHeight);
|
||||
|
||||
public ConsoleCanvas()
|
||||
{
|
||||
var componentCraftsman = new ComponentCraftsman(this);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
_drawCraftsman = new DrawCraftsman(componentCraftsman, containerCraftsman);
|
||||
}
|
||||
|
||||
public void SetPencil(Position pencilPosition)
|
||||
{
|
||||
Console.SetCursorPosition(pencilPosition.Left, pencilPosition.Top);
|
||||
}
|
||||
|
||||
public void Paint(string value) => Console.Write(value);
|
||||
|
||||
public void Draw(INode node)
|
||||
{
|
||||
_drawCraftsman.Draw(node, Position.Default, Size);
|
||||
}
|
||||
|
||||
public void Draw(INode node, Position pencil, Size maxSize)
|
||||
{
|
||||
_drawCraftsman.Draw(node, pencil, maxSize);
|
||||
}
|
||||
}
|
17
src/TUI.Engine/Rendering/Canvas/ICanvas.cs
Normal file
17
src/TUI.Engine/Rendering/Canvas/ICanvas.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering.Canvas;
|
||||
|
||||
public interface ICanvas
|
||||
{
|
||||
Size Size { get; }
|
||||
|
||||
void SetPencil(Position pencilPosition);
|
||||
|
||||
void Paint(string value);
|
||||
|
||||
void Draw(INode node);
|
||||
|
||||
void Draw(INode node, Position pencil, Size maxSize);
|
||||
}
|
42
src/TUI.Engine/Rendering/ComponentCraftsman.cs
Normal file
42
src/TUI.Engine/Rendering/ComponentCraftsman.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using Pastel;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
internal sealed class ComponentCraftsman : CraftsmanBase, IDrawable<IComponent>
|
||||
{
|
||||
private readonly ICanvas _canvas;
|
||||
|
||||
public ComponentCraftsman(ICanvas canvas)
|
||||
{
|
||||
_canvas = canvas;
|
||||
}
|
||||
|
||||
public Size Draw(IComponent component, Position pencil, Size maxSize)
|
||||
{
|
||||
var sketch = component.MakeSketch(maxSize);
|
||||
var sketchSize = sketch.GetSize();
|
||||
|
||||
var correctedPencil = component.CorrectContentPosition(pencil, maxSize, sketchSize);
|
||||
|
||||
Debug(pencil, maxSize);
|
||||
|
||||
foreach (var line in sketch.Crop(maxSize))
|
||||
{
|
||||
component.DrawContext = new DrawContext(_canvas, pencil, maxSize);
|
||||
|
||||
_canvas.SetPencil(correctedPencil);
|
||||
_canvas.Paint(component.StyleContext is not null
|
||||
? line.RemoveColors().Pastel(component.StyleContext.Foreground)
|
||||
: line);
|
||||
|
||||
|
||||
correctedPencil = correctedPencil with { Top = correctedPencil.Top + 1 };
|
||||
}
|
||||
|
||||
return sketchSize;
|
||||
}
|
||||
}
|
86
src/TUI.Engine/Rendering/ContainerCraftsman.cs
Normal file
86
src/TUI.Engine/Rendering/ContainerCraftsman.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
internal sealed class ContainerCraftsman : CraftsmanBase, IDrawable<IContainer>
|
||||
{
|
||||
private readonly IDrawable<IComponent> _componentCraftsman;
|
||||
|
||||
public ContainerCraftsman(IDrawable<IComponent> componentCraftsman)
|
||||
{
|
||||
_componentCraftsman = componentCraftsman;
|
||||
}
|
||||
|
||||
public Size Draw(IContainer container, Position pencil, Size maxSize)
|
||||
{
|
||||
var nodeNumber = 0;
|
||||
var nextNodePosition = pencil;
|
||||
var nodes = container.GetNodes();
|
||||
|
||||
Debug(nextNodePosition, maxSize);
|
||||
|
||||
while (nodeNumber < nodes.Count)
|
||||
{
|
||||
var node = nodes[nodeNumber];
|
||||
var nodeSize = node.GetSize(container, nodeNumber, maxSize);
|
||||
|
||||
nextNodePosition = DrawNode(node, container, nextNodePosition, nodeSize);
|
||||
nodeNumber++;
|
||||
}
|
||||
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
private Position DrawNode(INode node, IContainer container, Position nodePosition, Size maxSize)
|
||||
{
|
||||
switch (node)
|
||||
{
|
||||
case IContainer childContainer:
|
||||
var containerSize = Draw(childContainer, nodePosition, maxSize);
|
||||
return GetNextNodePosition(container, containerSize, nodePosition);
|
||||
case IComponent childComponent:
|
||||
var componentSize = _componentCraftsman.Draw(childComponent, nodePosition, maxSize);
|
||||
return childComponent.IsRelative
|
||||
? GetNextNodePosition(container, maxSize, nodePosition, componentSize)
|
||||
: nodePosition;
|
||||
default:
|
||||
throw new InvalidCastException();
|
||||
}
|
||||
}
|
||||
|
||||
private static Position GetNextNodePosition(
|
||||
IContainer container,
|
||||
Size defaultSize,
|
||||
Position position,
|
||||
Size? componentSize = null)
|
||||
{
|
||||
switch (container.Orientation)
|
||||
{
|
||||
case Orientation.Horizontal:
|
||||
var componentWidth = container.ResizingHorizontal switch
|
||||
{
|
||||
Resizing.Adaptive => defaultSize.Width,
|
||||
Resizing.Fixed => componentSize?.Width.Max(container.GetFixedSize().Width) ??
|
||||
container.GetFixedSize().Width,
|
||||
_ => 0
|
||||
};
|
||||
return position with { Left = position.Left + componentWidth };
|
||||
case Orientation.Vertical:
|
||||
var componentHeight = container.ResizingVertical switch
|
||||
{
|
||||
Resizing.Adaptive => defaultSize.Height,
|
||||
Resizing.Fixed => componentSize?.Height.Max(container.GetFixedSize().Height) ??
|
||||
container.GetFixedSize().Height,
|
||||
_ => 0
|
||||
};
|
||||
return position with { Top = position.Top + componentHeight };
|
||||
default:
|
||||
throw new InvalidCastException();
|
||||
}
|
||||
}
|
||||
}
|
14
src/TUI.Engine/Rendering/CraftsmanBase.cs
Normal file
14
src/TUI.Engine/Rendering/CraftsmanBase.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Diagnostics;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
public abstract class CraftsmanBase
|
||||
{
|
||||
protected void Debug(Position pencilPosition, Size allowableSize)
|
||||
{
|
||||
Debugger.Log(0, "Draw", $"{pencilPosition}{GetType().Name}.\n");
|
||||
Helper.ShowBackground(pencilPosition, allowableSize);
|
||||
}
|
||||
}
|
9
src/TUI.Engine/Rendering/IDrawable.cs
Normal file
9
src/TUI.Engine/Rendering/IDrawable.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
public interface IDrawable<in TItem> where TItem : INode
|
||||
{
|
||||
Size Draw(TItem item, Position pencil, Size maxSize);
|
||||
}
|
28
src/TUI.Engine/Rendering/NodeCraftsman.cs
Normal file
28
src/TUI.Engine/Rendering/NodeCraftsman.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
internal sealed class DrawCraftsman : IDrawable<INode>
|
||||
{
|
||||
private readonly IDrawable<IComponent> _componentCraftsman;
|
||||
private readonly IDrawable<IContainer> _containerCraftsman;
|
||||
|
||||
public DrawCraftsman(
|
||||
IDrawable<IComponent> componentCraftsman,
|
||||
IDrawable<IContainer> containerCraftsman)
|
||||
{
|
||||
_componentCraftsman = componentCraftsman;
|
||||
_containerCraftsman = containerCraftsman;
|
||||
}
|
||||
|
||||
public Size Draw(INode node, Position pencil, Size maxSize) =>
|
||||
node switch
|
||||
{
|
||||
IContainer container => _containerCraftsman.Draw(container, pencil, maxSize),
|
||||
IComponent component => _componentCraftsman.Draw(component, pencil, maxSize),
|
||||
_ => throw new InvalidCastException("Unknown node type.")
|
||||
};
|
||||
}
|
24
src/TUI.Engine/SymbolExtensions.cs
Normal file
24
src/TUI.Engine/SymbolExtensions.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using Pastel;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine;
|
||||
|
||||
public static class SymbolExtensions
|
||||
{
|
||||
public static string Colorized(this string symbol) =>
|
||||
!SymbolColors.ContainsKey(symbol) ? symbol.Hint() : symbol.Pastel(SymbolColors[symbol]);
|
||||
|
||||
private static readonly Dictionary<string, string> SymbolColors = new()
|
||||
{
|
||||
{ Symbols.Git, "F14E32" },
|
||||
{ Symbols.Site, "BF40BF" },
|
||||
{ Symbols.GitLab, "E24329" },
|
||||
{ Symbols.GitHub, "ADBAC7" },
|
||||
{ Symbols.NetworkPublic, "00FFFF" },
|
||||
{ Symbols.Api, "7F52FF" },
|
||||
{ Symbols.DockerImage, "086DD7" },
|
||||
{ Symbols.NpmPackage, "CB0000" },
|
||||
{ Symbols.Seo, "4285F4" },
|
||||
{ Symbols.Auth, "FFD700" },
|
||||
};
|
||||
}
|
37
src/TUI.Engine/Symbols.cs
Normal file
37
src/TUI.Engine/Symbols.cs
Normal file
@ -0,0 +1,37 @@
|
||||
namespace TUI.Engine;
|
||||
|
||||
public static class Symbols
|
||||
{
|
||||
public const string Space = " ";
|
||||
public const string Copyright = "©";
|
||||
public const string GitLab = "";
|
||||
public const string GitHub = "";
|
||||
public const string Git = "";
|
||||
public const string LineBreak = "\n";
|
||||
public const string NetworkPublic = "";
|
||||
public const string NetworkPrivate = "";
|
||||
public const string Undefined = "";
|
||||
public const string Site = "";
|
||||
public const string Api = "";
|
||||
public const string DockerImage = "";
|
||||
public const string NpmPackage = "";
|
||||
public const string Seo = "";
|
||||
public const string Auth = "";
|
||||
public const string NotFound = "";
|
||||
public const string Error = "";
|
||||
public const string Download = "";
|
||||
|
||||
public static class Lines
|
||||
{
|
||||
public const string Vertical = "│";
|
||||
public const string Horizontal = "─";
|
||||
}
|
||||
|
||||
public static class Angles
|
||||
{
|
||||
public const string RightTop = "┐";
|
||||
public const string LeftBottom = "└";
|
||||
public const string LeftTop = "┌";
|
||||
public const string RightBottom = "┘";
|
||||
}
|
||||
}
|
17
src/TUI.Engine/TUI.Engine.csproj
Normal file
17
src/TUI.Engine/TUI.Engine.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Pastel" Version="4.1.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
20
src/TUI.Engine/Theme/Defaults.cs
Normal file
20
src/TUI.Engine/Theme/Defaults.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
|
||||
namespace TUI.Engine.Theme;
|
||||
|
||||
public static class Defaults
|
||||
{
|
||||
public const Horizontal HorizontalAlignment = Horizontal.Center;
|
||||
|
||||
public const Vertical VerticalAlignment = Vertical.Top;
|
||||
|
||||
public const Level Padding = Level.None;
|
||||
|
||||
public const Resizing HorizontalResizing = Resizing.Adaptive;
|
||||
|
||||
public const Resizing VerticalResizing = Resizing.Adaptive;
|
||||
|
||||
public const Orientation Orientation = TUI.Engine.Attributes.Orientations.Orientation.Horizontal;
|
||||
}
|
7
src/TUI.Engine/Theme/Indentation.cs
Normal file
7
src/TUI.Engine/Theme/Indentation.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace TUI.Engine.Theme;
|
||||
|
||||
public static class Indentation
|
||||
{
|
||||
public const Level Default = Level.Normal;
|
||||
public const Level BorderWidth = Level.Normal;
|
||||
}
|
7
src/TUI.Engine/Theme/Level.cs
Normal file
7
src/TUI.Engine/Theme/Level.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace TUI.Engine.Theme;
|
||||
|
||||
public enum Level
|
||||
{
|
||||
None = 0,
|
||||
Normal = 1
|
||||
}
|
@ -1,21 +1,35 @@
|
||||
using Pastel;
|
||||
|
||||
|
||||
namespace TUI.UserInterface;
|
||||
namespace TUI.Engine.Theme;
|
||||
|
||||
public static class Palette
|
||||
{
|
||||
public const string HoverColor = "292928";
|
||||
public const string PrimaryColor = "84BA64";
|
||||
public const string HintColor = "71797E";
|
||||
public const string DisableColor = "303030";
|
||||
public const string ErrorColor = "CA3433";
|
||||
public const string WarningColor = "EC9706";
|
||||
public const string InfoColor = "25799F";
|
||||
|
||||
public static string Primary(this string currentText) => currentText.Pastel(PrimaryColor);
|
||||
|
||||
public static string Main(this string currentText, bool isFocused = true) =>
|
||||
isFocused
|
||||
? currentText.Pastel(PrimaryColor)
|
||||
: Hint(currentText);
|
||||
|
||||
public static string Hint(this string currentText) => currentText.Pastel(HintColor);
|
||||
|
||||
public static string Hint(this char currentText) => currentText.ToString().Pastel(HintColor);
|
||||
|
||||
public static string Disable(this string currentText) => currentText.RemoveColors().Pastel(HintColor);
|
||||
|
||||
public static string Warning(this string currentText) => currentText.Pastel(WarningColor);
|
||||
|
||||
public static string Error(this string currentText) => currentText.Pastel(ErrorColor);
|
||||
|
||||
public static string Info(this string currentText) => currentText.Pastel(InfoColor);
|
||||
|
||||
public static string Info(this char currentText) => currentText.ToString().Pastel(InfoColor);
|
||||
|
||||
public static string Info(this int currentText) => currentText.ToString().Pastel(InfoColor);
|
||||
}
|
40
src/TUI/Controls/Common/StubComponent.cs
Normal file
40
src/TUI/Controls/Common/StubComponent.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Components;
|
||||
|
||||
namespace TUI.Controls.Common;
|
||||
|
||||
public class StubComponent : ComponentBase
|
||||
{
|
||||
private readonly Size _size;
|
||||
private readonly string? _text;
|
||||
|
||||
public StubComponent(Size size, string? text = null)
|
||||
{
|
||||
_size = size;
|
||||
_text = text;
|
||||
SetFixed(Orientation.Horizontal, size.Width);
|
||||
SetFixed(Orientation.Vertical, size.Height);
|
||||
}
|
||||
|
||||
protected override Sketch DrawComponent(Size minSize)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
var height = 0;
|
||||
|
||||
|
||||
while (_size.Height > height)
|
||||
{
|
||||
builder.Append(Symbols.Space.Repeat(_size.Width - (_text?.GetWidth() ?? 0)));
|
||||
height++;
|
||||
}
|
||||
|
||||
if (_text is not null)
|
||||
{
|
||||
builder.Append(_text);
|
||||
}
|
||||
return new Sketch(builder.ToString());
|
||||
}
|
||||
}
|
20
src/TUI/Controls/Components/BreadCrumbsComponent.cs
Normal file
20
src/TUI/Controls/Components/BreadCrumbsComponent.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public class BreadCrumbsComponent : ComponentBase
|
||||
{
|
||||
private readonly List<string> _crumbs = new() { " " };
|
||||
|
||||
public BreadCrumbsComponent(params string[] crumbs)
|
||||
{
|
||||
_crumbs.AddRange(crumbs);
|
||||
}
|
||||
|
||||
protected override Sketch DrawComponent(Size minSize)
|
||||
{
|
||||
return new Sketch(string.Join(" ".Hint(), _crumbs).Hint());
|
||||
}
|
||||
}
|
36
src/TUI/Controls/Components/CellsComponentBase.cs
Normal file
36
src/TUI/Controls/Components/CellsComponentBase.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Components;
|
||||
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public class CellsComponentBase : ComponentBase, IComponent
|
||||
{
|
||||
private const int MaxCellWidth = 10;
|
||||
|
||||
private readonly IEnumerable<string> _cells;
|
||||
|
||||
public CellsComponentBase(IEnumerable<string> cells)
|
||||
{
|
||||
_cells = cells;
|
||||
}
|
||||
|
||||
public void Render(Horizontal horizontal, Size size)
|
||||
{
|
||||
var content = new StringBuilder();
|
||||
foreach (var cell in _cells)
|
||||
{
|
||||
content.Append(Symbols.Space.Repeat(MaxCellWidth - cell.GetWidth()));
|
||||
content.Append(cell);
|
||||
}
|
||||
|
||||
// base.Render(content, position, size);
|
||||
}
|
||||
|
||||
protected override Sketch DrawComponent(Size minSize)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
67
src/TUI/Controls/Components/PanelComponent.cs
Normal file
67
src/TUI/Controls/Components/PanelComponent.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
using static TUI.Engine.Symbols;
|
||||
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public class PanelComponent : ComponentBase, IComponent
|
||||
{
|
||||
private readonly string _title;
|
||||
|
||||
public PanelComponent(string title)
|
||||
{
|
||||
_title = title;
|
||||
SetAbsolute();
|
||||
}
|
||||
|
||||
private static void RenderTopLine(StringBuilder builder, Size size, string title)
|
||||
{
|
||||
var halfWidth = (size.Width - title.GetWidth() - (int)Indentation.BorderWidth * 2 -
|
||||
(int)Indentation.Default * 2) / 2;
|
||||
builder.Append(Angles.LeftTop);
|
||||
builder.Append(Lines.Horizontal.Repeat(halfWidth));
|
||||
builder.AppendFormat("{0}{1}{0}", Space.Repeat(Convert.ToInt32(Indentation.Default)), title);
|
||||
builder.Append(Lines.Horizontal.Repeat(halfWidth + halfWidth % 2));
|
||||
builder.Append(Angles.RightTop);
|
||||
builder.Append(LineBreak);
|
||||
}
|
||||
|
||||
private static void RenderMiddleLine(StringBuilder builder, Size size)
|
||||
{
|
||||
var dashboardHeight = size.Height - (int)Indentation.BorderWidth * 2;
|
||||
|
||||
while (dashboardHeight > 0)
|
||||
{
|
||||
var bodyWidth = size.Width - (int)Indentation.BorderWidth * 2;
|
||||
builder.Append(Lines.Vertical);
|
||||
builder.Append(Space.Repeat(bodyWidth));
|
||||
builder.Append(Lines.Vertical);
|
||||
builder.Append(LineBreak);
|
||||
|
||||
dashboardHeight--;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderBottomLine(StringBuilder builder, Size size)
|
||||
{
|
||||
var width = size.Width - (int)Indentation.BorderWidth * 2;
|
||||
builder.Append(Angles.LeftBottom);
|
||||
builder.Append(Lines.Horizontal.Repeat(width));
|
||||
builder.Append(Angles.RightBottom);
|
||||
builder.Append(LineBreak);
|
||||
}
|
||||
|
||||
protected override Sketch DrawComponent(Size minSize)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
RenderTopLine(builder, minSize, _title);
|
||||
RenderMiddleLine(builder, minSize);
|
||||
RenderBottomLine(builder, minSize);
|
||||
|
||||
return new Sketch(builder.ToString().Main());
|
||||
}
|
||||
}
|
47
src/TUI/Controls/Components/ProjectTitle.cs
Normal file
47
src/TUI/Controls/Components/ProjectTitle.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Text;
|
||||
using TUI.Domain;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
using TUI.UserInterface;
|
||||
using static TUI.Engine.Symbols;
|
||||
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public class ProjectTitle : ComponentBase
|
||||
{
|
||||
private readonly Project _project;
|
||||
|
||||
public ProjectTitle(Project project)
|
||||
{
|
||||
_project = project;
|
||||
}
|
||||
|
||||
protected override Sketch DrawComponent(Size minSize)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.Append(GetHub().Colorized());
|
||||
builder.Append(Space);
|
||||
builder.Append((_project.IsPublicNetwork ? NetworkPublic : NetworkPrivate).Colorized());
|
||||
builder.Append(Space);
|
||||
builder.Append(_project.SeoDependent ? Seo.Colorized() : Seo.Disable());
|
||||
builder.Append(Space);
|
||||
builder.Append(_project.HasAuth ? Auth.Colorized() : Auth.Disable());
|
||||
builder.Append(Space);
|
||||
builder.Append(GetApplicationType().Colorized());
|
||||
builder.Append(Space);
|
||||
builder.Append(_project.Name.Disable());
|
||||
return new Sketch(builder);
|
||||
}
|
||||
|
||||
private string GetHub() => _project.Hub.Type == "gitlab" ? GitLab : GitHub;
|
||||
|
||||
private string GetApplicationType()
|
||||
{
|
||||
foreach (var application in Icons.Applications.Where(application => _project.Tags.Have(application.Value)))
|
||||
return application.Key;
|
||||
|
||||
return Undefined.Hint();
|
||||
}
|
||||
}
|
50
src/TUI/Controls/Components/SpeakerComponent.cs
Normal file
50
src/TUI/Controls/Components/SpeakerComponent.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public class SpeakerComponent : ComponentBase
|
||||
{
|
||||
private string _message = "";
|
||||
|
||||
private Position? _pencil;
|
||||
|
||||
private SpeakerComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public static SpeakerComponent Instance { get; } = new();
|
||||
|
||||
protected override Sketch DrawComponent(Size minSize)
|
||||
{
|
||||
return new Sketch(_message);
|
||||
}
|
||||
|
||||
private void Clear()
|
||||
{
|
||||
_message = new string(' ', DrawContext.MaxSize.Width);
|
||||
DrawContext.Canvas.Draw(Instance, _pencil, DrawContext.MaxSize);
|
||||
}
|
||||
|
||||
public void Shout(string emoji, string message)
|
||||
{
|
||||
if (DrawContext is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_pencil ??= DrawContext.Pencil with { };
|
||||
|
||||
Clear();
|
||||
_message = emoji + Symbols.Space + message;
|
||||
DrawContext.Canvas.Draw(Instance, _pencil, DrawContext.MaxSize);
|
||||
|
||||
Task.Delay(2000).ContinueWith(_ =>
|
||||
{
|
||||
Clear();
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
44
src/TUI/Controls/Components/VersionComponent.cs
Normal file
44
src/TUI/Controls/Components/VersionComponent.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Text;
|
||||
using TUI.Domain;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public class VersionComponent : ComponentBase
|
||||
{
|
||||
private readonly VersionType _type;
|
||||
private readonly string _version;
|
||||
private readonly Brand? _brand;
|
||||
private readonly VersionStatus _status;
|
||||
|
||||
public VersionComponent(string version, Brand brand, VersionStatus status = VersionStatus.SoGood,
|
||||
VersionType type = VersionType.Release)
|
||||
{
|
||||
_version = version;
|
||||
_brand = brand;
|
||||
_status = status;
|
||||
_type = type;
|
||||
}
|
||||
|
||||
protected override Sketch DrawComponent(Size minSize)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
|
||||
if (_brand is not null)
|
||||
{
|
||||
builder.Append(_brand.ColorLogo());
|
||||
}
|
||||
|
||||
builder.Append(_type.ToImage().Warning());
|
||||
builder.Append(Symbols.Space);
|
||||
builder.Append(_version);
|
||||
var sketch = builder.ToString();
|
||||
|
||||
return new Sketch(_status.Colorize(sketch));
|
||||
}
|
||||
}
|
||||
|
28
src/TUI/Controls/Components/VersionExtensions.cs
Normal file
28
src/TUI/Controls/Components/VersionExtensions.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public static class VersionExtensions
|
||||
{
|
||||
public static string ToImage(this VersionType versionType)
|
||||
=>
|
||||
versionType switch
|
||||
{
|
||||
VersionType.Alpha => "",
|
||||
VersionType.Beta => "",
|
||||
VersionType.Candidate => "",
|
||||
VersionType.Canary => "",
|
||||
VersionType.Next => "",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
public static string Colorize(this VersionStatus versionStatus, string value) =>
|
||||
versionStatus switch
|
||||
{
|
||||
VersionStatus.TooOld => value.Warning(),
|
||||
VersionStatus.ToNew => value.Info(),
|
||||
VersionStatus.SoGood => value.Hint(),
|
||||
VersionStatus.BeNice => value.Main(),
|
||||
_ => value
|
||||
};
|
||||
}
|
10
src/TUI/Controls/Components/VersionStatus.cs
Normal file
10
src/TUI/Controls/Components/VersionStatus.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public enum VersionStatus
|
||||
{
|
||||
NotFound,
|
||||
ToNew,
|
||||
SoGood,
|
||||
BeNice,
|
||||
TooOld,
|
||||
}
|
12
src/TUI/Controls/Components/VersionType.cs
Normal file
12
src/TUI/Controls/Components/VersionType.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace TUI.Controls.Components;
|
||||
|
||||
public enum VersionType
|
||||
{
|
||||
Convention,
|
||||
Release,
|
||||
Candidate,
|
||||
Canary,
|
||||
Alpha,
|
||||
Beta,
|
||||
Next,
|
||||
}
|
19
src/TUI/Controls/Containers/ContentContainer.cs
Normal file
19
src/TUI/Controls/Containers/ContentContainer.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Controls.Containers;
|
||||
|
||||
public class ContentContainer : ContainerBase
|
||||
{
|
||||
private readonly Nodes _children = new();
|
||||
|
||||
public void AddChildren(INode node)
|
||||
{
|
||||
_children.Add(node);
|
||||
}
|
||||
|
||||
public override Nodes GetNodes()
|
||||
{
|
||||
return _children;
|
||||
}
|
||||
}
|
34
src/TUI/Controls/Containers/DashboardContainer.cs
Normal file
34
src/TUI/Controls/Containers/DashboardContainer.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using TUI.Controls.Components;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Containers;
|
||||
|
||||
public class DashboardContainer : ContainerBase
|
||||
{
|
||||
private readonly Nodes _children = new();
|
||||
private readonly ContentContainer _content;
|
||||
|
||||
public DashboardContainer()
|
||||
{
|
||||
var panel = new PanelComponent(" ".Info() + " Dependencies".Main());
|
||||
_content = new ContentContainer();
|
||||
_content.SetOrientationVertical();
|
||||
SetOrientationVertical();
|
||||
|
||||
_children.Add(panel);
|
||||
_children.Add(_content);
|
||||
}
|
||||
|
||||
public void AddChildren(IContainer node)
|
||||
{
|
||||
node.SetFixed(Orientation.Vertical, 1);
|
||||
_content.AddChildren(node);
|
||||
}
|
||||
|
||||
public override Nodes GetNodes() => _children;
|
||||
|
||||
public Nodes GetContent() => _content.GetNodes();
|
||||
}
|
105
src/TUI/Controls/Containers/DependenciesContainer.cs
Normal file
105
src/TUI/Controls/Containers/DependenciesContainer.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using TUI.Controls.Common;
|
||||
using TUI.Controls.Components;
|
||||
using TUI.Domain;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Containers;
|
||||
|
||||
public class DependenciesContainer : ContainerBase
|
||||
{
|
||||
public readonly Project? Project;
|
||||
|
||||
private const int VersionColumnWidth = 11;
|
||||
|
||||
private const int TitleColumnWidth = 25;
|
||||
|
||||
private readonly Nodes _dependencies = new();
|
||||
|
||||
public DependenciesContainer()
|
||||
{
|
||||
}
|
||||
|
||||
public DependenciesContainer(Project project)
|
||||
{
|
||||
Project = project;
|
||||
}
|
||||
|
||||
public void AddTitleStub()
|
||||
{
|
||||
var size = new Size(TitleColumnWidth, 1);
|
||||
var title = new StubComponent(size);
|
||||
title.SetPadding(Level.Normal);
|
||||
|
||||
_dependencies.Add(title);
|
||||
}
|
||||
|
||||
public void AddTitle(IComponent title)
|
||||
{
|
||||
title.SetPadding(Level.Normal);
|
||||
title.SetFixed(Orientation.Horizontal, TitleColumnWidth);
|
||||
title.SetAlignment(Horizontal.Left);
|
||||
|
||||
if (Project is not null && Project.Legacy)
|
||||
{
|
||||
title.StyleContext = new StyleContext(Palette.DisableColor);
|
||||
}
|
||||
|
||||
_dependencies.Add(title);
|
||||
}
|
||||
|
||||
public void AddDependencyStub()
|
||||
{
|
||||
var size = new Size(VersionColumnWidth, 1);
|
||||
var stub = new StubComponent(size, Symbols.NotFound.Hint());
|
||||
stub.SetPadding(Level.Normal);
|
||||
stub.SetAlignment(Horizontal.Right);
|
||||
stub.SetFixed(Orientation.Horizontal, VersionColumnWidth);
|
||||
|
||||
if (Project is not null && Project.Legacy)
|
||||
{
|
||||
stub.StyleContext = new StyleContext(Palette.DisableColor);
|
||||
}
|
||||
|
||||
_dependencies.Add(stub);
|
||||
}
|
||||
|
||||
public void AddError()
|
||||
{
|
||||
var size = new Size(25, 1);
|
||||
var stub = new StubComponent(size, (Symbols.Error + Symbols.Space + " Something went wrong").Error());
|
||||
stub.SetPadding(Level.Normal);
|
||||
stub.SetAlignment(Horizontal.Right);
|
||||
stub.SetFixed(Orientation.Horizontal, 25);
|
||||
|
||||
if (Project is not null && Project.Legacy)
|
||||
{
|
||||
stub.StyleContext = new StyleContext(Palette.DisableColor);
|
||||
}
|
||||
|
||||
_dependencies.Add(stub);
|
||||
}
|
||||
|
||||
public void AddDependency(Dependency dependency, VersionStatus status = VersionStatus.BeNice)
|
||||
{
|
||||
var version = new VersionComponent(dependency.Version, dependency.Brand, status, dependency.Type);
|
||||
version.SetPadding(Level.Normal);
|
||||
version.SetAlignment(Horizontal.Right);
|
||||
version.SetFixed(Orientation.Horizontal, VersionColumnWidth);
|
||||
|
||||
if (Project is not null && Project.Legacy)
|
||||
{
|
||||
version.StyleContext = new StyleContext(Palette.DisableColor);
|
||||
}
|
||||
|
||||
_dependencies.Add(version);
|
||||
}
|
||||
|
||||
public override Nodes GetNodes() => _dependencies;
|
||||
}
|
32
src/TUI/Controls/Containers/FooterContainer.cs
Normal file
32
src/TUI/Controls/Containers/FooterContainer.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using TUI.Controls.Components;
|
||||
using TUI.Controls.Statics;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Containers;
|
||||
|
||||
public class FooterContainer : ContainerBase
|
||||
{
|
||||
private readonly INode _breadcrumbs;
|
||||
private readonly INode _speaker;
|
||||
|
||||
public FooterContainer(IComponent? breadcrumbs)
|
||||
{
|
||||
breadcrumbs.SetAlignment(Horizontal.Left);
|
||||
breadcrumbs.SetPaddingLeft(Level.Normal);
|
||||
_breadcrumbs = breadcrumbs;
|
||||
|
||||
_speaker = SpeakerComponent.Instance;
|
||||
}
|
||||
|
||||
public override Nodes GetNodes()
|
||||
{
|
||||
var copyright = new CopyrightComponent();
|
||||
copyright.SetAlignment(Horizontal.Right);
|
||||
copyright.SetPaddingRight(Level.Normal);
|
||||
return new Nodes { _breadcrumbs, _speaker, copyright };
|
||||
}
|
||||
}
|
38
src/TUI/Controls/Containers/HeaderContainer.cs
Normal file
38
src/TUI/Controls/Containers/HeaderContainer.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using TUI.Controls.Statics;
|
||||
using TUI.Controls.Statics.Hints;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Containers;
|
||||
|
||||
public class HeaderContainer : ContainerBase, IContainer
|
||||
{
|
||||
public override Nodes GetNodes()
|
||||
{
|
||||
var versionHints = new VersionHints();
|
||||
versionHints.SetPadding(Indentation.Default);
|
||||
versionHints.SetAlignment(Horizontal.Left);
|
||||
|
||||
var tagsHints = new TagHints();
|
||||
tagsHints.SetPadding(Indentation.Default);
|
||||
tagsHints.SetAlignment(Horizontal.Left);
|
||||
|
||||
var appTypeHints = new AppTypeHints();
|
||||
appTypeHints.SetPadding(Indentation.Default);
|
||||
appTypeHints.SetAlignment(Horizontal.Left);
|
||||
|
||||
var hotkeysHints = new HotkeysHint();
|
||||
hotkeysHints.SetPadding(Indentation.Default);
|
||||
hotkeysHints.SetAlignment(Horizontal.Left);
|
||||
|
||||
var logo = new LogoComponent();
|
||||
logo.SetAlignment(Horizontal.Right);
|
||||
logo.SetPaddingLeft(Indentation.Default);
|
||||
logo.SetPaddingBottom(Indentation.Default);
|
||||
logo.SetPaddingRight(Indentation.Default);
|
||||
|
||||
return new Nodes { versionHints, tagsHints, appTypeHints, hotkeysHints, logo };
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using TUI.UserInterface;
|
||||
|
||||
|
||||
namespace TUI.Controls;
|
||||
|
||||
public class Copyright : IControl<string>
|
||||
{
|
||||
public void Render(string author, Position position)
|
||||
{
|
||||
const string icon = "© ";
|
||||
Console.SetCursorPosition(position.Left - icon.Width(), position.Top);
|
||||
|
||||
var copyright = $"{icon}{author}".Hint();
|
||||
Console.Write(copyright);
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
using System.Text;
|
||||
using TUI.UserInterface;
|
||||
|
||||
|
||||
namespace TUI.Controls;
|
||||
|
||||
public class Dashboard : IControl<string>
|
||||
{
|
||||
public void Render(string title, Position position)
|
||||
{
|
||||
Console.SetCursorPosition(position.Left, position.Top);
|
||||
|
||||
RenderTopLine(title);
|
||||
|
||||
var marginTop = Theme.BorderWidth + Theme.Padding + position.Top;
|
||||
var dashboardHeight = Console.WindowHeight - Theme.BorderWidth;
|
||||
|
||||
for (var top = marginTop; top < dashboardHeight; top++)
|
||||
{
|
||||
RenderMiddleLine();
|
||||
}
|
||||
|
||||
RenderBottomLine();
|
||||
}
|
||||
|
||||
private static void RenderMiddleLine()
|
||||
{
|
||||
Console.Write("│".Primary());
|
||||
Console.Write(new string(' ', Console.WindowWidth - Theme.BorderWidth * 2));
|
||||
Console.WriteLine("│".Primary());
|
||||
}
|
||||
|
||||
private static void RenderBottomLine()
|
||||
{
|
||||
var lineWidth = Console.WindowWidth - Theme.BorderWidth * 2;
|
||||
Console.Write("└".Primary());
|
||||
Console.Write('─'.Repeat(lineWidth).Primary());
|
||||
Console.WriteLine("┘".Primary());
|
||||
}
|
||||
|
||||
private static void RenderTopLine(string title)
|
||||
{
|
||||
var lineWidth =
|
||||
(Console.WindowWidth - title.Width() - Theme.BorderWidth * 2 - Theme.Padding * 2) /
|
||||
2;
|
||||
|
||||
var topLine = new StringBuilder();
|
||||
topLine.Append("┌");
|
||||
topLine.Append('─'.Repeat(lineWidth));
|
||||
topLine.AppendFormat("{0}{1}{0}", ' '.Repeat(Theme.Padding), title);
|
||||
if (title.Width() % 2 == 1)
|
||||
{
|
||||
topLine.Append('─');
|
||||
}
|
||||
|
||||
topLine.Append('─'.Repeat(lineWidth));
|
||||
topLine.Append("┐");
|
||||
Console.WriteLine(topLine.ToString().Primary());
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
using TUI.Dashboards;
|
||||
using TUI.Domain;
|
||||
using TUI.UserInterface;
|
||||
|
||||
|
||||
namespace TUI.Controls;
|
||||
|
||||
public class Display
|
||||
{
|
||||
private bool _headerInDisplay = true;
|
||||
public readonly Header Header;
|
||||
|
||||
public readonly Copyright Copyright;
|
||||
|
||||
public readonly DependencyDashboard DependencyDashboard;
|
||||
private Project _currentProject;
|
||||
|
||||
public Display()
|
||||
{
|
||||
Header = new Header();
|
||||
Copyright = new Copyright();
|
||||
DependencyDashboard = new DependencyDashboard();
|
||||
|
||||
Render();
|
||||
}
|
||||
|
||||
public void OpenDeps(Project project)
|
||||
{
|
||||
_currentProject = project;
|
||||
var dashboardPosition = new Position(0, Header.Height);
|
||||
DependencyDashboard.Render(_currentProject, dashboardPosition);
|
||||
}
|
||||
|
||||
private void ResizeDependencies(bool full)
|
||||
{
|
||||
var dashboardPosition = new Position(0, full ? 0 : Header.Height);
|
||||
DependencyDashboard.Render(_currentProject, dashboardPosition);
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
var headerPosition = new Position(0, 0);
|
||||
Header.Render(headerPosition);
|
||||
|
||||
const string copyrightText = "Kolosov Aleksandr";
|
||||
var copyrightPosition = new Position(
|
||||
Console.WindowWidth - copyrightText.Width(),
|
||||
Console.WindowHeight);
|
||||
Copyright.Render(copyrightText, copyrightPosition);
|
||||
}
|
||||
|
||||
public void ToggleHeader()
|
||||
{
|
||||
_headerInDisplay = !_headerInDisplay;
|
||||
if (_headerInDisplay)
|
||||
{
|
||||
var headerPosition = new Position(0, 0);
|
||||
Header.Render(headerPosition);
|
||||
}
|
||||
|
||||
ResizeDependencies(!_headerInDisplay);
|
||||
}
|
||||
|
||||
public void Next()
|
||||
{
|
||||
DependencyDashboard.Next();
|
||||
}
|
||||
|
||||
public void Previous()
|
||||
{
|
||||
DependencyDashboard.Previous();
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace TUI.Controls;
|
||||
|
||||
public interface IControl
|
||||
{
|
||||
void Render(Position position);
|
||||
}
|
||||
|
||||
public interface IControl<in TProps>
|
||||
{
|
||||
void Render(TProps props, Position position);
|
||||
}
|
32
src/TUI/Controls/Layouts/DashboardLayout.cs
Normal file
32
src/TUI/Controls/Layouts/DashboardLayout.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Controls.Layouts;
|
||||
|
||||
public class DashboardLayout : ContainerBase, IContainer
|
||||
{
|
||||
private readonly INode _header;
|
||||
private readonly INode _footer;
|
||||
private readonly INode _dashboard;
|
||||
|
||||
public DashboardLayout(INode header, INode dashboard, INode footer)
|
||||
{
|
||||
SetOrientationVertical();
|
||||
SetAdaptive(Orientation.Horizontal);
|
||||
SetAdaptive(Orientation.Vertical);
|
||||
|
||||
header.SetFixed(Orientation.Vertical, 6);
|
||||
footer.SetFixed(Orientation.Vertical, 1);
|
||||
|
||||
_header = header;
|
||||
_footer = footer;
|
||||
_dashboard = dashboard;
|
||||
}
|
||||
|
||||
public override Nodes GetNodes() =>
|
||||
new()
|
||||
{
|
||||
_header, _dashboard, _footer
|
||||
};
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
namespace TUI.Controls;
|
||||
|
||||
public record Position(int Left, int Top);
|
18
src/TUI/Controls/Statics/CopyrightComponent.cs
Normal file
18
src/TUI/Controls/Statics/CopyrightComponent.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Statics;
|
||||
|
||||
public class CopyrightComponent : StaticComponentBase
|
||||
{
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
builder.Append(Symbols.Copyright.Info());
|
||||
builder.Append(Symbols.Space);
|
||||
builder.Append("Kolosov A. aka \"dnwSilver\"".Hint());
|
||||
builder.Append(Symbols.Space);
|
||||
builder.Append(DateTime.Now.Year.Info());
|
||||
}
|
||||
}
|
27
src/TUI/Controls/Statics/Hints/AppTypeHints.cs
Normal file
27
src/TUI/Controls/Statics/Hints/AppTypeHints.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Statics.Hints;
|
||||
|
||||
public class AppTypeHints : StaticComponentBase
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
{ Symbols.NpmPackage, "package" },
|
||||
{ Symbols.DockerImage, "image" },
|
||||
{ Symbols.Site, "site" },
|
||||
{ Symbols.Api, "api" }
|
||||
};
|
||||
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
foreach (var hint in _hints)
|
||||
{
|
||||
builder.Append(hint.Key);
|
||||
builder.Append(Symbols.Space);
|
||||
builder.AppendLine(hint.Value.Hint());
|
||||
}
|
||||
}
|
||||
}
|
27
src/TUI/Controls/Statics/Hints/HotkeysHint.cs
Normal file
27
src/TUI/Controls/Statics/Hints/HotkeysHint.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Statics.Hints;
|
||||
|
||||
public class HotkeysHint : StaticComponentBase
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
{ "", "select prev" },
|
||||
{ "", "select next" },
|
||||
{ "", "toggle head" },
|
||||
{ "", "quit" }
|
||||
};
|
||||
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
foreach (var hint in _hints)
|
||||
{
|
||||
builder.Append(hint.Key.Hint());
|
||||
builder.Append(Symbols.Space);
|
||||
builder.AppendLine(hint.Value.Hint());
|
||||
}
|
||||
}
|
||||
}
|
27
src/TUI/Controls/Statics/Hints/TagHints.cs
Normal file
27
src/TUI/Controls/Statics/Hints/TagHints.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Statics.Hints;
|
||||
|
||||
public class TagHints : StaticComponentBase
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
{ Symbols.Auth, "Auth" },
|
||||
{ Symbols.NetworkPublic, "WWW" },
|
||||
{ Symbols.Seo, "SEO" },
|
||||
{ Symbols.Git, "VCS" }
|
||||
};
|
||||
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
foreach (var hint in _hints)
|
||||
{
|
||||
builder.Append(hint.Key);
|
||||
builder.Append(Symbols.Space);
|
||||
builder.AppendLine(hint.Value.Hint());
|
||||
}
|
||||
}
|
||||
}
|
28
src/TUI/Controls/Statics/Hints/VersionHints.cs
Normal file
28
src/TUI/Controls/Statics/Hints/VersionHints.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Text;
|
||||
using TUI.Controls.Components;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Statics.Hints;
|
||||
|
||||
public class VersionHints : StaticComponentBase
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
{ "", VersionStatus.ToNew.Colorize("too new") },
|
||||
{ "", VersionStatus.SoGood.Colorize("so good") },
|
||||
{ "", VersionStatus.BeNice.Colorize("be nice") },
|
||||
{ "", VersionStatus.TooOld.Colorize("too old") }
|
||||
};
|
||||
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
foreach (var hint in _hints)
|
||||
{
|
||||
builder.Append(hint.Key.Hint());
|
||||
builder.Append(Symbols.Space);
|
||||
builder.AppendLine(hint.Value);
|
||||
}
|
||||
}
|
||||
}
|
20
src/TUI/Controls/Statics/LogoComponent.cs
Normal file
20
src/TUI/Controls/Statics/LogoComponent.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Controls.Statics;
|
||||
|
||||
public class LogoComponent : StaticComponentBase
|
||||
{
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
builder.Append($" {"╭━━━━┳╮".Main()}{"╱╱".Hint()}{"╭━━━╮".Main()}").Append(Symbols.LineBreak);
|
||||
builder.Append($" {"┃╭╮╭╮┃┃".Main()}{"╱╱".Hint()}{"╰╮╭╮┃".Main()}").Append(Symbols.LineBreak);
|
||||
builder.Append($" {"╰╯┃┃╰┫┃".Main()}{"╱╱╱".Hint()}{"┃┃┃┃".Main()}").Append(Symbols.LineBreak);
|
||||
builder.Append($" {"╱╱".Hint()}{"┃┃".Main()}{"╱".Hint()}{"┃┃".Main()}{"╱".Hint()}{"╭╮┃┃┃┃".Main()}")
|
||||
.Append(Symbols.LineBreak);
|
||||
builder.Append($" {"╱╱╱".Hint()}{"┃┃".Main()}{"╱".Hint()}{"┃╰━╯┣╯╰╯┃".Main()}").Append(Symbols.LineBreak);
|
||||
builder.Append($"{"╱╱╱╱".Hint()}{"╰╯".Main()}{"╱".Hint()}{"╰━━━┻━━━╯".Main()}").Append(Symbols.LineBreak);
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
using Pastel;
|
||||
using TUI.UserInterface;
|
||||
|
||||
|
||||
namespace TUI.Controls;
|
||||
|
||||
public record TableProps(IEnumerable<string> HeaderCells,
|
||||
IEnumerable<string> Rows,
|
||||
int TitleWidth,
|
||||
int ColumnWidth);
|
||||
|
||||
public class Table : IControl<TableProps>
|
||||
{
|
||||
private Position _position;
|
||||
private int _selectedRowId;
|
||||
|
||||
public void Render(TableProps props, Position position)
|
||||
{
|
||||
_position = position;
|
||||
Console.SetCursorPosition(_position.Left, _position.Top);
|
||||
|
||||
Console.Write(' '.Repeat(props.TitleWidth));
|
||||
foreach (var headerCell in props.HeaderCells)
|
||||
{
|
||||
Console.Write(' '.Repeat(props.ColumnWidth - headerCell.Width()) + headerCell);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<int, string> _rows = new();
|
||||
|
||||
public void RenderRow(int rowId, string rowText, string? bgColor = default)
|
||||
{
|
||||
var padRight = ' '.Repeat(Console.WindowWidth - rowText.Width() - Theme.BorderWidth * 2);
|
||||
_rows[rowId] = rowText + padRight;
|
||||
|
||||
Console.SetCursorPosition(_position.Left, _position.Top + rowId);
|
||||
Console.Write(string.IsNullOrEmpty(bgColor) ? rowText : rowText.PastelBg(bgColor));
|
||||
}
|
||||
|
||||
public void Next()
|
||||
{
|
||||
if (_selectedRowId >= _rows.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveHoverFromCurrentRow();
|
||||
RenderRow(++_selectedRowId, _rows[_selectedRowId], Palette.HoverColor);
|
||||
}
|
||||
|
||||
private void RemoveHoverFromCurrentRow()
|
||||
{
|
||||
if (_rows.TryGetValue(_selectedRowId, out var row))
|
||||
{
|
||||
RenderRow(_selectedRowId, row);
|
||||
}
|
||||
}
|
||||
|
||||
public void Previous()
|
||||
{
|
||||
if (_selectedRowId == 0)
|
||||
{
|
||||
Next();
|
||||
}
|
||||
|
||||
if (_selectedRowId == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveHoverFromCurrentRow();
|
||||
RenderRow(--_selectedRowId, _rows[_selectedRowId], Palette.HoverColor);
|
||||
}
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Pastel;
|
||||
using TUI.Controls;
|
||||
using TUI.Domain;
|
||||
using TUI.Settings;
|
||||
using TUI.UserInterface;
|
||||
|
||||
|
||||
namespace TUI.Dashboards;
|
||||
|
||||
public class DependencyDashboard : IControl<Project>
|
||||
{
|
||||
private const int TitleWidth = 25;
|
||||
private const int ColumnWidth = 10;
|
||||
|
||||
private readonly Table _table = new();
|
||||
|
||||
public void Render(Project project, Position position)
|
||||
{
|
||||
var dashboard = new Dashboard();
|
||||
dashboard.Render(project.Icon, position);
|
||||
|
||||
var header = project.Dependencies.Select(GetConventionVersion).ToArray();
|
||||
var rows = project.Sources.Select(GetTitle).ToArray();
|
||||
|
||||
var tablePosition = new Position(
|
||||
position.Left + Theme.BorderWidth,
|
||||
position.Top + Theme.BorderWidth);
|
||||
|
||||
var tableProps = new TableProps(header, rows, TitleWidth, ColumnWidth);
|
||||
|
||||
_table.Render(tableProps, tablePosition);
|
||||
|
||||
for (var rowId = 0; rowId < rows.Length; rowId++)
|
||||
{
|
||||
var actualDependencies = GetDependencies(project.Sources[rowId], project.Dependencies);
|
||||
_table.RenderRow(rowId + 1, rows[rowId] + actualDependencies);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDependencies(SourceDto sourceDto, IEnumerable<DependencyDto> conventionDependencies)
|
||||
{
|
||||
try
|
||||
{
|
||||
var package = DownloadPackage(sourceDto);
|
||||
|
||||
return string.Join("",
|
||||
conventionDependencies
|
||||
.Select(dependency => GetVersion(dependency, package))
|
||||
.Select(RenderCurrentVersion));
|
||||
}
|
||||
catch (HttpRequestException exception)
|
||||
{
|
||||
switch (exception.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.BadRequest:
|
||||
return " Request have errors.".Pastel(Palette.ErrorColor);
|
||||
case HttpStatusCode.Forbidden:
|
||||
return " Not enough rights.".Pastel(Palette.ErrorColor);
|
||||
case HttpStatusCode.NotFound:
|
||||
return " Repository or branch master not found.".Pastel(Palette.ErrorColor);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debugger.Break();
|
||||
return " We tried to send a request but couldn't. Check your configuration.".Pastel(Palette.ErrorColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static string GetVersion(DependencyDto dependency, Package package)
|
||||
{
|
||||
var currentVersion = package.ParseVersion(dependency.Name);
|
||||
|
||||
if (currentVersion == null)
|
||||
{
|
||||
return Icons.NotFound;
|
||||
}
|
||||
|
||||
var conventionVersion = dependency.Version?.ToVersion();
|
||||
return PaintingVersion(currentVersion, conventionVersion);
|
||||
}
|
||||
|
||||
private static string PaintingVersion(Version current, Version? convention)
|
||||
{
|
||||
var textVersion = current.ToString();
|
||||
|
||||
if (current > convention)
|
||||
{
|
||||
return textVersion.Info();
|
||||
}
|
||||
|
||||
if (current < convention)
|
||||
{
|
||||
return current.Major == convention.Major ? textVersion.Primary() : textVersion.Warning();
|
||||
}
|
||||
|
||||
return textVersion.Hint();
|
||||
}
|
||||
|
||||
private readonly static Dictionary<string, Package> Packages = new();
|
||||
|
||||
private static Package DownloadPackage(SourceDto sourceDto)
|
||||
{
|
||||
if (Packages.TryGetValue(sourceDto.Repo, out var downloadPackage))
|
||||
{
|
||||
return downloadPackage;
|
||||
}
|
||||
|
||||
using HttpClient client = new();
|
||||
var endpoint = sourceDto.Tags.Have("gitlab") ? GetGitlabEndpoint(sourceDto) : sourceDto.Repo;
|
||||
var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult();
|
||||
var package = JsonSerializer.Deserialize<Package>(json);
|
||||
Packages.Add(endpoint, package);
|
||||
return package;
|
||||
}
|
||||
|
||||
private static string GetGitlabEndpoint(SourceDto sourceDto)
|
||||
{
|
||||
var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT");
|
||||
return $"{sourceDto.Repo}/api/v4/projects/{sourceDto.ProjectId}/repository/files/package.json/raw?" +
|
||||
$"private_token={token}&ref=master";
|
||||
}
|
||||
|
||||
private static string GetConventionVersion(DependencyDto dependencyDto)
|
||||
{
|
||||
return dependencyDto.Icon.Pastel(dependencyDto.Color) + dependencyDto.Version.Primary();
|
||||
}
|
||||
|
||||
private static string RenderCurrentVersion(string version)
|
||||
{
|
||||
var versionWidth = version.Width();
|
||||
if (versionWidth == 0)
|
||||
{
|
||||
return ' '.Repeat(ColumnWidth - 1) + Icons.NotFound.Hint();
|
||||
}
|
||||
|
||||
return ' '.Repeat(ColumnWidth - versionWidth) + version;
|
||||
}
|
||||
|
||||
private static string GetTitle(SourceDto sourceDto)
|
||||
{
|
||||
var title = "";
|
||||
|
||||
title += RenderPadding();
|
||||
title += RenderTags(sourceDto);
|
||||
if (title.Width() + sourceDto.Name.Length + Theme.Padding <= TitleWidth)
|
||||
{
|
||||
title += sourceDto.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
var maxNameWidth = TitleWidth - title.Width() - Theme.Padding;
|
||||
title += $"{sourceDto.Name[..(maxNameWidth - 1)]}{"#".Hint()}";
|
||||
}
|
||||
|
||||
title += RenderPadding();
|
||||
return $"{title}{' '.Repeat(TitleWidth - title.Width())}";
|
||||
}
|
||||
|
||||
private static string RenderPadding()
|
||||
{
|
||||
return new string(' ', Theme.Padding);
|
||||
}
|
||||
|
||||
private static string RenderTags(SourceDto sourceDto)
|
||||
{
|
||||
var tags = "";
|
||||
tags += GetGitApplication(sourceDto);
|
||||
tags += " ";
|
||||
tags += sourceDto.Tags.Have("public") ? Icons.NetworkPublic : Icons.NetworkPrivate;
|
||||
tags += " ";
|
||||
tags += sourceDto.Tags.Have("seo") ? Icons.SEO : Icons.SEO.Disable();
|
||||
tags += " ";
|
||||
tags += sourceDto.Tags.Have("auth") ? Icons.Auth : Icons.Auth.Disable();
|
||||
tags += " ";
|
||||
tags += GetApplicationType(sourceDto);
|
||||
tags += " ";
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
private static string GetApplicationType(SourceDto sourceDto)
|
||||
{
|
||||
foreach (var application in Icons.Applications)
|
||||
{
|
||||
if (sourceDto.Tags.Have(application.Value))
|
||||
return application.Key;
|
||||
}
|
||||
|
||||
return Icons.Undefined;
|
||||
}
|
||||
|
||||
private static string GetGitApplication(SourceDto sourceDto) => sourceDto.Repo switch
|
||||
{
|
||||
{ } url when url.Contains("gitlab") => Icons.GitLab,
|
||||
{ } url when url.Contains("github") => Icons.GitHub,
|
||||
_ => Icons.Git
|
||||
};
|
||||
|
||||
public void Next()
|
||||
{
|
||||
_table.Next();
|
||||
}
|
||||
|
||||
public void Previous()
|
||||
{
|
||||
_table.Previous();
|
||||
}
|
||||
}
|
8
src/TUI/Domain/Brand.cs
Normal file
8
src/TUI/Domain/Brand.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using Pastel;
|
||||
|
||||
namespace TUI.Domain;
|
||||
|
||||
public record Brand(string Name, string? Logo = null, string? Color = null)
|
||||
{
|
||||
public string ColorLogo() => Logo?.Pastel(Color) ?? string.Empty;
|
||||
};
|
67
src/TUI/Domain/Dependency.cs
Normal file
67
src/TUI/Domain/Dependency.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using TUI.Controls.Components;
|
||||
|
||||
namespace TUI.Domain;
|
||||
|
||||
public record Dependency()
|
||||
{
|
||||
private readonly Version _current;
|
||||
public readonly Brand Brand;
|
||||
public VersionType Type { get; private set; }
|
||||
|
||||
public string Version => $"{_current.Major}.{_current.Minor}.{_current.Patch}";
|
||||
|
||||
public Dependency(string version, Brand brand) : this()
|
||||
{
|
||||
_current = new Version(version);
|
||||
Brand = brand;
|
||||
}
|
||||
|
||||
public VersionStatus Comparison(Dependency outerDependency)
|
||||
{
|
||||
// if (string.IsNullOrEmpty(Version) || string.IsNullOrEmpty(outerDependency.Version))
|
||||
// {
|
||||
// return VersionStatus.NotFound;
|
||||
// }
|
||||
|
||||
var outer = outerDependency._current;
|
||||
|
||||
Type = _current.Type;
|
||||
|
||||
if (_current.Major < outer.Major)
|
||||
{
|
||||
return VersionStatus.TooOld;
|
||||
}
|
||||
|
||||
if (_current.Major > outer.Major)
|
||||
{
|
||||
return VersionStatus.ToNew;
|
||||
}
|
||||
|
||||
if (_current.Minor < outer.Minor)
|
||||
{
|
||||
return VersionStatus.BeNice;
|
||||
}
|
||||
|
||||
if (_current.Minor > outer.Minor)
|
||||
{
|
||||
return VersionStatus.ToNew;
|
||||
}
|
||||
|
||||
if (_current.Patch < outer.Patch)
|
||||
{
|
||||
return VersionStatus.BeNice;
|
||||
}
|
||||
|
||||
if (_current.Patch > outer.Patch)
|
||||
{
|
||||
return VersionStatus.ToNew;
|
||||
}
|
||||
|
||||
if (outer.Type != VersionType.Release)
|
||||
{
|
||||
return VersionStatus.ToNew;
|
||||
}
|
||||
|
||||
return VersionStatus.SoGood;
|
||||
}
|
||||
};
|
3
src/TUI/Domain/Hub.cs
Normal file
3
src/TUI/Domain/Hub.cs
Normal file
@ -0,0 +1,3 @@
|
||||
namespace TUI.Domain;
|
||||
|
||||
public record Hub(string Origin, string Type);
|
@ -1,21 +1,14 @@
|
||||
using TUI.Settings;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
|
||||
namespace TUI.Domain;
|
||||
|
||||
[YamlSerializable]
|
||||
public class Project
|
||||
public record Project(int Id, string Name, IEnumerable<string> Tags, Hub Hub)
|
||||
{
|
||||
[YamlMember]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[YamlMember]
|
||||
public string Name { get; set; }
|
||||
|
||||
[YamlMember]
|
||||
public DependencyDto[] Dependencies { get; set; }
|
||||
|
||||
[YamlMember]
|
||||
public IList<SourceDto> Sources { get; set; }
|
||||
private IEnumerable<Dependency> Dependencies => new List<Dependency>();
|
||||
|
||||
public bool IsPublicNetwork => Tags.Contains("public");
|
||||
|
||||
public bool HasAuth => Tags.Contains("auth");
|
||||
|
||||
public bool SeoDependent => Tags.Contains("seo");
|
||||
|
||||
public bool Legacy => Tags.Contains("legacy");
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
|
||||
namespace TUI.Domain;
|
||||
|
||||
[YamlSerializable]
|
||||
public class Settings
|
||||
{
|
||||
public static Settings Init()
|
||||
{
|
||||
var deserializer = new DeserializerBuilder()
|
||||
.WithNamingConvention(UnderscoredNamingConvention.Instance)
|
||||
.Build();
|
||||
|
||||
using var sr = new StreamReader("settings.yaml");
|
||||
return deserializer.Deserialize<Settings>(sr.ReadToEnd());
|
||||
}
|
||||
|
||||
[YamlMember]
|
||||
public Project[] Projects { get; set; }
|
||||
}
|
32
src/TUI/Domain/Version.cs
Normal file
32
src/TUI/Domain/Version.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using TUI.Controls.Components;
|
||||
|
||||
namespace TUI.Domain;
|
||||
|
||||
public class Version
|
||||
{
|
||||
public readonly int Major;
|
||||
public readonly int Minor;
|
||||
public readonly int Patch;
|
||||
public readonly VersionType Type;
|
||||
|
||||
public Version(string version)
|
||||
{
|
||||
var parts = version.Split('.');
|
||||
|
||||
Major = Convert.ToInt32(parts[0].Replace("^", "").Replace("~", ""));
|
||||
Minor = Convert.ToInt32(parts[1]);
|
||||
Patch = Convert.ToInt32(string.Join("", parts[2].TakeWhile(char.IsDigit)));
|
||||
|
||||
var extension = parts[2].Replace(Patch.ToString(), "");
|
||||
|
||||
Type = extension switch
|
||||
{
|
||||
not null when extension.Contains("rc") => VersionType.Candidate,
|
||||
not null when extension.Contains("beta") => VersionType.Beta,
|
||||
not null when extension.Contains("alpha") => VersionType.Alpha,
|
||||
not null when extension.Contains("canary") => VersionType.Canary,
|
||||
not null when extension.Contains("next") => VersionType.Next,
|
||||
_ => VersionType.Release
|
||||
};
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace TUI;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static bool Have(this IEnumerable<string> array, string findValue)
|
||||
{
|
||||
return array.Any(item => item == findValue);
|
||||
}
|
||||
|
||||
public static string Repeat(this char symbol, int repeatCount)
|
||||
{
|
||||
return repeatCount < 0 ? "" : new string(symbol, repeatCount);
|
||||
}
|
||||
|
||||
public static string RemoveColors(this string text)
|
||||
{
|
||||
return Regex.Replace(text, @"\S\[(\d{0,3}[;m][_]?){0,5}", "");
|
||||
}
|
||||
|
||||
public static int Width(this string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var clearText = text.RemoveColors();
|
||||
var stringInfo = new System.Globalization.StringInfo(clearText);
|
||||
return stringInfo.LengthInTextElements;
|
||||
}
|
||||
|
||||
public static Version? ToVersion(this string textVersion)
|
||||
{
|
||||
var version = textVersion.Replace("^", "").Replace("~", "").Split(".");
|
||||
if (version.Length != 3)
|
||||
return null;
|
||||
var major = Convert.ToInt32(version[0]);
|
||||
var minor = Convert.ToInt32(version[1]);
|
||||
var patch = Convert.ToInt32(version[2].Split('-')[0]);
|
||||
return new Version(major, minor, patch);
|
||||
}
|
||||
}
|
178
src/TUI/Pages/DependenciesPage.cs
Normal file
178
src/TUI/Pages/DependenciesPage.cs
Normal file
@ -0,0 +1,178 @@
|
||||
using TUI.Controls.Components;
|
||||
using TUI.Controls.Containers;
|
||||
using TUI.Controls.Layouts;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
using TUI.Store;
|
||||
|
||||
namespace TUI.Pages;
|
||||
|
||||
public record DependenciesState(HeaderContainer Header, DashboardContainer Dashboard, FooterContainer Footer);
|
||||
|
||||
public class DependenciesPage : PageBase
|
||||
{
|
||||
private DependenciesPage()
|
||||
{
|
||||
}
|
||||
|
||||
public static DependenciesPage Instance { get; } = new();
|
||||
|
||||
private DependenciesStore _store;
|
||||
|
||||
private DependenciesState _state;
|
||||
|
||||
public override void Initial()
|
||||
{
|
||||
var header = new HeaderContainer();
|
||||
var dashboard = new DashboardContainer();
|
||||
var dependenciesHeader = new DependenciesContainer();
|
||||
dependenciesHeader.AddTitleStub();
|
||||
|
||||
foreach (var conventionDependency in _store.ConventionDependencies)
|
||||
{
|
||||
dependenciesHeader.AddDependency(conventionDependency);
|
||||
}
|
||||
|
||||
dashboard.AddChildren(dependenciesHeader);
|
||||
|
||||
foreach (var project in _store.Projects)
|
||||
{
|
||||
var projectDependencies = new DependenciesContainer(project);
|
||||
projectDependencies.AddTitle(new ProjectTitle(project));
|
||||
dashboard.AddChildren(projectDependencies);
|
||||
}
|
||||
|
||||
var breadCrumbs = new BreadCrumbsComponent(" Dependencies", "JavaScript");
|
||||
var footer = new FooterContainer(breadCrumbs);
|
||||
|
||||
_state = new DependenciesState(header, dashboard, footer);
|
||||
}
|
||||
|
||||
public override void Render()
|
||||
{
|
||||
ICanvas canvas = new ConsoleCanvas();
|
||||
var layout = new DashboardLayout(_state.Header, _state.Dashboard, _state.Footer);
|
||||
canvas.Draw(layout);
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
Initial();
|
||||
var projects = _state.Dashboard.GetContent();
|
||||
foreach (var projectDependencies in projects.Cast<DependenciesContainer?>().Skip(1))
|
||||
{
|
||||
if (projectDependencies is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var project = projectDependencies.Project;
|
||||
var actualDependencies = _store.ActualDependencies(project).ToArray();
|
||||
|
||||
if (!actualDependencies.Any())
|
||||
{
|
||||
projectDependencies.AddError();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var conventionDependency in _store.ConventionDependencies)
|
||||
{
|
||||
var actualDependency = actualDependencies.SingleOrDefault(
|
||||
dependency => string.Equals(dependency.Brand.Name, conventionDependency.Brand.Name,
|
||||
StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
if (actualDependency is null)
|
||||
{
|
||||
projectDependencies.AddDependencyStub();
|
||||
continue;
|
||||
}
|
||||
|
||||
var versionType = actualDependency.Comparison(conventionDependency);
|
||||
projectDependencies.AddDependency(actualDependency, versionType);
|
||||
}
|
||||
}
|
||||
|
||||
Render();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Bind()
|
||||
{
|
||||
_store = new DependenciesStore();
|
||||
_store.Bind();
|
||||
}
|
||||
|
||||
// private bool _commandLineInDisplay;
|
||||
|
||||
// private ProjectDto _currentProjectDto;
|
||||
|
||||
// private bool _headerInDisplay = true;
|
||||
|
||||
|
||||
// public string FocusedElement { get; set; } = "";
|
||||
|
||||
// public void OpenDeps(ProjectDto projectDto)
|
||||
// {
|
||||
// _currentProjectDto = projectDto;
|
||||
// var dashboardPosition = new ControlPosition(0, Header.Height);
|
||||
// // DependencyDashboard.IsFocused = true;
|
||||
// // CommandLine.IsFocused = false;
|
||||
// DependenciesView.Render(_currentProjectDto, dashboardPosition);
|
||||
// }
|
||||
//
|
||||
// private void ResizeDependencies()
|
||||
// {
|
||||
// var topPosition = 0;
|
||||
// topPosition += _commandLineInDisplay ? CommandLine.Height : 0;
|
||||
// topPosition += _headerInDisplay ? Header.Height : 0;
|
||||
// var dashboardPosition = new ControlPosition(0, topPosition);
|
||||
// DependenciesView.Render(_currentProjectDto, dashboardPosition);
|
||||
// }
|
||||
//
|
||||
// public void Render()
|
||||
// {
|
||||
// var headerPosition = new ControlPosition(0, 0);
|
||||
// Header.Render(headerPosition);
|
||||
//
|
||||
// const string copyrightText = "Kolosov Aleksandr";
|
||||
// var copyrightPosition = new ControlPosition(
|
||||
// Console.WindowWidth - copyrightText.Width(),
|
||||
// Console.WindowHeight);
|
||||
// CopyrightControl.Render(copyrightText, copyrightPosition);
|
||||
// }
|
||||
//
|
||||
// public void ToggleHeader()
|
||||
// {
|
||||
// _headerInDisplay = !_headerInDisplay;
|
||||
// if (_headerInDisplay)
|
||||
// {
|
||||
// var headerPosition = new ControlPosition(0, 0);
|
||||
// Header.Render(headerPosition);
|
||||
// }
|
||||
//
|
||||
// ResizeDependencies();
|
||||
// }
|
||||
//
|
||||
// public void Next()
|
||||
// {
|
||||
// DependenciesView.Next();
|
||||
// }
|
||||
//
|
||||
// public void Previous()
|
||||
// {
|
||||
// DependenciesView.Previous();
|
||||
// }
|
||||
//
|
||||
// public void OpenCommandLine()
|
||||
// {
|
||||
// var commandLinePosition = new ControlPosition(0, _headerInDisplay ? Header.Height : 0);
|
||||
// // CommandLine.IsFocused = true;
|
||||
// // DependencyDashboard.IsFocused = false;
|
||||
// FocusedElement = nameof(CommandLine);
|
||||
// CommandLine.Render(commandLinePosition);
|
||||
// _commandLineInDisplay = true;
|
||||
// ResizeDependencies();
|
||||
// Console.SetCursorPosition(commandLinePosition.Left + Theme.Padding + Theme.BorderWidth + 2,
|
||||
// commandLinePosition.Top + Theme.BorderWidth);
|
||||
// Console.CursorVisible = true;
|
||||
// }
|
||||
}
|
10
src/TUI/Pages/IPage.cs
Normal file
10
src/TUI/Pages/IPage.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace TUI.Pages;
|
||||
|
||||
interface IPage
|
||||
{
|
||||
void Open();
|
||||
void Initial();
|
||||
void Render();
|
||||
void Bind();
|
||||
void Load();
|
||||
}
|
22
src/TUI/Pages/PageBase.cs
Normal file
22
src/TUI/Pages/PageBase.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TUI.Pages;
|
||||
|
||||
public abstract class PageBase : IPage
|
||||
{
|
||||
public void Open()
|
||||
{
|
||||
Debugger.Log(0, "Event", $"Open page ${GetType().UnderlyingSystemType.Name}\n");
|
||||
Bind();
|
||||
Initial();
|
||||
Render();
|
||||
}
|
||||
|
||||
public abstract void Load();
|
||||
|
||||
public abstract void Initial();
|
||||
|
||||
public abstract void Render();
|
||||
|
||||
public abstract void Bind();
|
||||
}
|
47
src/TUI/Pages/WelcomePage.cs
Normal file
47
src/TUI/Pages/WelcomePage.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using TUI.Controls.Common;
|
||||
using TUI.Controls.Components;
|
||||
using TUI.Controls.Containers;
|
||||
using TUI.Controls.Layouts;
|
||||
using TUI.Controls.Statics;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
|
||||
namespace TUI.Pages;
|
||||
|
||||
public class WelcomePage : PageBase
|
||||
{
|
||||
private WelcomePage()
|
||||
{
|
||||
}
|
||||
|
||||
public static WelcomePage Instance { get; } = new();
|
||||
|
||||
public override void Initial()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Render()
|
||||
{
|
||||
ICanvas canvas = new ConsoleCanvas();
|
||||
|
||||
var header = new StubComponent(new Size(1, 1));
|
||||
|
||||
var logo = new LogoComponent();
|
||||
|
||||
var breadCrumbs = new BreadCrumbsComponent();
|
||||
|
||||
var footer = new FooterContainer(breadCrumbs);
|
||||
|
||||
var layout = new DashboardLayout(header, logo, footer);
|
||||
|
||||
canvas.Draw(layout);
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Bind()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,32 +1,48 @@
|
||||
using TUI.Controls;
|
||||
using Settings = TUI.Domain.Settings;
|
||||
using TUI.Pages;
|
||||
|
||||
|
||||
Console.Clear();
|
||||
Console.CursorVisible = false;
|
||||
|
||||
var settings = Settings.Init();
|
||||
var welcomePage = WelcomePage.Instance;
|
||||
welcomePage.Open();
|
||||
Thread.Sleep(500);
|
||||
|
||||
var display = new Display();
|
||||
display.OpenDeps(settings.Projects[0]);
|
||||
IPage currentPage = DependenciesPage.Instance;
|
||||
currentPage.Open();
|
||||
|
||||
var hotKey = ConsoleKey.NoName;
|
||||
|
||||
ConsoleKeyInfo? key = null;
|
||||
|
||||
var waitCommand = true;
|
||||
do
|
||||
{
|
||||
switch (hotKey)
|
||||
switch (key?.Key)
|
||||
{
|
||||
case ConsoleKey.DownArrow:
|
||||
display.Next();
|
||||
case ConsoleKey.Q:
|
||||
waitCommand = false;
|
||||
break;
|
||||
case ConsoleKey.UpArrow:
|
||||
display.Previous();
|
||||
case ConsoleKey.R:
|
||||
key = null;
|
||||
currentPage.Load();
|
||||
break;
|
||||
case ConsoleKey.E:
|
||||
display.ToggleHeader();
|
||||
case ConsoleKey.D1:
|
||||
key = null;
|
||||
currentPage = DependenciesPage.Instance;
|
||||
Console.Clear();
|
||||
currentPage.Render();
|
||||
break;
|
||||
case ConsoleKey.D0:
|
||||
key = null;
|
||||
currentPage = WelcomePage.Instance;
|
||||
Console.Clear();
|
||||
currentPage.Render();
|
||||
break;
|
||||
default:
|
||||
key = Console.ReadKey(true);
|
||||
break;
|
||||
}
|
||||
} while (waitCommand);
|
||||
|
||||
hotKey = Console.ReadKey(intercept: true).Key;
|
||||
} while (hotKey != ConsoleKey.Q);
|
||||
|
||||
Console.Clear();
|
||||
Console.Clear();
|
||||
Console.CursorVisible = true;
|
11
src/TUI/Providers/Dependencies/DependenciesDto.cs
Normal file
11
src/TUI/Providers/Dependencies/DependenciesDto.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Runtime.Serialization;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace TUI.Providers.Dependencies;
|
||||
|
||||
[DataContract]
|
||||
[YamlSerializable]
|
||||
public class DependenciesDto
|
||||
{
|
||||
[DataMember] [YamlMember] public StackDto[] Stacks { get; set; }
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
using System.Runtime.Serialization;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
|
||||
namespace TUI.Settings;
|
||||
namespace TUI.Providers.Dependencies;
|
||||
|
||||
[DataContract]
|
||||
[YamlSerializable]
|
||||
@ -13,7 +12,7 @@ public class DependencyDto
|
||||
[DataMember]
|
||||
[YamlMember]
|
||||
public string? Name { get; set; }
|
||||
|
||||
|
||||
[DataMember]
|
||||
[YamlMember]
|
||||
public string? Icon
|
126
src/TUI/Providers/Dependencies/DependencyRepository.cs
Normal file
126
src/TUI/Providers/Dependencies/DependencyRepository.cs
Normal file
@ -0,0 +1,126 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using TUI.Domain;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace TUI.Providers.Dependencies;
|
||||
|
||||
public class DependencyRepository
|
||||
{
|
||||
private DependenciesDto? _dependenciesDto;
|
||||
|
||||
private DependenciesDto DependenciesDto
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dependenciesDto is not null)
|
||||
{
|
||||
return _dependenciesDto;
|
||||
}
|
||||
|
||||
var deserializer = new DeserializerBuilder()
|
||||
.WithNamingConvention(UnderscoredNamingConvention.Instance)
|
||||
.Build();
|
||||
|
||||
using var sr = new StreamReader("dependencies.yaml");
|
||||
_dependenciesDto = deserializer.Deserialize<DependenciesDto>(sr.ReadToEnd());
|
||||
|
||||
return _dependenciesDto;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Dependency> ReadConventions(string stackName)
|
||||
{
|
||||
return DependenciesDto.Stacks
|
||||
.Single(stack => stack.Name == stackName)
|
||||
.Conventions
|
||||
.Select(convention =>
|
||||
{
|
||||
var brand = new Brand(convention.Name, convention.Icon, convention.Color);
|
||||
return new Dependency(convention.Version, brand);
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<Project> ReadProjects(string stackName)
|
||||
{
|
||||
var projects = new List<Project>();
|
||||
|
||||
var hubs = DependenciesDto.Stacks
|
||||
.Single(stack => stack.Name == stackName)
|
||||
.Hubs;
|
||||
|
||||
foreach (var hub in hubs)
|
||||
{
|
||||
projects.AddRange(hub
|
||||
.Projects
|
||||
.Select(proj => new Project(proj.Id, proj.Name, proj.Tags, new Hub(hub.Origin, hub.Type))));
|
||||
}
|
||||
|
||||
return projects;
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<Dependency> ReadActual(Project project)
|
||||
{
|
||||
var dependencies = new List<Dependency>();
|
||||
|
||||
if (project.Hub.Type == "gitlab")
|
||||
{
|
||||
var endpoint = GetGitlabEndpoint(project.Hub.Origin, project.Id);
|
||||
using HttpClient client = new();
|
||||
var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult();
|
||||
|
||||
var packageJson = JsonSerializer.Deserialize<PackageJson>(json);
|
||||
|
||||
dependencies.AddRange(Map(packageJson?.Dependencies));
|
||||
dependencies.AddRange(Map(packageJson?.DevDependencies));
|
||||
dependencies.AddRange(Map(packageJson?.Engines));
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private static string GetGitlabEndpoint(string origin, int projectId)
|
||||
{
|
||||
var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT");
|
||||
return $"{origin}/api/v4/projects/{projectId}/repository/files/package.json/raw?" +
|
||||
$"private_token={token}&ref=dev";
|
||||
}
|
||||
|
||||
private static IEnumerable<Dependency> Map(JsonObject? dependencies)
|
||||
{
|
||||
if (dependencies is null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var dependency in dependencies)
|
||||
{
|
||||
var actualVersion = dependency.Value?.ToString();
|
||||
var brand = new Brand(dependency.Key);
|
||||
|
||||
if (actualVersion is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new Dependency(actualVersion, brand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// private static Package DownloadPackage(ProjectDto project)
|
||||
// {
|
||||
// // var endpoint = projectDto.Tags.Have("gitlab") ? GetGitlabEndpoint(projectDto) : projectDto.Repo;
|
||||
// var endpoint = "";
|
||||
// if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage;
|
||||
//
|
||||
// using HttpClient client = new();
|
||||
// var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult();
|
||||
//
|
||||
// Packages.Add(endpoint, package);
|
||||
// return package;
|
||||
// }
|
||||
//
|
15
src/TUI/Providers/Dependencies/HubDto.cs
Normal file
15
src/TUI/Providers/Dependencies/HubDto.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Runtime.Serialization;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace TUI.Providers.Dependencies;
|
||||
|
||||
[DataContract]
|
||||
[YamlSerializable]
|
||||
public class HubDto
|
||||
{
|
||||
[YamlMember] [DataMember] public string Origin { get; set; }
|
||||
|
||||
[YamlMember] [DataMember] public string Type { get; set; }
|
||||
|
||||
[YamlMember] [DataMember] public IEnumerable<ProjectDto> Projects { get; set; }
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using TUI.Engine;
|
||||
|
||||
namespace TUI.Providers.Dependencies;
|
||||
|
||||
namespace TUI.Domain;
|
||||
|
||||
public class Package
|
||||
public class PackageJson
|
||||
{
|
||||
[JsonPropertyName("dependencies")]
|
||||
public JsonObject? Dependencies { get; set; }
|
||||
@ -14,29 +14,20 @@ public class Package
|
||||
|
||||
[JsonPropertyName("engines")]
|
||||
public JsonObject? Engines { get; set; }
|
||||
|
||||
|
||||
public Version? ParseVersion(string? dependencyName)
|
||||
{
|
||||
if (dependencyName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dependencyName == null) return null;
|
||||
|
||||
JsonNode? version = null;
|
||||
|
||||
|
||||
var lowerDependencyName = dependencyName.ToLower();
|
||||
Dependencies?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||
|
||||
if (version == null)
|
||||
{
|
||||
Engines?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||
}
|
||||
|
||||
if (version == null)
|
||||
{
|
||||
DevDependencies?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||
}
|
||||
|
||||
if (version == null) Engines?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||
|
||||
if (version == null) DevDependencies?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||
|
||||
return version?.GetValue<string>().ToVersion();
|
||||
}
|
||||
}
|
16
src/TUI/Providers/Dependencies/ProjectDto.cs
Normal file
16
src/TUI/Providers/Dependencies/ProjectDto.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Runtime.Serialization;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace TUI.Providers.Dependencies;
|
||||
|
||||
[YamlSerializable]
|
||||
public class ProjectDto
|
||||
{
|
||||
[DataMember] [YamlMember] public int Id { get; set; }
|
||||
|
||||
[DataMember] [YamlMember] public string Name { get; set; }
|
||||
|
||||
[DataMember] [YamlMember] public string Deps { get; set; }
|
||||
|
||||
[DataMember] [YamlMember] public IEnumerable<string> Tags { get; set; }
|
||||
}
|
17
src/TUI/Providers/Dependencies/StackDto.cs
Normal file
17
src/TUI/Providers/Dependencies/StackDto.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System.Runtime.Serialization;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace TUI.Providers.Dependencies;
|
||||
|
||||
[DataContract]
|
||||
[YamlSerializable]
|
||||
public class StackDto
|
||||
{
|
||||
[YamlMember] [DataMember] public string Name { get; set; }
|
||||
|
||||
[YamlMember] [DataMember] public string Icon { get; set; }
|
||||
|
||||
[YamlMember] [DataMember] public DependencyDto[] Conventions { get; set; }
|
||||
|
||||
[YamlMember] [DataMember] public IEnumerable<HubDto> Hubs { get; set; }
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
|
||||
namespace TUI.Settings;
|
||||
|
||||
[YamlSerializable]
|
||||
public class SourceDto
|
||||
{
|
||||
[YamlMember]
|
||||
public string[] Tags { get; set; }
|
||||
|
||||
[YamlMember]
|
||||
public string Name { get; set; }
|
||||
|
||||
[YamlMember]
|
||||
public int ProjectId { get; set; } = 0;
|
||||
|
||||
[YamlMember]
|
||||
public string Repo { get; set; }
|
||||
}
|
43
src/TUI/Store/DependenciesStore.cs
Normal file
43
src/TUI/Store/DependenciesStore.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.Diagnostics;
|
||||
using TUI.Controls.Components;
|
||||
using TUI.Domain;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Theme;
|
||||
using TUI.Providers.Dependencies;
|
||||
|
||||
namespace TUI.Store;
|
||||
|
||||
public class DependenciesStore
|
||||
{
|
||||
public IEnumerable<Dependency> ConventionDependencies;
|
||||
|
||||
public IEnumerable<Project> Projects;
|
||||
|
||||
private DependencyRepository Repository = new();
|
||||
|
||||
public IEnumerable<Dependency> ActualDependencies(Project project)
|
||||
{
|
||||
SpeakerComponent.Instance.Shout(Symbols.Download.Info(),
|
||||
$"Fetch actual dependencies for project {project.Name.Main()}");
|
||||
|
||||
try
|
||||
{
|
||||
return Repository.ReadActual(project);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Debugger.Log(0, "error", ex.Message);
|
||||
SpeakerComponent.Instance.Shout(Symbols.Error.Error(), $"Fetch failed for project{project.Name}");
|
||||
return new List<Dependency>();
|
||||
}
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
SpeakerComponent.Instance.Shout("🤔", "Prepare javascript conventions");
|
||||
ConventionDependencies = Repository.ReadConventions("javascript");
|
||||
|
||||
SpeakerComponent.Instance.Shout("🤩", "Prepare javascript projects");
|
||||
Projects = Repository.ReadProjects("javascript");
|
||||
}
|
||||
}
|
@ -1,22 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyVersion>0.1.0</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyVersion>0.1.0</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Pastel" Version="4.1.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="13.1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Pastel" Version="4.1.0"/>
|
||||
<PackageReference Include="YamlDotNet" Version="13.1.1"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="settings.yaml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="dependencies.yaml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>$(MSBuildProjectName).Controls.Tests</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TUI.Engine\TUI.Engine.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
19
src/TUI/UserInterface/CommandLine.cs
Normal file
19
src/TUI/UserInterface/CommandLine.cs
Normal file
@ -0,0 +1,19 @@
|
||||
// using TUI.Components.Controls;
|
||||
// using TUI.Engine;
|
||||
// using TUI.Engine.Controls;
|
||||
//
|
||||
//
|
||||
// namespace TUI.UserInterface;
|
||||
// //
|
||||
// // public class CommandLine : DashboardControl
|
||||
// // {
|
||||
// // public const int Height = 3;
|
||||
// //
|
||||
// // public void Render(ControlPosition position)
|
||||
// // {
|
||||
// // base.Render("Command", position, Height);
|
||||
// //
|
||||
// // Console.SetCursorPosition(position.Left + Theme.BorderWidth + Theme.Padding, position.Top + Theme.BorderWidth);
|
||||
// // Console.Write(">");
|
||||
// // }
|
||||
// // }
|
@ -1,82 +0,0 @@
|
||||
using TUI.Controls;
|
||||
|
||||
|
||||
namespace TUI.UserInterface;
|
||||
|
||||
public class Header : IControl
|
||||
{
|
||||
public const int LogoWidth = 16;
|
||||
public const int Height = 6;
|
||||
public const int MaxHeaderBlocksWidth = 16;
|
||||
|
||||
|
||||
private readonly Dictionary<string, string> _hotKeys = new()
|
||||
{
|
||||
{ "", "select prev" },
|
||||
{ "", "select next" },
|
||||
{ "", "toggle head" },
|
||||
{ "", "quit" },
|
||||
};
|
||||
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
{ "", "too new".Info() },
|
||||
{ "", "so good" },
|
||||
{ "", "be nice".Primary() },
|
||||
{ "", "too old".Warning() }
|
||||
};
|
||||
|
||||
private readonly Dictionary<string, string> _tags = new()
|
||||
{
|
||||
{ Icons.Auth, "Auth" },
|
||||
{ Icons.NetworkPublic, "WWW" },
|
||||
{ Icons.SEO, "SEO" },
|
||||
{ Icons.GitLab, "VCS" },
|
||||
};
|
||||
|
||||
public void Render(Position position)
|
||||
{
|
||||
Console.SetCursorPosition(position.Left, position.Top);
|
||||
|
||||
for (var i = 1; i <= Height; i++)
|
||||
{
|
||||
Console.WriteLine(new string(' ', Console.WindowWidth - LogoWidth));
|
||||
}
|
||||
|
||||
RenderBlock(0, _hints);
|
||||
RenderBlock(1, _tags);
|
||||
RenderBlock(2, Icons.Applications);
|
||||
RenderBlock(3, _hotKeys);
|
||||
RenderLogo();
|
||||
}
|
||||
|
||||
private static void RenderBlock(int blockNumber, Dictionary<string, string> items)
|
||||
{
|
||||
var leftPadding = Theme.Padding + blockNumber * MaxHeaderBlocksWidth;
|
||||
|
||||
var hotKeyNumber = 0;
|
||||
foreach (var item in items)
|
||||
{
|
||||
Console.SetCursorPosition(leftPadding, Theme.Padding + hotKeyNumber++);
|
||||
Console.Write((item.Key + " " + item.Value).Hint());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void RenderLogo()
|
||||
{
|
||||
Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 0);
|
||||
Console.WriteLine(" ╭━━━━┳╮".Primary() + "╱╱".Hint() + "╭━━━╮ ".Primary());
|
||||
Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 1);
|
||||
Console.WriteLine(" ┃╭╮╭╮┃┃".Primary() + "╱╱".Hint() + "╰╮╭╮┃ ".Primary());
|
||||
Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 2);
|
||||
Console.WriteLine(" ╰╯┃┃╰┫┃".Primary() + "╱╱╱".Hint() + "┃┃┃┃ ".Primary());
|
||||
Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 3);
|
||||
Console.WriteLine(" ╱╱".Hint() + "┃┃".Primary() + "╱".Hint() + "┃┃".Primary() + "╱".Hint() +
|
||||
"╭╮┃┃┃┃ ".Primary());
|
||||
Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 4);
|
||||
Console.WriteLine(" ╱╱╱".Hint() + "┃┃".Primary() + "╱".Hint() + "┃╰━╯┣╯╰╯┃ ".Primary());
|
||||
Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 5);
|
||||
Console.WriteLine("╱╱╱╱".Hint() + "╰╯".Primary() + "╱".Hint() + "╰━━━┻━━━╯ ".Primary());
|
||||
}
|
||||
}
|
@ -1,32 +1,15 @@
|
||||
using Pastel;
|
||||
using TUI.Engine;
|
||||
|
||||
|
||||
namespace TUI.UserInterface;
|
||||
|
||||
public static class Icons
|
||||
{
|
||||
public static string GitLab => GetIcon("", "E24329");
|
||||
public static string GitHub => GetIcon("", "ADBAC7");
|
||||
public static string Git => GetIcon("", "F14E32");
|
||||
public static string NetworkPublic => GetIcon("", "00FFFF");
|
||||
public static string NetworkPrivate => GetIcon("");
|
||||
public static string Undefined => GetIcon("");
|
||||
public static string Site => GetIcon("", "BF40BF");
|
||||
public static string Api => GetIcon("", "7F52FF");
|
||||
public static string DockerImage => GetIcon("", "086DD7");
|
||||
public static string NpmPackage => GetIcon("", "CB0000");
|
||||
public static string SEO => GetIcon("", "4285F4");
|
||||
public static string Auth => GetIcon("", "FFD700");
|
||||
public static string NotFound => GetIcon("");
|
||||
|
||||
public readonly static Dictionary<string, string> Applications = new()
|
||||
public static readonly Dictionary<string, string> Applications = new()
|
||||
{
|
||||
{ NpmPackage, "package" },
|
||||
{ DockerImage, "image" },
|
||||
{ Site, "site" },
|
||||
{ Api, "api" },
|
||||
{ Symbols.NpmPackage.Colorized(), "package" },
|
||||
{ Symbols.DockerImage.Colorized(), "image" },
|
||||
{ Symbols.Site.Colorized(), "site" },
|
||||
{ Symbols.Api, "api" }
|
||||
};
|
||||
|
||||
private static string GetIcon(string icon, string? activeColor = null) =>
|
||||
icon.Pastel(activeColor ?? Palette.HintColor);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using TUI.Settings;
|
||||
using TUI.Engine.Theme;
|
||||
using TUI.Providers.Dependencies;
|
||||
|
||||
|
||||
namespace TUI.UserInterface;
|
||||
@ -11,13 +12,16 @@ public static class Panel
|
||||
private const int TagCount = 5;
|
||||
private const int TagWidth = 2;
|
||||
|
||||
public static void RenderRows(SourceDto[] sources, int selectedRowNumber)
|
||||
|
||||
private static int _marginTop;
|
||||
|
||||
public static void RenderRows(ProjectDto[] sources, int selectedRowNumber)
|
||||
{
|
||||
for (var index = 0; index < sources.Length; index++)
|
||||
{
|
||||
Console.SetCursorPosition(Theme.Padding,
|
||||
6 + index + _marginTop + BorderWidth +
|
||||
Theme.Padding);
|
||||
Console.SetCursorPosition(Convert.ToInt32(Indentation.Default),
|
||||
6 + index + _marginTop + BorderWidth +
|
||||
Convert.ToInt32(Indentation.Default));
|
||||
|
||||
if (selectedRowNumber == index + 1)
|
||||
{
|
||||
@ -28,20 +32,18 @@ public static class Panel
|
||||
}
|
||||
|
||||
for (var index = 0; index < sources.Length; index++)
|
||||
{
|
||||
Console.SetCursorPosition(TitleWidth,
|
||||
6 + index + _marginTop + BorderWidth + Theme.Padding);
|
||||
// var source = sources[index];
|
||||
// var package = DownloadPackage(source);
|
||||
// var resultText = package.Dependencies.React;
|
||||
// resultText = new string(' ', ColumnWidth - resultText.Width()) + resultText;
|
||||
// if (selectedRowNumber == index + 1)
|
||||
// {
|
||||
// resultText = resultText.PastelBg("292928");
|
||||
// }
|
||||
//
|
||||
// Console.Write(resultText);
|
||||
}
|
||||
6 + index + _marginTop + BorderWidth + Convert.ToInt32(Indentation.Default));
|
||||
// var source = sources[index];
|
||||
// var package = DownloadPackage(source);
|
||||
// var resultText = package.Dependencies.React;
|
||||
// resultText = new string(' ', ColumnWidth - resultText.Width()) + resultText;
|
||||
// if (selectedRowNumber == index + 1)
|
||||
// {
|
||||
// resultText = resultText.PastelBg("292928");
|
||||
// }
|
||||
//
|
||||
// Console.Write(resultText);
|
||||
// for (var index = 0; index < sources.Length; index++)
|
||||
// {
|
||||
// var loading = true;
|
||||
@ -74,9 +76,6 @@ public static class Panel
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
private static int _marginTop;
|
||||
|
||||
// private static Package DownloadPackage(Source source)
|
||||
// {
|
||||
// if (Packages.TryGetValue(source.Repo, out var downloadPackage))
|
||||
|
@ -1,7 +0,0 @@
|
||||
namespace TUI.UserInterface;
|
||||
|
||||
public static class Theme
|
||||
{
|
||||
public static int Padding = 1;
|
||||
public static int BorderWidth = 1;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user