Browse Source

WarcViewer: index-manager inner collection and query event

HOME 2 months ago
parent
commit
6dd6884ea1

+ 23 - 8
WarcViewerBlazorWinForm/Backend/Warc/WarcIndexManager.cs

@@ -113,11 +113,14 @@ internal class WarcIndexManager : IAssemblyInjectSingleton, IAssemblyInjectSyncS
     private FileDescriptor? _currentFileDescriptor;
     private float? _currentProgress;
 
+    private readonly SortedList<string, WarcIndexEntry> _indexedEntries = new();
+
     public WarcIndexManager(IEventBus eventBus)
     {
         _eventBus = eventBus;
         _eventBus.Subscript<WarcIndexerLoadRequestEvent>(obj => _ = LoadIndexAsync(obj.FileDescriptor));
         _eventBus.Subscript<WarcIndexerStatusRequestEvent>(_ => PublishStatus());
+        _eventBus.Subscript<WarcIndexerQueryRequestEvent>(DoQuery);
     }
 
     private void PublishStatus() => _eventBus.Publish(new WarcIndexerStatusEvent(_isWorking, _queue.Reader.Count, _currentFileDescriptor, _currentProgress));
@@ -144,7 +147,14 @@ internal class WarcIndexManager : IAssemblyInjectSingleton, IAssemblyInjectSyncS
                 var (url, type) = indexContent.Urls[i];
                 batch.Add(new WarcIndexEntry(fd, indexContent.Offsets[i], type, url));
             }
-            _eventBus.Publish(new WarcIndexerLoadedEvent(batch));
+
+            lock (_indexedEntries)
+            {
+                foreach (var item in batch)
+                {
+                    _indexedEntries.Add(item.Url, item);
+                }
+            }
 
             if (indexContent.Offsets.Last() + indexContent.LastEntrySize == len)
             {
@@ -155,6 +165,18 @@ internal class WarcIndexManager : IAssemblyInjectSingleton, IAssemblyInjectSyncS
         } while (true);
     }
 
+    private void DoQuery(WarcIndexerQueryRequestEvent obj)
+    {
+        lock (_indexedEntries)
+        {
+            IEnumerable<WarcIndexEntry> source = _indexedEntries.Values;
+            if (obj.Filter != null) source = source.Where(obj.Filter);
+            var resultSet = source.Skip(obj.PageSize * (obj.PageNumber - 1)).Take(obj.PageSize).ToArray();
+            var result = new WarcIndexerQueryResultEvent(obj.EventId, resultSet, _indexedEntries.Count);
+            _eventBus.Publish(result);
+        }
+    }
+
     public void Start()
     {
         Task.Run(async () =>
@@ -239,11 +261,4 @@ internal class WarcIndexManager : IAssemblyInjectSingleton, IAssemblyInjectSyncS
     }
 
     public void Stop() => _cancellationTokenSource.Cancel();
-
-    public enum IndexingState
-    {
-        NotIndexed,
-        PartIndexed,
-        CompletelyIndexed
-    }
 }

+ 2 - 1
WarcViewerBlazorWinForm/Backend/Warc/WarcIndexManagerEvents.cs

@@ -13,4 +13,5 @@ internal record WarcIndexerStatusEvent(
     float? Position = null
     );
 
-internal record WarcIndexerLoadedEvent(IReadOnlyCollection<WarcIndexEntry> IndexEntries);
+internal record WarcIndexerQueryRequestEvent(Guid EventId, Func<WarcIndexEntry, bool>? Filter, int PageSize = 50, int PageNumber = 1);
+internal record WarcIndexerQueryResultEvent(Guid EventId, WarcIndexEntry[] ResultSet, int TotalCount);

+ 3 - 3
WarcViewerBlazorWinForm/UI/App.razor

@@ -8,7 +8,7 @@
 @inject IEventBus EventBus
 
 <BootstrapBlazorRoot>
-    <Tab @ref="TabControl" IsCard IsOnlyRenderActiveTab>
+    <Tab IsCard IsOnlyRenderActiveTab class="h-100vh">
         <TabItem Text="Open Archive">
             <ArchiveView></ArchiveView>
         </TabItem>
@@ -18,7 +18,7 @@
         <TabItem Text="Viewer">
             <Split Basis="30%">
                 <FirstPaneTemplate>
-                    <div class="d-flex justify-content-center align-items-center h-100"></div>
+                    <div class="d-flex justify-content-center align-items-center h-100">我是左侧面板</div>
                 </FirstPaneTemplate>
                 <SecondPaneTemplate>
                     <div class="d-flex justify-content-center align-items-center h-100">我是右侧面板</div>
