Skip to content

Commit

Permalink
BugFix: BasemapGallery loading demo data in production release (#579)
Browse files Browse the repository at this point in the history
* Refactor basemap loading and add event handler

* Update BasemapGallery and BasemapGalleryItem classes

- In `BasemapGallery.Appearance.cs`, the visibility of `PART_LoadingScrim` Grid has been set to `False`.
- The `LoadBasemaps` method in `BasemapGallery.cs` and `BasemapGallery.Windows.cs` has been removed and its functionality has been moved to the `BasemapGallery_Loaded` method.
- In `BasemapGalleryItem.cs`, the `Equals` method has been updated to check for equality of `BaseLayers` count and existence of all layers in `Basemap` in the `other` object, in addition to the existing checks.

* Refactor BasemapGalleryItem equality logic

* Add cancellation support to BasemapGallery

* Unsubscribe from Loaded event in BasemapGallery

* Refactor basemap loading cancellation logic

* Refactor BasemapGalleryItem Equals logic

* Enhance layer comparison in BasemapGalleryItem

* Update src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryItem.cs
  • Loading branch information
prathameshnarkhede authored Jun 18, 2024
1 parent 9fef6e5 commit d7dd108
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ static BasemapGallery()
</Style>
</Grid.Resources>
<CollectionView x:Name=""PART_InnerListView"" HorizontalOptions=""Fill"" VerticalOptions=""Fill"" SelectionMode=""Single"" BackgroundColor=""{{AppThemeBinding Light=#fff,Dark=#353535}}"" />
<Grid x:Name=""PART_LoadingScrim"">
<Grid x:Name=""PART_LoadingScrim"" IsVisible=""False"">
<Grid BackgroundColor=""{{AppThemeBinding Light=White, Dark=Black}}"" Opacity=""0.3"" />
<ActivityIndicator IsRunning=""True"" HorizontalOptions=""Center"" VerticalOptions=""Center"" />
</Grid>
Expand Down
19 changes: 15 additions & 4 deletions src/Toolkit/Toolkit.Maui/BasemapGallery/BasemapGallery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,20 @@ public BasemapGallery()
ListItemTemplate = DefaultListDataTemplate;
GridItemTemplate = DefaultGridDataTemplate;
ControlTemplate = DefaultControlTemplate;
_ = _controller.LoadFromDefaultPortal();
}

Loaded += BasemapGallery_Loaded;
}

private async void BasemapGallery_Loaded(object? sender, EventArgs e)
{
// Unsubscribe from the Loaded event to ensure this only runs once.
Loaded -= BasemapGallery_Loaded;

if (AvailableBasemaps is null)
{
await _controller.LoadFromDefaultPortal();
}
}

private void HandleControllerPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
Expand Down Expand Up @@ -185,7 +196,7 @@ public GeoModel? GeoModel
public IList<BasemapGalleryItem>? AvailableBasemaps
{
get => GetValue(AvailableBasemapsProperty) as IList<BasemapGalleryItem>;
set => SetValue(AvailableBasemapsProperty, value);
set => SetValue(AvailableBasemapsProperty, value);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,18 @@ public BasemapGallery()
SizeChanged += BasemapGallerySizeChanged;
AvailableBasemaps = new ObservableCollection<BasemapGalleryItem>();
_controller.PropertyChanged += HandleControllerPropertyChanged;
_ = _controller.LoadFromDefaultPortal();
Loaded += BasemapGallery_Loaded;
}

private async void BasemapGallery_Loaded(object? sender, RoutedEventArgs e)
{
// Unsubscribe from the Loaded event to ensure this only runs once.
Loaded -= BasemapGallery_Loaded;

if (AvailableBasemaps is null)
{
await _controller.LoadFromDefaultPortal();
}
}

private void HandleControllerPropertyChanged(object? sender, PropertyChangedEventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ namespace Esri.ArcGISRuntime.Toolkit.Maui
namespace Esri.ArcGISRuntime.Toolkit.UI
#endif
{
#pragma warning disable CA1001 // Types that own disposable fields should be disposable
internal class BasemapGalleryController : INotifyPropertyChanged
#pragma warning restore CA1001 // Types that own disposable fields should be disposable
{
private ArcGISPortal? _portal;
private bool _ignoreEventsFlag;
private IList<BasemapGalleryItem>? _availableBasemaps;
private GeoModel? _geoModel;
private BasemapGalleryItem? _selectedBasemap;
private bool _isLoading;
private CancellationTokenSource? _loadCancellationTokenSource;

public bool IsLoading
{
Expand Down Expand Up @@ -72,6 +75,7 @@ public IList<BasemapGalleryItem>? AvailableBasemaps

HandleAvailableBasemapsChanged();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AvailableBasemaps)));
_loadCancellationTokenSource?.Cancel();
}
}
}
Expand Down Expand Up @@ -227,10 +231,13 @@ private void HandleSelectedBasemapChanged()
public async Task LoadFromDefaultPortal()
{
IsLoading = true;
_loadCancellationTokenSource = new CancellationTokenSource();
try
{
AvailableBasemaps = await PopulateFromDefaultList();
AvailableBasemaps = await PopulateFromDefaultList(_loadCancellationTokenSource.Token);
}
catch (OperationCanceledException)
{ }
finally
{
IsLoading = false;
Expand Down Expand Up @@ -305,11 +312,11 @@ private static async Task<bool> BasemapIsActuallyNotABasemap(Basemap input)
return listOfBasemaps;
}

private static async Task<IList<BasemapGalleryItem>> PopulateFromDefaultList()
private static async Task<IList<BasemapGalleryItem>> PopulateFromDefaultList(CancellationToken cancellationToken = default)
{
ArcGISPortal defaultPortal = await ArcGISPortal.CreateAsync();
ArcGISPortal defaultPortal = await ArcGISPortal.CreateAsync(cancellationToken);

var results = await defaultPortal.GetDeveloperBasemapsAsync();
var results = await defaultPortal.GetDeveloperBasemapsAsync(cancellationToken);

var listOfBasemaps = new List<BasemapGalleryItem>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,53 @@ internal bool EqualsBasemap(Basemap? other)
return false;
}

return other == Basemap || other.Name == Basemap?.Name
|| (other.Item?.ItemId != null && other.Item?.ItemId == Basemap?.Item?.ItemId)
|| (other.Uri != null && other.Uri == Basemap?.Uri);
return other == Basemap || (other.Item?.ItemId != null && other.Item?.ItemId == Basemap?.Item?.ItemId)
|| (other.Uri != null && other.Uri == Basemap?.Uri)
|| AreBasemapsEqualByLayers(Basemap, other);
}

