Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [55.6.4]
- [iOS][SearchBar] Fixed memory leak where `SearchButtonClicked` event was never unsubscribed due to wrong event name in cleanup
- [iOS][Camera] Fixed memory leak where `PreviewView.OnTapToFocus` event was never unsubscribed when stopping camera session
- [SlidableLayout] Fixed memory leak where `TapGestureRecognizer.Tapped` event was never unsubscribed due to missing field reference

## [55.6.3]
- [ScrollView][iOS] ShouldBounce now sets correct native property.

Expand Down
2 changes: 1 addition & 1 deletion build/bootstrapper/bootstrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fi


#azure-CLI
if az > /dev/null ; then
if az > /dev/null 2>&1 ; then
echo "✅ Azure CLI was found"
else
echo "❌ Azure CLI not found, installing it..."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,7 @@ private void GoToEditState()

m_currentlyRotatedImageDisplayed.TranslationY -= m_topToolbar.HeightRequest;

m_currentlyRotatedImageDisplayed.SizeChanged += delegate
{
if (m_startingImageWidth is not null)
return;

m_startingImageWidth = m_currentlyRotatedImageDisplayed.Width;
m_startingImageHeight = m_currentlyRotatedImageDisplayed.Height;

m_carouselView.Opacity = 0;
m_navigatePreviousImageButton.IsVisible = false;
m_navigateNextImageButton.IsVisible = false;
};
m_currentlyRotatedImageDisplayed.SizeChanged += OnRotatedImageSizeChanged;

m_rotatingImageTcs = null;

Expand All @@ -169,11 +158,25 @@ private void GoToDefaultState()

m_positionBeforeEdit = m_carouselView!.Position;

m_currentlyRotatedImageDisplayed.SizeChanged -= OnRotatedImageSizeChanged;
m_grid.Remove(m_currentlyRotatedImageDisplayed);
UpdateNavigationButtonsVisibility(m_carouselView.Position);
OnImagesChanged();
}

private void OnRotatedImageSizeChanged(object? sender, EventArgs e)
{
if (m_startingImageWidth is not null)
return;

m_startingImageWidth = m_currentlyRotatedImageDisplayed.Width;
m_startingImageHeight = m_currentlyRotatedImageDisplayed.Height;

m_carouselView!.Opacity = 0;
m_navigatePreviousImageButton.IsVisible = false;
m_navigateNextImageButton.IsVisible = false;
}

