Skip to content

Commit

Permalink
fix(calendar): Improve reliability of calendar by safely handling inv…
Browse files Browse the repository at this point in the history
…alid cases
  • Loading branch information
dr1rrb authored and jeromelaban committed Jun 9, 2021
1 parent 02a25e8 commit 6bf96e5
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
Expand Up @@ -351,6 +351,15 @@ internal void OnItemFocused(CalendarViewBaseItem pItem)
SetDisplayDateInternal(date); // scroll item into view so we can move focus to it.

spItemAsI = pHost.Panel.ContainerFromIndex(index);

// Uno workaround
if (spItemAsI is null)
{
// The scrolling might occurs async, especially on wasm.
// For safety we prefer to ignore this instead of crashing which might cause exceptions worst than loosing the focus.
return;
}

global::System.Diagnostics.Debug.Assert(spItemAsI is {});
spItem = (CalendarViewBaseItem) spItemAsI;

Expand Down
Expand Up @@ -14,6 +14,7 @@
using Uno.Extensions.Specialized;
using Uno.Logging;
using Uno.UI;
using Uno.UI.Extensions;

namespace Windows.UI.Xaml.Controls.Primitives
{
Expand Down Expand Up @@ -48,7 +49,7 @@ private class ContainersCache : IItemContainerMapping, IEnumerable<CacheEntry>
set
{
_host = value;
_entries.Clear();
Clear();
}
}

Expand All @@ -71,6 +72,17 @@ private enum GenerationState
After
}

internal void Clear()
{
_entries.Clear();
FirstIndex = -1;
LastIndex = int.MinValue;

_generationStartIndex = -1;
_generationCurrentIndex = -1;
_generationEndIndex = -1;
}

internal void BeginGeneration(int startIndex, int endIndex)
{
if (_host is null)
Expand All @@ -86,7 +98,7 @@ internal void BeginGeneration(int startIndex, int endIndex)
_generationEndIndex = endIndex;
_generationState = GenerationState.Before;

// Note: Start and End indexes are INCLUSIVE
// Note: Fist and Last indexes are INCLUSIVE
startIndex = Math.Max(FirstIndex, startIndex);
endIndex = Math.Min(LastIndex, endIndex);

Expand Down Expand Up @@ -607,17 +619,28 @@ private Size base_MeasureOverride(Size availableSize)
}
finally
{
FirstVisibleIndexBase = Math.Max(firstVisibleIndex, startIndex);
LastVisibleIndexBase = Math.Max(FirstVisibleIndexBase, lastVisibleIndex);
try
{
FirstVisibleIndexBase = Math.Max(firstVisibleIndex, startIndex);
LastVisibleIndexBase = Math.Max(FirstVisibleIndexBase, lastVisibleIndex);

foreach (var unusedEntry in _cache.CompleteGeneration(index - 1))
{
Children.Remove(unusedEntry.Container);
}

foreach (var unusedEntry in _cache.CompleteGeneration(index - 1))
global::System.Diagnostics.Debug.Assert(_cache.FirstIndex <= FirstVisibleIndex || FirstVisibleIndex == -1);
global::System.Diagnostics.Debug.Assert(_cache.LastIndex >= LastVisibleIndex || LastVisibleIndex == -1);
global::System.Diagnostics.Debug.Assert(Children.Count == _cache.LastIndex - _cache.FirstIndex + 1 || (_cache.LastIndex == -1 && _cache.LastIndex == -1));
}
catch
{
Children.Remove(unusedEntry.Container);
_cache.Clear();
Children.Clear();

InvalidateMeasure();
}

global::System.Diagnostics.Debug.Assert(_cache.FirstIndex <= FirstVisibleIndex || FirstVisibleIndex == -1);
global::System.Diagnostics.Debug.Assert(_cache.LastIndex >= LastVisibleIndex || LastVisibleIndex == -1);
global::System.Diagnostics.Debug.Assert(Children.Count == _cache.LastIndex - _cache.FirstIndex + 1 || (_cache.LastIndex == -1 && _cache.LastIndex == -1));

// We force the parent ScrollViewer to use the same viewport as us, no matter its own stretching.
ViewportHeight = viewport.Height;
Expand Down

0 comments on commit 6bf96e5

Please sign in to comment.