Skip to content

Commit 86f583e

Browse files
puk06Copilot
andauthored
refactor: implement CacheManager class and update PageManager and ScrollManager (#343)
* refactor: implement CacheManager class and update PageManager and ScrollManager to use new methods * fix: restore correct pagination default and use HashSet for O(1) lookup in PageManager/ScrollManager Agent-Logs-Url: https://github.com/puk06/VRC-Avatar-Explorer/sessions/895f399d-229a-474a-9476-e14ae19931ef Co-authored-by: puk06 <86549420+puk06@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 8ba6576 commit 86f583e

4 files changed

Lines changed: 100 additions & 81 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace AvatarExplorer.Core.Services.System;
2+
3+
public class CacheManager<T, TValue>(TValue? defaultValue = default) where T : notnull
4+
{
5+
private readonly TValue? defaultValue = defaultValue;
6+
private readonly Dictionary<T, TValue> _cache = [];
7+
8+
public virtual void Add(T key, TValue value)
9+
{
10+
_cache[key] = value;
11+
}
12+
13+
public virtual bool TryGetValue(T key, out TValue? value)
14+
{
15+
if (_cache.TryGetValue(key, out TValue? cachedValue))
16+
{
17+
value = cachedValue;
18+
return true;
19+
}
20+
21+
value = defaultValue;
22+
return false;
23+
}
24+
25+
public virtual TValue? Get(T key)
26+
{
27+
if (TryGetValue(key, out TValue? value))
28+
{
29+
return value;
30+
}
31+
32+
return defaultValue;
33+
}
34+
35+
public virtual bool ContainsKey(T key) => _cache.ContainsKey(key);
36+
public virtual bool Remove(T key) => _cache.Remove(key);
37+
38+
public T[] GetKeys() => _cache.Keys.ToArray();
39+
public TValue[] GetValues() => _cache.Values.ToArray();
40+
41+
public virtual void Clear() => _cache.Clear();
42+
}
Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,44 @@
11
using System.Collections.Generic;
2-
using System.Linq;
32
using AvatarExplorer.Core.Models.Items;
3+
using AvatarExplorer.Core.Services.System;
44

55
namespace AvatarExplorer.UI.Services.ViewControl;
66

7-
internal class PageManager
7+
internal class PageManager(int defaultValue) : CacheManager<ItemTagStates, int>(defaultValue)
88
{
9-
private readonly Dictionary<ItemTagStates, int> _currentPageStates = new()
10-
{
11-
{ ItemTagStates.SearchItem, 0 },
12-
{ ItemTagStates.RootAvatar, 0 },
13-
{ ItemTagStates.RootAuthor, 0 },
14-
{ ItemTagStates.RootCategory, 0 },
15-
{ ItemTagStates.RootItem, 0 },
16-
{ ItemTagStates.RootSelectedCategory, 0 },
17-
{ ItemTagStates.RootSelectedItem, 0 },
18-
{ ItemTagStates.ItemFileCategoryOpen, 0 }
19-
};
9+
private static readonly HashSet<ItemTagStates> _supportedPageStates =
10+
[
11+
ItemTagStates.SearchItem,
12+
ItemTagStates.RootAvatar,
13+
ItemTagStates.RootAuthor,
14+
ItemTagStates.RootCategory,
15+
ItemTagStates.RootItem,
16+
ItemTagStates.RootSelectedCategory,
17+
ItemTagStates.RootSelectedItem,
18+
ItemTagStates.ItemFileCategoryOpen
19+
];
2020

21-
private static readonly ItemTagStates[] _leftPanelStates =
21+
private static readonly HashSet<ItemTagStates> _leftPanelStates =
2222
[
2323
ItemTagStates.RootAvatar,
2424
ItemTagStates.RootAuthor,
2525
ItemTagStates.RootCategory
2626
];
2727

28-
internal bool IsPageSupported(ItemTagStates itemTagState) => _currentPageStates.ContainsKey(itemTagState);
29-
internal bool IsStateResetSupported(ItemTagStates itemTagState) => !_leftPanelStates.Contains(itemTagState);
30-
31-
internal int GetPage(ItemTagStates itemTagState) => IsPageSupported(itemTagState) ? _currentPageStates[itemTagState] : -1;
32-
internal void SetPage(ItemTagStates itemTagState, int value)
28+
public override int Get(ItemTagStates key)
3329
{
34-
if (!IsPageSupported(itemTagState)) return;
35-
_currentPageStates[itemTagState] = value;
30+
if (ContainsKey(key)) return base.Get(key);
31+
return _supportedPageStates.Contains(key) ? 0 : base.Get(key);
3632
}
3733

38-
internal void ResetPageValue(ItemTagStates itemTagState)
34+
public override bool Remove(ItemTagStates key)
3935
{
40-
if (!IsPageSupported(itemTagState) || !IsStateResetSupported(itemTagState)) return;
41-
SetPage(itemTagState, 0);
36+
if (_leftPanelStates.Contains(key)) return false; // 左パネルのページ情報は消さないようにする
37+
return base.Remove(key);
4238
}
43-
internal void ResetAllPageValues()
39+
40+
public override void Clear()
4441
{
45-
foreach (ItemTagStates key in GetKeys().Where(IsStateResetSupported))
46-
ResetPageValue(key);
42+
foreach (var state in GetKeys()) Remove(state);
4743
}
48-
49-
internal ItemTagStates[] GetKeys() => _currentPageStates.Keys.ToArray();
5044
}
Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,25 @@
11
using System.Collections.Generic;
2-
using System.Linq;
32
using Avalonia;
43
using AvatarExplorer.Core.Models.Items;
4+
using AvatarExplorer.Core.Services.System;
55

66
namespace AvatarExplorer.UI.Services.ViewControl;
77

8-
internal class ScrollManager
8+
internal class ScrollManager(Vector defaultValue) : CacheManager<ItemTagStates, Vector>(defaultValue)
99
{
10-
private static readonly Vector Empty = new();
11-
private readonly Dictionary<ItemTagStates, Vector> _currentScrollValues = new()
12-
{
13-
{ ItemTagStates.SearchItem, Empty },
14-
{ ItemTagStates.RootItem, Empty },
15-
{ ItemTagStates.RootSelectedCategory, Empty },
16-
{ ItemTagStates.RootSelectedItem, Empty },
17-
{ ItemTagStates.ItemFileCategory, Empty },
18-
{ ItemTagStates.ItemFileCategoryOpen, Empty }
19-
};
20-
21-
internal bool IsScrollSupported(ItemTagStates itemTagState) => _currentScrollValues.ContainsKey(itemTagState);
22-
23-
internal Vector GetScrollValue(ItemTagStates itemTagState) => IsScrollSupported(itemTagState) ? _currentScrollValues[itemTagState] : new();
24-
internal void SetScroll(ItemTagStates itemTagState, Vector value)
25-
{
26-
if (!IsScrollSupported(itemTagState)) return;
27-
_currentScrollValues[itemTagState] = value;
28-
}
10+
private static readonly HashSet<ItemTagStates> _supportedScrollStates =
11+
[
12+
ItemTagStates.SearchItem,
13+
ItemTagStates.RootItem,
14+
ItemTagStates.RootSelectedCategory,
15+
ItemTagStates.RootSelectedItem,
16+
ItemTagStates.ItemFileCategory,
17+
ItemTagStates.ItemFileCategoryOpen
18+
];
2919

30-
internal void ResetScrollValue(ItemTagStates itemTagState)
31-
{
32-
if (!IsScrollSupported(itemTagState)) return;
33-
SetScroll(itemTagState, Empty);
34-
}
35-
internal void ResetAllScrollValues()
20+
public override void Add(ItemTagStates key, Vector value)
3621
{
37-
foreach (ItemTagStates key in GetKeys())
38-
ResetScrollValue(key);
22+
if (!_supportedScrollStates.Contains(key)) return;
23+
base.Add(key, value);
3924
}
40-
41-
internal ItemTagStates[] GetKeys() => _currentScrollValues.Keys.ToArray();
4225
}

AvatarExplorer.UI/Views/MainWindow.axaml.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ namespace AvatarExplorer.UI;
4040

4141
public partial class MainWindow : Window
4242
{
43-
private readonly PageManager _main_pageManager = new();
44-
private readonly ScrollManager _main_scrollManager = new();
43+
private readonly PageManager _main_pageManager = new(defaultValue: -1);
44+
private readonly ScrollManager _main_scrollManager = new(defaultValue: Vector.Zero);
4545

4646
private string _main_lastSearchTextCache = string.Empty; // 最後に実行された検索のキャッシュ
4747
private string _main_searchTextCache = string.Empty;
@@ -267,7 +267,7 @@ private void Main_RenderLeftPanel()
267267
}
268268
}
269269

