mirror of
https://github.com/dnwSilver/tld.git
synced 2024-11-25 16:42:07 +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
|
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}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI", "src\TUI\TUI.csproj", "{F92C03F7-2A65-4D0A-9736-13E749AF6903}"
|
||||||
EndProject
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{F92C03F7-2A65-4D0A-9736-13E749AF6903}.Release|Any CPU.Build.0 = 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
|
EndGlobalSection
|
||||||
EndGlobal
|
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;
|
using Pastel;
|
||||||
|
|
||||||
|
namespace TUI.Engine.Theme;
|
||||||
namespace TUI.UserInterface;
|
|
||||||
|
|
||||||
public static class Palette
|
public static class Palette
|
||||||
{
|
{
|
||||||
public const string HoverColor = "292928";
|
public const string HoverColor = "292928";
|
||||||
public const string PrimaryColor = "84BA64";
|
public const string PrimaryColor = "84BA64";
|
||||||
public const string HintColor = "71797E";
|
public const string HintColor = "71797E";
|
||||||
|
public const string DisableColor = "303030";
|
||||||
public const string ErrorColor = "CA3433";
|
public const string ErrorColor = "CA3433";
|
||||||
public const string WarningColor = "EC9706";
|
public const string WarningColor = "EC9706";
|
||||||
public const string InfoColor = "25799F";
|
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 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 Disable(this string currentText) => currentText.RemoveColors().Pastel(HintColor);
|
||||||
|
|
||||||
public static string Warning(this string currentText) => currentText.Pastel(WarningColor);
|
public static string Warning(this string currentText) => currentText.Pastel(WarningColor);
|
||||||
|
|
||||||
public static string Error(this string currentText) => currentText.Pastel(ErrorColor);
|
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 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;
|
namespace TUI.Domain;
|
||||||
|
|
||||||
[YamlSerializable]
|
public record Project(int Id, string Name, IEnumerable<string> Tags, Hub Hub)
|
||||||
public class Project
|
|
||||||
{
|
{
|
||||||
[YamlMember]
|
private IEnumerable<Dependency> Dependencies => new List<Dependency>();
|
||||||
public string Icon { get; set; }
|
|
||||||
|
public bool IsPublicNetwork => Tags.Contains("public");
|
||||||
[YamlMember]
|
|
||||||
public string Name { get; set; }
|
public bool HasAuth => Tags.Contains("auth");
|
||||||
|
|
||||||
[YamlMember]
|
public bool SeoDependent => Tags.Contains("seo");
|
||||||
public DependencyDto[] Dependencies { get; set; }
|
|
||||||
|
public bool Legacy => Tags.Contains("legacy");
|
||||||
[YamlMember]
|
|
||||||
public IList<SourceDto> Sources { get; set; }
|
|
||||||
}
|
}
|
@ -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 TUI.Pages;
|
||||||
using Settings = TUI.Domain.Settings;
|
|
||||||
|
|
||||||
|
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
Console.CursorVisible = false;
|
Console.CursorVisible = false;
|
||||||
|
|
||||||
var settings = Settings.Init();
|
var welcomePage = WelcomePage.Instance;
|
||||||
|
welcomePage.Open();
|
||||||
|
Thread.Sleep(500);
|
||||||
|
|
||||||
var display = new Display();
|
IPage currentPage = DependenciesPage.Instance;
|
||||||
display.OpenDeps(settings.Projects[0]);
|
currentPage.Open();
|
||||||
|
|
||||||
var hotKey = ConsoleKey.NoName;
|
|
||||||
|
ConsoleKeyInfo? key = null;
|
||||||
|
|
||||||
|
var waitCommand = true;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
switch (hotKey)
|
switch (key?.Key)
|
||||||
{
|
{
|
||||||
case ConsoleKey.DownArrow:
|
case ConsoleKey.Q:
|
||||||
display.Next();
|
waitCommand = false;
|
||||||
break;
|
break;
|
||||||
case ConsoleKey.UpArrow:
|
case ConsoleKey.R:
|
||||||
display.Previous();
|
key = null;
|
||||||
|
currentPage.Load();
|
||||||
break;
|
break;
|
||||||
case ConsoleKey.E:
|
case ConsoleKey.D1:
|
||||||
display.ToggleHeader();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
} while (waitCommand);
|
||||||
|
|
||||||
hotKey = Console.ReadKey(intercept: true).Key;
|
Console.Clear();
|
||||||
} while (hotKey != ConsoleKey.Q);
|
Console.CursorVisible = true;
|
||||||
|
|
||||||
Console.Clear();
|
|
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 System.Runtime.Serialization;
|
||||||
using YamlDotNet.Serialization;
|
using YamlDotNet.Serialization;
|
||||||
|
|
||||||
|
namespace TUI.Providers.Dependencies;
|
||||||
namespace TUI.Settings;
|
|
||||||
|
|
||||||
[DataContract]
|
[DataContract]
|
||||||
[YamlSerializable]
|
[YamlSerializable]
|
||||||
@ -13,7 +12,7 @@ public class DependencyDto
|
|||||||
[DataMember]
|
[DataMember]
|
||||||
[YamlMember]
|
[YamlMember]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
[YamlMember]
|
[YamlMember]
|
||||||
public string? Icon
|
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.Nodes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using TUI.Engine;
|
||||||
|
|
||||||
|
namespace TUI.Providers.Dependencies;
|
||||||
|
|
||||||
namespace TUI.Domain;
|
public class PackageJson
|
||||||
|
|
||||||
public class Package
|
|
||||||
{
|
{
|
||||||
[JsonPropertyName("dependencies")]
|
[JsonPropertyName("dependencies")]
|
||||||
public JsonObject? Dependencies { get; set; }
|
public JsonObject? Dependencies { get; set; }
|
||||||
@ -14,29 +14,20 @@ public class Package
|
|||||||
|
|
||||||
[JsonPropertyName("engines")]
|
[JsonPropertyName("engines")]
|
||||||
public JsonObject? Engines { get; set; }
|
public JsonObject? Engines { get; set; }
|
||||||
|
|
||||||
public Version? ParseVersion(string? dependencyName)
|
public Version? ParseVersion(string? dependencyName)
|
||||||
{
|
{
|
||||||
if (dependencyName == null)
|
if (dependencyName == null) return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonNode? version = null;
|
JsonNode? version = null;
|
||||||
|
|
||||||
var lowerDependencyName = dependencyName.ToLower();
|
var lowerDependencyName = dependencyName.ToLower();
|
||||||
Dependencies?.TryGetPropertyValue(lowerDependencyName, out version);
|
Dependencies?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||||
|
|
||||||
if (version == null)
|
if (version == null) Engines?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||||
{
|
|
||||||
Engines?.TryGetPropertyValue(lowerDependencyName, out version);
|
if (version == null) DevDependencies?.TryGetPropertyValue(lowerDependencyName, out version);
|
||||||
}
|
|
||||||
|
|
||||||
if (version == null)
|
|
||||||
{
|
|
||||||
DevDependencies?.TryGetPropertyValue(lowerDependencyName, out version);
|
|
||||||
}
|
|
||||||
|
|
||||||
return version?.GetValue<string>().ToVersion();
|
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">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AssemblyVersion>0.1.0</AssemblyVersion>
|
<AssemblyVersion>0.1.0</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Pastel" Version="4.1.0" />
|
<PackageReference Include="Pastel" Version="4.1.0"/>
|
||||||
<PackageReference Include="YamlDotNet" Version="13.1.1" />
|
<PackageReference Include="YamlDotNet" Version="13.1.1"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="settings.yaml">
|
<None Update="dependencies.yaml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</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>
|
</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;
|
namespace TUI.UserInterface;
|
||||||
|
|
||||||
public static class Icons
|
public static class Icons
|
||||||
{
|
{
|
||||||
public static string GitLab => GetIcon("", "E24329");
|
public static readonly Dictionary<string, string> Applications = new()
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
{ NpmPackage, "package" },
|
{ Symbols.NpmPackage.Colorized(), "package" },
|
||||||
{ DockerImage, "image" },
|
{ Symbols.DockerImage.Colorized(), "image" },
|
||||||
{ Site, "site" },
|
{ Symbols.Site.Colorized(), "site" },
|
||||||
{ Api, "api" },
|
{ 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;
|
namespace TUI.UserInterface;
|
||||||
@ -11,13 +12,16 @@ public static class Panel
|
|||||||
private const int TagCount = 5;
|
private const int TagCount = 5;
|
||||||
private const int TagWidth = 2;
|
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++)
|
for (var index = 0; index < sources.Length; index++)
|
||||||
{
|
{
|
||||||
Console.SetCursorPosition(Theme.Padding,
|
Console.SetCursorPosition(Convert.ToInt32(Indentation.Default),
|
||||||
6 + index + _marginTop + BorderWidth +
|
6 + index + _marginTop + BorderWidth +
|
||||||
Theme.Padding);
|
Convert.ToInt32(Indentation.Default));
|
||||||
|
|
||||||
if (selectedRowNumber == index + 1)
|
if (selectedRowNumber == index + 1)
|
||||||
{
|
{
|
||||||
@ -28,20 +32,18 @@ public static class Panel
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (var index = 0; index < sources.Length; index++)
|
for (var index = 0; index < sources.Length; index++)
|
||||||
{
|
|
||||||
Console.SetCursorPosition(TitleWidth,
|
Console.SetCursorPosition(TitleWidth,
|
||||||
6 + index + _marginTop + BorderWidth + Theme.Padding);
|
6 + index + _marginTop + BorderWidth + Convert.ToInt32(Indentation.Default));
|
||||||
// var source = sources[index];
|
// var source = sources[index];
|
||||||
// var package = DownloadPackage(source);
|
// var package = DownloadPackage(source);
|
||||||
// var resultText = package.Dependencies.React;
|
// var resultText = package.Dependencies.React;
|
||||||
// resultText = new string(' ', ColumnWidth - resultText.Width()) + resultText;
|
// resultText = new string(' ', ColumnWidth - resultText.Width()) + resultText;
|
||||||
// if (selectedRowNumber == index + 1)
|
// if (selectedRowNumber == index + 1)
|
||||||
// {
|
// {
|
||||||
// resultText = resultText.PastelBg("292928");
|
// resultText = resultText.PastelBg("292928");
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Console.Write(resultText);
|
// Console.Write(resultText);
|
||||||
}
|
|
||||||
// for (var index = 0; index < sources.Length; index++)
|
// for (var index = 0; index < sources.Length; index++)
|
||||||
// {
|
// {
|
||||||
// var loading = true;
|
// var loading = true;
|
||||||
@ -74,9 +76,6 @@ public static class Panel
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static int _marginTop;
|
|
||||||
|
|
||||||
// private static Package DownloadPackage(Source source)
|
// private static Package DownloadPackage(Source source)
|
||||||
// {
|
// {
|
||||||
// if (Packages.TryGetValue(source.Repo, out var downloadPackage))
|
// 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