Skip to content

Commit 34f200d

Browse files
committed
refactor: 重构组件
1 parent ffd3100 commit 34f200d

8 files changed

Lines changed: 100 additions & 112 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@namespace BootstrapBlazor.Components
2+
@inherits BootstrapModuleComponentBase
3+
4+
<div @attributes="AdditionalAttributes" id="@Id" class="@ClassString" style="@StyleString"></div>

src/components/BootstrapBlazor.Term/Components/Term/Term.razor.cs renamed to src/components/BootstrapBlazor.Term/Components/Term.razor.cs

Lines changed: 89 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,20 @@
33
// Website: https://www.blazor.zone or https://argozhang.github.io/
44

55
using Microsoft.AspNetCore.Components;
6+
using System.Buffers;
67

78
namespace BootstrapBlazor.Components;
89

910
/// <summary>
1011
/// <para lang="zh">Term 终端组件</para>
1112
/// <para lang="en">Term Component</para>
1213
/// </summary>
13-
[JSModuleAutoLoader("./_content/BootstrapBlazor.Term/Components/Term/Term.razor.js", JSObjectReference = true)]
14+
[JSModuleAutoLoader("./_content/BootstrapBlazor.Term/Components/Term.razor.js", JSObjectReference = true)]
1415
public partial class Term
1516
{
1617
/// <summary>
17-
/// <para lang="zh">获得/设置 UI Element</para>
18-
/// <para lang="en">Gets or sets the UI Element.</para>
19-
/// </summary>
20-
private ElementReference Element { get; set; }
21-
22-
/// <summary>
23-
/// <para lang="zh">获得/设置 Options</para>
24-
/// <para lang="en">Gets or sets the Options.</para>
18+
/// <para lang="zh">获得/设置 <see cref="TermOptions"/> 实例</para>
19+
/// <para lang="en">Gets or sets the <see cref="TermOptions"/></para>
2520
/// </summary>
2621
[Parameter]
2722
public TermOptions Options { get; set; } = new TermOptions();
@@ -31,7 +26,7 @@ public partial class Term
3126
/// <para lang="en">Gets or sets the callback when data is received.</para>
3227
/// </summary>
3328
[Parameter]
34-
public Func<byte[], Task>? OnData { get; set; }
29+
public Func<byte[], Task>? OnReceivedAsync { get; set; }
3530

3631
/// <summary>
3732
/// <para lang="zh">获得/设置 终端 Resize 回调</para>
@@ -48,34 +43,29 @@ public partial class Term
4843
public string Height { get; set; } = "300px";
4944

5045
/// <summary>
51-
/// GetClassString
46+
/// <para lang="zh">获得 终端行数</para>
47+
/// <para lang="en">Gets the number of rows in the terminal.</para>
5248
/// </summary>
53-
/// <returns></returns>
54-
private string? GetClassString() => CssBuilder.Default("bb-term")
55-
.AddClassFromAttributes(AdditionalAttributes)
56-
.Build();
49+
public int Rows { get; private set; }
5750

5851
/// <summary>
59-
/// GetStyleString
52+
/// <para lang="zh">获得 终端列数</para>
53+
/// <para lang="en">Gets the number of columns in the terminal.</para>
6054
/// </summary>
61-
/// <returns></returns>
62-
private string? GetStyleString() => CssBuilder.Default()
55+
public int Columns { get; private set; }
56+
57+
private string? ClassString => CssBuilder.Default("bb-term")
58+
.AddClassFromAttributes(AdditionalAttributes)
59+
.Build();
60+
61+
private string? StyleString => CssBuilder.Default()
6362
.AddClass($"height: {Height};", !string.IsNullOrEmpty(Height))
6463
.AddStyleFromAttributes(AdditionalAttributes)
6564
.Build();
6665

6766
/// <summary>
68-
/// OnInitialized
67+
/// <inheritdoc/>
6968
/// </summary>
70-
protected override void OnInitialized()
71-
{
72-
base.OnInitialized();
73-
}
74-
75-
/// <summary>
76-
/// InvokeInitAsync
77-
/// </summary>
78-
/// <returns></returns>
7969
protected override async Task InvokeInitAsync()
8070
{
8171
await InvokeVoidAsync("init", Id, Interop, Options);
@@ -86,28 +76,45 @@ protected override async Task InvokeInitAsync()
8676
/// <para lang="en">Writes data to the terminal.</para>
8777
/// </summary>
8878
/// <param name="data"></param>
89-
/// <returns></returns>
9079
public async Task Write(string data)
9180
{
9281
await InvokeVoidAsync("write", Id, data);
9382
}
9483

9584
/// <summary>
96-
/// <para lang="zh">写入一行数据</para>
85+
/// <para lang="zh">写入一行文本数据</para>
9786
/// <para lang="en">Writes a line of data to the terminal.</para>
9887
/// </summary>
9988
/// <param name="data"></param>
100-
/// <returns></returns>
10189
public async Task WriteLine(string data)
10290
{
10391
await InvokeVoidAsync("writeln", Id, data);
10492
}
10593

94+
/// <summary>
95+
/// <para lang="zh">写入数据 (<see langword="byte[]"/>)</para>
96+
/// <para lang="en">Writes byte array data to the terminal.</para>
97+
/// </summary>
98+
/// <param name="data"></param>
99+
public async Task Write(byte[] data)
100+
{
101+
await InvokeVoidAsync("write", Id, data);
102+
}
103+
104+
/// <summary>
105+
/// <para lang="zh">写入数据 (<see langword="Memory[]"/>)</para>
106+
/// <para lang="en">Writes data to the terminal.</para>
107+
/// </summary>
108+
/// <param name="data"></param>
109+
public async Task Write(Memory<byte> data)
110+
{
111+
await InvokeVoidAsync("write", Id, data);
112+
}
113+
106114
/// <summary>
107115
/// <para lang="zh">清空终端</para>
108116
/// <para lang="en">Clears the terminal.</para>
109117
/// </summary>
110-
/// <returns></returns>
111118
public async Task Clear()
112119
{
113120
await InvokeVoidAsync("clear", Id);
@@ -118,116 +125,105 @@ public async Task Clear()
118125
/// <para lang="en">Connects a stream.</para>
119126
/// </summary>
120127
/// <param name="stream"></param>
121-
/// <returns></returns>
122-
public async Task Open(Stream stream)
123-
{
124-
_stream = stream;
125-
_cancellationTokenSource = new CancellationTokenSource();
126-
_ = ReadStreamAsync();
127-
128-
await Task.CompletedTask;
129-
}
128+
public Task Open(Stream stream) => ReadStreamAsync(stream);
130129

131130
private Stream? _stream;
132131
private CancellationTokenSource? _cancellationTokenSource;
133132

134-
private async Task ReadStreamAsync()
133+
private async Task ReadStreamAsync(Stream stream)
135134
{
136-
if (_stream == null) return;
135+
if (stream is { CanRead: true })
136+
{
137+
_ = Task.Run(() => LoopRead(stream));
138+
}
139+
}
140+
141+
private async Task LoopRead(Stream stream)
142+
{
143+
_stream = stream;
144+
145+
if (_cancellationTokenSource is { IsCancellationRequested: false })
146+
{
147+
_cancellationTokenSource.Cancel();
148+
_cancellationTokenSource.Dispose();
149+
}
137150

138-
var buffer = new byte[1024];
139151
try
140152
{
141-
while (!_cancellationTokenSource!.IsCancellationRequested)
153+
_cancellationTokenSource = new();
154+
using var memoryOwner = MemoryPool<byte>.Shared.Rent(1024);
155+
var buffer = memoryOwner.Memory;
156+
while (_cancellationTokenSource is { IsCancellationRequested: false })
142157
{
143-
var read = await _stream.ReadAsync(buffer, _cancellationTokenSource.Token);
144-
if (read == 0) break;
145-
var data = new byte[read];
146-
Array.Copy(buffer, data, read);
147-
await Write(data);
158+
var length = await stream.ReadAsync(buffer, _cancellationTokenSource.Token);
159+
if (length == 0)
160+
{
161+
break;
162+
}
163+
await Write(buffer.Slice(0, length));
148164
}
149165
}
150-
catch (TaskCanceledException)
166+
catch (OperationCanceledException)
151167
{
152168
// ignored
153169
}
154170
catch (Exception ex)
155171
{
156-
// Handle error
157172
await WriteLine($"\r\nError: {ex.Message}");
158173
}
159174
}
160175

161176
/// <summary>
162-
/// <para lang="zh">写入数据 (Byte[])</para>
163-
/// <para lang="en">Writes byte array data to the terminal.</para>
177+
/// <para lang="zh">收到数据回调方法由 JavaScript 调用</para>
178+
/// <para lang="en">Callback when data is received from JS</para>
164179
/// </summary>
165180
/// <param name="data"></param>
166-
/// <returns></returns>
167-
public async Task Write(byte[] data)
168-
{
169-
await InvokeVoidAsync("write", Id, data);
170-
}
171-
172-
/// <summary>
173-
/// <para lang="zh">收到数据 JSInvoke</para>
174-
/// <para lang="en">Callback when data is received from JS.</para>
175-
/// </summary>
176-
/// <param name="data"></param>
177-
/// <returns></returns>
178181
[JSInvokable]
179182
public async Task OnDataAsync(byte[] data)
180183
{
181-
if (_stream != null && _stream.CanWrite)
184+
if (_stream is { CanWrite: true })
182185
{
183186
await _stream.WriteAsync(data);
184187
await _stream.FlushAsync();
185188
}
186189

187-
if (OnData != null)
190+
if (OnReceivedAsync != null)
188191
{
189-
await OnData(data);
192+
await OnReceivedAsync(data);
190193
}
191194
}
192195

193-
/// <summary>
194-
/// Dispose
195-
/// </summary>
196-
/// <param name="disposing"></param>
197-
protected override async ValueTask DisposeAsync(bool disposing)
198-
{
199-
_cancellationTokenSource?.Cancel();
200-
_cancellationTokenSource?.Dispose();
201-
await base.DisposeAsync(disposing);
202-
}
203-
204-
/// <summary>
205-
/// <para lang="zh">获得 终端行数</para>
206-
/// <para lang="en">Gets the number of rows in the terminal.</para>
207-
/// </summary>
208-
public int Rows { get; private set; }
209-
210-
/// <summary>
211-
/// <para lang="zh">获得 终端列数</para>
212-
/// <para lang="en">Gets the number of columns in the terminal.</para>
213-
/// </summary>
214-
public int Columns { get; private set; }
215-
216196
/// <summary>
217197
/// <para lang="zh">Resize JSInvoke</para>
218198
/// <para lang="en">Callback when terminal is resized from JS.</para>
219199
/// </summary>
220200
/// <param name="rows"></param>
221201
/// <param name="cols"></param>
222-
/// <returns></returns>
223202
[JSInvokable]
224203
public async Task OnResizeAsync(int rows, int cols)
225204
{
226205
Rows = rows;
227206
Columns = cols;
207+
228208
if (OnResize != null)
229209
{
230210
await OnResize(rows, cols);
231211
}
232212
}
213+
214+
/// <summary>
215+
/// <inheritdoc/>
216+
/// </summary>
217+
/// <param name="disposing"></param>
218+
protected override async ValueTask DisposeAsync(bool disposing)
219+
{
220+
await base.DisposeAsync(disposing);
221+
222+
if (disposing)
223+
{
224+
_cancellationTokenSource?.Cancel();
225+
_cancellationTokenSource?.Dispose();
226+
_cancellationTokenSource = null;
227+
}
228+
}
233229
}

src/components/BootstrapBlazor.Term/Components/Term/Term.razor.js renamed to src/components/BootstrapBlazor.Term/Components/Term.razor.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
1-
import "../../lib/xterm/xterm.js";
2-
import "../../lib/xterm/xterm-addon-fit.js";
1+
import "../lib/xterm.js";
2+
import "../lib/xterm-addon-fit.js";
3+
import { addLink } from '../../BootstrapBlazor/modules/utility.js'
4+
import Data from '../../BootstrapBlazor/modules/data.js'
5+
6+
export async function init(id, invoke, options) {
7+
await addLink('./_content/BootstrapBlazor.Term/lib/xterm.css');
38

4-
export function init(id, invoke, options) {
59
const el = document.getElementById(id);
610
if (el === null) {
711
return;
812
}
913

10-
// Load CSS
11-
const linkId = "bb-term-css";
12-
if (!document.getElementById(linkId)) {
13-
const link = document.createElement('link');
14-
link.id = linkId;
15-
link.rel = 'stylesheet';
16-
link.href = './_content/BootstrapBlazor.Term/lib/xterm/xterm.css';
17-
document.head.appendChild(link);
18-
}
19-
2014
const term = new Terminal({
2115
fontFamily: options.fontFamily || "Consolas, 'Courier New', monospace",
2216
fontSize: options.fontSize || 14,
@@ -41,12 +35,10 @@ export function init(id, invoke, options) {
4135
invoke.invokeMethodAsync("OnResizeAsync", size.rows, size.cols);
4236
});
4337

44-
// Store instance
4538
el.term = term;
4639
el.fitAddon = fitAddon;
4740
el.invoke = invoke;
4841

49-
// Window resize handling
5042
const resizeHandler = () => {
5143
try {
5244
fitAddon.fit();

src/components/BootstrapBlazor.Term/Components/Term/Term.razor

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/components/BootstrapBlazor.Term/Components/Term/TermOptions.cs renamed to src/components/BootstrapBlazor.Term/Components/TermOptions.cs

File renamed without changes.

src/components/BootstrapBlazor.Term/wwwroot/lib/xterm/xterm-addon-fit.js renamed to src/components/BootstrapBlazor.Term/wwwroot/lib/xterm-addon-fit.js

File renamed without changes.

src/components/BootstrapBlazor.Term/wwwroot/lib/xterm/xterm.css renamed to src/components/BootstrapBlazor.Term/wwwroot/lib/xterm.css

File renamed without changes.

src/components/BootstrapBlazor.Term/wwwroot/lib/xterm/xterm.js renamed to src/components/BootstrapBlazor.Term/wwwroot/lib/xterm.js

File renamed without changes.

0 commit comments

Comments
 (0)