270-
int currentPage = _main_pageManager.GetPage(customState); // -1が返された場合は対応していないStateのため、全てのアイテムを表示してあげる
270+
int currentPage = _main_pageManager.Get(customState); // -1が返された場合は対応していないStateのため、全てのアイテムを表示してあげる
271271

272272
foreach (ItemCountInfo itemCountInfo in currentPage != -1 ? items.Skip(currentPage * UserPreferences.ItemsPerPage).Take(UserPreferences.ItemsPerPage) : items)
273273
{
@@ -288,7 +288,7 @@ private void Main_RenderLeftPanel()
288288

289289
// スクロール位置をDictionaryから復元してあげる
290290
Main_LeftPanelScrollViewer.Presenter?.UpdateLayout();
291-
Main_LeftPanelScrollViewer.Offset = _main_scrollManager.GetScrollValue(customState);
291+
Main_LeftPanelScrollViewer.Offset = _main_scrollManager.Get(customState);
292292
}
293293
private void LeftPanel_ItemButton_Click(object? sender, RoutedEventArgs e)
294294
{
@@ -306,8 +306,8 @@ private void LeftPanel_ItemButton_Click(object? sender, RoutedEventArgs e)
306306

307307
if (button.Tag is PageButtonInfo pageButtonInfo)
308308
{
309-
_main_pageManager.SetPage(pageButtonInfo.ItemTagState, pageButtonInfo.NextPageValue);
310-
_main_scrollManager.SetScroll(pageButtonInfo.ItemTagState, new()); // 今のStateのページをリセットしてあげる
309+
_main_pageManager.Add(pageButtonInfo.ItemTagState, pageButtonInfo.NextPageValue);
310+
_main_scrollManager.Remove(pageButtonInfo.ItemTagState); // 今のStateのページをリセットしてあげる
311311
Main_RenderLeftPanel();
312312
}
313313
}
@@ -332,7 +332,7 @@ private void Main_RenderRightPanel()
332332