private static bool AreBasemapsEqualByLayers(Basemap? basemap1, Basemap? basemap2)
{
if (basemap1 == null || basemap2 == null) return false;

return LayersEqual(basemap1.BaseLayers, basemap2.BaseLayers)
&& LayersEqual(basemap1.ReferenceLayers, basemap2.ReferenceLayers);
}

private static bool LayersEqual(LayerCollection layers1, LayerCollection layers2)
{
return layers1.Count == layers2.Count
&& layers1.Zip(layers2, LayerEquals).All(equal => equal);
}

private static bool LayerEquals(Layer layer1, Layer layer2)
{
// This method can be extended to handle more specific layer comparisons if needed
if (layer1.GetType() != layer2.GetType()) return false;

return layer1 switch
{
AnnotationLayer annotationLayer => annotationLayer.Source == ((AnnotationLayer)layer2).Source,
ArcGISMapImageLayer arcGISMapImageLayer => arcGISMapImageLayer.Source == ((ArcGISMapImageLayer)layer2).Source,
ArcGISSceneLayer sceneLayer => sceneLayer.Source == ((ArcGISSceneLayer)layer2).Source,
ArcGISTiledLayer tiledLayer => tiledLayer.Source == ((ArcGISTiledLayer)layer2).Source,
ArcGISVectorTiledLayer vectorTiledLayer => vectorTiledLayer.Source == ((ArcGISVectorTiledLayer)layer2).Source,
BingMapsLayer imageServiceLayer => imageServiceLayer.Portal?.Uri == ((BingMapsLayer)layer2).Portal?.Uri,
DimensionLayer dimensionLayer => dimensionLayer.Source == ((DimensionLayer)layer2).Source,
FeatureCollectionLayer featureCollectionLayer => featureCollectionLayer.FeatureCollection == ((FeatureCollectionLayer)layer2).FeatureCollection,
GroupLayer groupLayer => groupLayer.Layers.Count == ((GroupLayer)layer2).Layers.Count && LayersEqual(groupLayer.Layers, ((GroupLayer)layer2).Layers),
IntegratedMeshLayer integratedMeshLayer => integratedMeshLayer.Source == ((IntegratedMeshLayer)layer2).Source,
KmlLayer kmlLayer => kmlLayer.Dataset?.Source == ((KmlLayer)layer2).Dataset?.Source,
Ogc3DTilesLayer ogc3DTilesLayer => ogc3DTilesLayer.Source == ((Ogc3DTilesLayer)layer2).Source,
OpenStreetMapLayer openStreetMapLayer => true, // OpenStreetMap layers are considered equal if types match
PointCloudLayer pointCloudLayer => pointCloudLayer.Source == ((PointCloudLayer)layer2).Source,
WebTiledLayer webTiledLayer => webTiledLayer.TemplateUri == ((WebTiledLayer)layer2).TemplateUri,
ServiceImageTiledLayer serviceImageTiledLayer => serviceImageTiledLayer.TileInfo == ((ServiceImageTiledLayer)layer2).TileInfo && serviceImageTiledLayer.FullExtent == ((ServiceImageTiledLayer)layer2).FullExtent,
SubtypeFeatureLayer subtypeFeatureLayer => subtypeFeatureLayer.FeatureTable == ((SubtypeFeatureLayer)layer2).FeatureTable,
WmsLayer wmsLayer => wmsLayer.Source == ((WmsLayer)layer2).Source,
WmtsLayer wmtsLayer => wmtsLayer.Source == ((WmtsLayer)layer2).Source,
_ => false,
};
}

/// <inheritdoc />
Expand Down

0 comments on commit d7dd108

Please sign in to comment.