@@ -30,7 +30,7 @@
 
 @code
 {
-    private Tab TabControl;
+  
 
     protected override void OnInitialized()
     {

+ 30 - 28
WarcViewerBlazorWinForm/UI/Components/ArchiveView.razor

@@ -11,36 +11,38 @@
 </ConditionBlock>
 
 <ConditionBlock If="_selectedFile != null">
-    <Card>
-        <HeaderTemplate>
-            <div class="w-100">
-                File: @_selectedFile
-                <Button Color="Color.Danger" Icon="fa-solid fa-close" Text="Close" @onclick="CloseFile"></Button>
+    <Row>
+        <Card>
+            <HeaderTemplate>
+                <div class="w-100">
+                    File: @_selectedFile
+                    <Button Color="Color.Danger" Icon="fa-solid fa-close" Text="Close" @onclick="CloseFile"></Button>
+                    <ConditionBlock If="_isDirectlyRead == false">
+                        <Button Color="Color.Primary" Icon="fa-solid fa-check" Text="Load Selected" @onclick="LoadSelectArchiveEntry"></Button>
+                    </ConditionBlock>
+                </div>
+            </HeaderTemplate>
+            <BodyTemplate>
+                <ConditionBlock If="_isDirectlyRead == null">
+                    Opening file...
+                </ConditionBlock>
+                <ConditionBlock If="_isDirectlyRead == true">
+                    TODO: read WARC directly
+                </ConditionBlock>
                 <ConditionBlock If="_isDirectlyRead == false">
-                    <Button Color="Color.Primary" Icon="fa-solid fa-check" Text="Load Selected" @onclick="LoadSelectArchiveEntry"></Button>
+                    <div style="height:100%">
+                        <Table TItem="ArchiveEntryRow" TableSize="TableSize.Compact" OnQueryAsync="@DoQueryResult" @bind-SelectedRows="_selectedRows"
+                               ScrollMode="ScrollMode.Virtual" ShowLineNo LineNoText="#"
+                               IsBordered IsStriped IsFixedHeader ShowSkeleton IsMultipleSelect="true">
+                            <TableColumns>
+                                <TableColumn @bind-Field="@context.Name" Text="Name" Filterable></TableColumn>
+                            </TableColumns>
+                        </Table>
+                    </div>
                 </ConditionBlock>
-            </div>
-        </HeaderTemplate>
-        <BodyTemplate>
-            <ConditionBlock If="_isDirectlyRead == null">
-                Opening file...
-            </ConditionBlock>
-            <ConditionBlock If="_isDirectlyRead == true">
-                TODO: read WARC directly
-            </ConditionBlock>
-            <ConditionBlock If="_isDirectlyRead == false">
-                <div style="height:100%">
-                    <Table TItem="ArchiveEntryRow" OnQueryAsync="@DoQueryResult" @bind-SelectedRows="_selectedRows"
-                           ScrollMode="ScrollMode.Virtual" ShowLineNo LineNoText="#"
-                           IsBordered IsStriped IsFixedHeader ShowSkeleton IsMultipleSelect="true">
-                        <TableColumns>
-                            <TableColumn @bind-Field="@context.Name" Text="Name" Filterable></TableColumn>
-                        </TableColumns>
-                    </Table>
-                </div>
-            </ConditionBlock>
-        </BodyTemplate>
-    </Card>
+            </BodyTemplate>
+        </Card>
+    </Row>
 </ConditionBlock>
 
 @code {

+ 5 - 0
WarcViewerBlazorWinForm/wwwroot/css/app.css

@@ -46,3 +46,8 @@ a, .btn-link {
         right: 0.75rem;
         top: 0.5rem;
     }
+
+
+.h-100vh {
+    height: 100vh;
+}

+ 8 - 8
WarcViewerBlazorWinForm/wwwroot/index.html

@@ -14,16 +14,16 @@
 
 <body>
 
-<div id="app">Loading...</div>
+    <div id="app">Loading...</div>
 
-<div id="blazor-error-ui" data-nosnippet>
-    An unhandled error has occurred.
-    <a href="" class="reload">Reload</a>
-    <a class="dismiss">🗙</a>
-</div>
+    <div id="blazor-error-ui" data-nosnippet>
+        An unhandled error has occurred.
+        <a href="" class="reload">Reload</a>
+        <a class="dismiss">🗙</a>
+    </div>
 
-<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
-<script src="_framework/blazor.webview.js"></script>
+    <script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
+    <script src="_framework/blazor.webview.js"></script>
 
 </body>