333333
_main_lastRightPanelItemTagState = itemTagState;
334334

335-
int currentPage = _main_pageManager.GetPage(itemTagState); // -1が返された場合は対応していないStateのため、全てのアイテムを表示してあげる
335+
int currentPage = _main_pageManager.Get(itemTagState); // -1が返された場合は対応していないStateのため、全てのアイテムを表示してあげる
336336

337337
foreach (ItemCountInfo itemCountInfo in currentPage != -1 ? items.Skip(currentPage * UserPreferences.ItemsPerPage).Take(UserPreferences.ItemsPerPage) : items)
338338
{
@@ -356,7 +356,7 @@ private void Main_RenderRightPanel()
356356

357357
// スクロール位置をDictionaryから復元してあげる
358358
Main_RightPanelScrollViewer.Presenter?.UpdateLayout();
359-
Main_RightPanelScrollViewer.Offset = _main_scrollManager.GetScrollValue(itemTagState);
359+
Main_RightPanelScrollViewer.Offset = _main_scrollManager.Get(itemTagState);
360360
}
361361
private async void RightPanel_ItemButton_Click(object? sender, RoutedEventArgs e)
362362
{
@@ -374,16 +374,16 @@ private async void RightPanel_ItemButton_Click(object? sender, RoutedEventArgs e
374374
AvatarExplorer.Select(itemTagInfo.State, itemTagInfo.Value);
375375
Main_CheckPageStates();
376376
Main_CheckScrollStates();
377-
_main_scrollManager.SetScroll(itemTagInfo.State, Main_RightPanelScrollViewer.Offset); // 次の画面に行くため、今のStateのスクロール位置を保存する
377+
_main_scrollManager.Add(itemTagInfo.State, Main_RightPanelScrollViewer.Offset); // 次の画面に行くため、今のStateのスクロール位置を保存する
378378

379379
Main_RenderRightPanel();
380380
}
381381
}
382382

383383
if (button.Tag is PageButtonInfo pageButtonInfo)
384384
{
385-
_main_pageManager.SetPage(pageButtonInfo.ItemTagState, pageButtonInfo.NextPageValue);
386-
_main_scrollManager.SetScroll(pageButtonInfo.ItemTagState, new()); // ページは今のStateをリセットしてあげる
385+
_main_pageManager.Add(pageButtonInfo.ItemTagState, pageButtonInfo.NextPageValue);
386+
_main_scrollManager.Remove(pageButtonInfo.ItemTagState); // ページは今のStateをリセットしてあげる
387387

388388
if (pageButtonInfo.ItemTagState == ItemTagStates.SearchItem) Main_ExecuteSearchItems();
389389
else Main_RenderRightPanel();
@@ -432,13 +432,13 @@ private void Main_ExecuteSearchItems(string searchText = "")
432432
}
433433