async void IGalleryDefaultStateObserver.RemoveImage()
{
if(Images.Count == 0)
Expand Down Expand Up @@ -276,6 +279,7 @@ private void OnImagesChanged()

if (m_carouselView is not null)
{
m_carouselView.SizeChanged -= OnCarouselViewSizeChanged;
m_carouselView.PositionChanged -= CarouselViewOnPositionChanged;
try
{
Expand Down Expand Up @@ -310,30 +314,32 @@ private void OnImagesChanged()
};
m_carouselViewWrapperView.Content = m_carouselView;

m_carouselView.SizeChanged += delegate
{
if (m_hasSetToolbarHeights)
{
return;
}

var actualImageHeight = m_carouselView.Width / CameraPreview.ThreeFourRatio;
var letterBoxHeight = m_carouselView.Height - actualImageHeight;

m_topToolbar.HeightRequest = letterBoxHeight * CameraPreview.TopToolbarPercentHeightOfLetterBox;
m_bottomToolbar.HeightRequest = letterBoxHeight * CameraPreview.BottomToolbarPercentHeightOfLetterBox;

m_carouselViewWrapperView.TranslationY -= m_topToolbar.HeightRequest;
m_navigatePreviousImageButton.TranslationY -= m_topToolbar.HeightRequest;
m_navigateNextImageButton.TranslationY -= m_topToolbar.HeightRequest;

m_hasSetToolbarHeights = true;
};
m_carouselView.SizeChanged += OnCarouselViewSizeChanged;

m_carouselView.PositionChanged += CarouselViewOnPositionChanged;
m_grid.Insert(0, m_carouselViewWrapperView);
}

private void OnCarouselViewSizeChanged(object? sender, EventArgs e)
{
if (m_hasSetToolbarHeights)
{
return;
}

var actualImageHeight = m_carouselView!.Width / CameraPreview.ThreeFourRatio;
var letterBoxHeight = m_carouselView.Height - actualImageHeight;

m_topToolbar.HeightRequest = letterBoxHeight * CameraPreview.TopToolbarPercentHeightOfLetterBox;
m_bottomToolbar.HeightRequest = letterBoxHeight * CameraPreview.BottomToolbarPercentHeightOfLetterBox;

m_carouselViewWrapperView.TranslationY -= m_topToolbar.HeightRequest;
m_navigatePreviousImageButton.TranslationY -= m_topToolbar.HeightRequest;
m_navigateNextImageButton.TranslationY -= m_topToolbar.HeightRequest;

m_hasSetToolbarHeights = true;
}

private void OnStartingIndexChanged()
{
if(m_carouselView is not null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ await Task.Run(() =>
if (PreviewView is not null)
{
PreviewView.OnZoomChanged -= PreviewViewOnZoomChanged;
PreviewView.OnTapToFocus -= PreviewViewOnOnTapToFocus;
PreviewView?.Dispose();
PreviewView = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,6 @@ public void Dispose()
{
m_timer.Stop();
m_timer.Elapsed -= OnTimerEnded;
m_timer.Dispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,20 @@ public partial class BottomSheetHandler : ContentViewHandler
private BottomSheetHeader m_bottomSheetHeader;
private List<WeakReference<SearchBar>> m_weakSearchBars = [];
private WeakReference<AView>? m_weakCurrentFocusedSearchBar;
private BottomSheetCallback? m_bottomSheetCallback;
private KeyListener? m_keyListener;

public AView OnBeforeOpening(IMauiContext mauiContext, Context context, AView bottomSheetAndroidView,
RelativeLayout rootLayout, LinearLayout bottomSheetLayout)
{
if (VirtualView is not BottomSheet bottomSheet) return new AView(Context);

m_bottomSheet = bottomSheet;
bottomSheet.BottomSheetDialog.Behavior.AddBottomSheetCallback(
new BottomSheetCallback(this));
m_bottomSheetCallback = new BottomSheetCallback(this);
m_keyListener = new KeyListener(this);
bottomSheet.BottomSheetDialog.Behavior.AddBottomSheetCallback(m_bottomSheetCallback);
bottomSheet.BottomSheetDialog.SetOnShowListener(new DialogInterfaceOnShowListener(this));
bottomSheet.BottomSheetDialog.SetOnKeyListener(new KeyListener(this));
bottomSheet.BottomSheetDialog.SetOnKeyListener(m_keyListener);

//Add a handle, with a innerGrid that works as a big hit box for the user to hit
//Inspired by com.google.android.material.bottomsheet.BottomSheetDragHandleView , which will be added in Xamarin Android Material Design v1.7.0. https://github.com/material-components/material-components-android/commit/ac7b761294808748df167b50b223b591ca9dac06
Expand Down Expand Up @@ -234,6 +237,16 @@ protected override void DisconnectHandler(ContentViewGroup platformView)
{
base.DisconnectHandler(platformView);

if (m_bottomSheetCallback is not null)
{
m_bottomSheet.BottomSheetDialog.Behavior.RemoveBottomSheetCallback(m_bottomSheetCallback);
m_bottomSheetCallback = null;
}

m_bottomSheet.BottomSheetDialog.SetOnShowListener(null);
m_bottomSheet.BottomSheetDialog.SetOnKeyListener(null);
m_keyListener = null;

s_mEmptyNonFitToContentView?.RemoveFromParent();
m_bottomSheetHeader.DisconnectHandlers();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ private BoxView CreateBox(SkeletonShape shape)
return box;
}

protected override void OnHandlerChanging(HandlerChangingEventArgs args)
{
base.OnHandlerChanging(args);

if (args.NewHandler is not null)
return;

StopAnimation();
}

private void StartAnimation()
{
StopAnimation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,20 @@ private async Task FadeIn(IView? view)
}
}

private StateViewModel? m_previousStateViewModel;

private void OnStateViewModelChanged()
{
if(StateViewModel is null)
return;

if (m_previousStateViewModel is not null)
{
m_previousStateViewModel.OnStateChanged -= OnStateChanged;
}

m_previousStateViewModel = StateViewModel;

ErrorView ??= new ErrorView { BindingContext = StateViewModel.Error };
LoadingView ??= new LoadingView { BindingContext = StateViewModel.Loading };
EmptyView ??= new EmptyView { BindingContext = StateViewModel.Empty };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,24 @@ private static partial void MapIsClickable(FloatingNavigationButtonHandler handl
if (handler.PlatformView is not global::Android.Views.View aView) return;
if (handler.VirtualView is not FloatingNavigationButton fab) return;

aView.Click -= handler.OnNativeViewClick;

if (floatingNavigationButton.IsClickable)
{
aView.Clickable = true;
aView.Click += (_, _) =>
{
_ = fab.Close();
};
aView.Click += handler.OnNativeViewClick;
}
else
{
aView.Clickable = false;
}
}

private void OnNativeViewClick(object? sender, EventArgs e)
{
if (VirtualView is FloatingNavigationButton fab)
{
_ = fab.Close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public static void Close()
public static void Remove()
{
PlatformRemove();
FloatingNavigationButton = null;
}

private static partial void PlatformRemove();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ protected override void DisconnectHandler(UIDatePicker platformView)
{
base.DisconnectHandler(platformView);

platformView.ValueChanged -= OnValueChanged;
platformView.EditingDidBegin -= OnOpen;
platformView.EditingDidEnd -= OnClose;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ private static void ItemsSourceChanged(BindableObject bindable, object oldValue,
picker.AddContextMenuItems();
}

if (oldValue is INotifyCollectionChanged oldNotifyCollectionChanged)
{
oldNotifyCollectionChanged.CollectionChanged -= picker.OnCollectionChanged;
}

if (newValue is INotifyCollectionChanged notifyCollectionChanged)
{
notifyCollectionChanged.CollectionChanged += picker.OnCollectionChanged;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ protected override void OnHandlerChanging(HandlerChangingEventArgs args)
base.OnHandlerChanging(args);

if(args.NewHandler is null)
{
DateEnabledSwitch.Toggled -= OnSwitchToggled;
return;
}

m_dateOrTimePicker = CreateDateOrTimePicker();
m_dateOrTimePicker.IsVisible = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ protected override void DisconnectHandler(Chip platformView)

platformView.Click -= PlatformViewOnClick;
m_scrollPickerViewModel.OnAnyComponentsDataInvalidated -= SetChipTitle;
m_scrollPickerViewModel.Dispose();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -95,32 +95,34 @@ private View CreateSegment()
horizontalStackLayout.Add(checkedImage);
horizontalStackLayout.Add(label);
border.Content = horizontalStackLayout;
border.SizeChanged += ((sender, _) =>
{
if (sender is not View view) return;
border.SizeChanged += OnBorderSizeChanged;

// Sometimes on Android, the different does not have equal heights, so this is a workaround to ensure all borders have same height.
return border;
}

private void OnBorderSizeChanged(object? sender, EventArgs _)
{
if (sender is not Border border) return;

// Sometimes on Android, the different does not have equal heights, so this is a workaround to ensure all borders have same height.
#if __ANDROID__
border.HeightRequest = this.Height;
#endif

if (view.BindingContext is not SelectableItemViewModel selectableListItem) return;
if (border.BindingContext is not SelectableItemViewModel selectableListItem) return;

var radius = Sizes.GetSize(SizeName.radius_xlarge);
var roundRectangle = new RoundRectangle() { StrokeThickness = 0};
if (m_allSelectableItems.Last() == selectableListItem)
{
roundRectangle.CornerRadius = new CornerRadius(0, radius, 0, radius);
}
else if (m_allSelectableItems.First() == selectableListItem)
{
roundRectangle.CornerRadius = new CornerRadius(radius, 0, radius, 0);
}

border.StrokeShape = roundRectangle;
});
var radius = Sizes.GetSize(SizeName.radius_xlarge);
var roundRectangle = new RoundRectangle() { StrokeThickness = 0};
if (m_allSelectableItems.Last() == selectableListItem)
{
roundRectangle.CornerRadius = new CornerRadius(0, radius, 0, radius);
}
else if (m_allSelectableItems.First() == selectableListItem)
{
roundRectangle.CornerRadius = new CornerRadius(radius, 0, radius, 0);
}

return border;
border.StrokeShape = roundRectangle;
}

private void OnItemTouched(SelectableItemViewModel selectableItemViewModel)
Expand Down
5 changes: 2 additions & 3 deletions src/library/DIPS.Mobile.UI/Components/Searching/SearchPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ public SearchPage()
SearchBar.SetBinding(SearchBar.DelayProperty, static (SearchPage searchPage) => searchPage.Delay, source: this);
SearchBar.SetBinding(SearchBar.IsAutocorrectEnabledProperty, static (SearchPage searchPage) => searchPage.IsAutocorrectEnabled, source: this);

SearchBar.TextChanged += SearchBarOnTextChanged;

SearchBar.SearchCommand = new Command(() => OnSearchQueryChanged(SearchBar.Text));
SearchBar.ClearTextCommand = new Command(TextWasClearedFromClick);
SearchBar.CancelCommand = CancelCommand;
Expand Down Expand Up @@ -125,6 +123,7 @@ protected override void OnHandlerChanged()
SearchBar.Focus();
}

SearchBar.TextChanged += SearchBarOnTextChanged;
SearchBar.Focused += OnSearchBarFocused;
}

Expand Down Expand Up @@ -209,7 +208,6 @@ private async void OnSearchQueryChanged(string searchQuery)

protected override void OnDisappearing()
{
SearchBar.TextChanged -= SearchBarOnTextChanged;
SearchBar.Unfocus();
base.OnDisappearing();
}
Expand Down Expand Up @@ -279,6 +277,7 @@ protected override void OnHandlerChanging(HandlerChangingEventArgs args)

if (args.NewHandler is null)
{
SearchBar.TextChanged -= SearchBarOnTextChanged;
m_resultCollectionView.Scrolled -= OnCollectionViewScrolled;
SearchBar.Focused -= OnSearchBarFocused;
}
Expand Down
10 changes: 10 additions & 0 deletions src/library/DIPS.Mobile.UI/Components/Shell/Shell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ public Shell()
SetNavBarHasShadow(this, false);
}

protected override void OnHandlerChanging(HandlerChangingEventArgs args)
{
base.OnHandlerChanging(args);

if (args.NewHandler is not null)
return;

Navigated -= OnNavigated;
}

private async void OnNavigated(object? sender, ShellNavigatedEventArgs e)
{
switch (e.Source)
Expand Down
Loading