434434
// 検索画面に切り替わる時に、前の画面のスクロール位置を保存してあげる
435-
if (!_main_isLastWindowSearch) _main_scrollManager.SetScroll(_main_lastRightPanelItemTagState, Main_RightPanelScrollViewer.Offset);
435+
if (!_main_isLastWindowSearch) _main_scrollManager.Add(_main_lastRightPanelItemTagState, Main_RightPanelScrollViewer.Offset);
436436

437437
// 検索文字列が前回と違う場合はページ、スクロール位置をリセットする
438438
if (searchFilter.ToString() != _main_lastSearchTextCache)
439439
{
440-
_main_pageManager.SetPage(ItemTagStates.SearchItem, 0);
441-
_main_scrollManager.SetScroll(ItemTagStates.SearchItem, new());
440+
_main_pageManager.Add(ItemTagStates.SearchItem, 0);
441+
_main_scrollManager.Remove(ItemTagStates.SearchItem);
442442
}
443443
_main_lastSearchTextCache = searchFilter.ToString();
444444

@@ -449,7 +449,7 @@ private void Main_ExecuteSearchItems(string searchText = "")
449449
if (items.Length == 0) Main_ShowNoItemsLabel();
450450
else Main_HideNoItemsLabel();
451451

452-
int currentPage = _main_pageManager.GetPage(ItemTagStates.SearchItem); // SearchItemは必ずページが存在しているため
452+
int currentPage = _main_pageManager.Get(ItemTagStates.SearchItem); // SearchItemは必ずページが存在しているため
453453

454454
foreach (Item item in items.Skip(currentPage * UserPreferences.ItemsPerPage).Take(UserPreferences.ItemsPerPage))
455455
{
@@ -474,7 +474,7 @@ private void Main_ExecuteSearchItems(string searchText = "")
474474

475475
// スクロール位置をDictionaryから復元してあげる
476476
Main_RightPanelScrollViewer.Presenter?.UpdateLayout();
477-
Main_RightPanelScrollViewer.Offset = _main_scrollManager.GetScrollValue(ItemTagStates.SearchItem);
477+
Main_RightPanelScrollViewer.Offset = _main_scrollManager.Get(ItemTagStates.SearchItem);
478478
}
479479
#endregion
480480

@@ -519,8 +519,8 @@ private void Main_ExecuteUndo()
519519
private void Main_ExecuteHome()
520520
{
521521
AvatarExplorer.SelectClear();
522-
_main_pageManager.ResetAllPageValues();
523-
_main_scrollManager.ResetAllScrollValues();
522+
_main_pageManager.Clear();
523+
_main_scrollManager.Clear();
524524
Main_RenderRightPanel();
525525
}
526526
private void Main_ReloadCurrentWindow()
@@ -532,7 +532,7 @@ private void Main_ReloadCurrentWindow()
532532
else
533533
{
534534
// 再読込する前に、前の画面のスクロール位置を保存してあげる
535-
_main_scrollManager.SetScroll(_main_lastRightPanelItemTagState, Main_RightPanelScrollViewer.Offset);
535+
_main_scrollManager.Add(_main_lastRightPanelItemTagState, Main_RightPanelScrollViewer.Offset);
536536
Main_RenderRightPanel();
537537
}
538538

@@ -551,7 +551,7 @@ private void Main_CheckPageStates()
551551
foreach (var pageInfo in _main_pageManager.GetKeys().Where(i => !selectedItemTagStates.Contains(i)))
552552
{
553553
if (pageInfo == ItemTagStates.RootItem) continue;
554-
_main_pageManager.ResetPageValue(pageInfo);
554+
_main_pageManager.Remove(pageInfo);
555555
}
556556
}
557557
private void Main_CheckScrollStates()
@@ -565,7 +565,7 @@ private void Main_CheckScrollStates()
565565

566566
foreach (var scrollInfo in _main_scrollManager.GetKeys().Where(i => !selectedItemTagStates.Contains(i)))
567567
{
568-
_main_scrollManager.ResetScrollValue(scrollInfo);
568+
_main_scrollManager.Remove(scrollInfo);
569569
}
570570
}
571571

0 commit comments

Comments
 (0)