Repository: vitalii-vov/Maui.PDFView
Pull request #24: Add TwoWay bindable property PageIndex
Author: login: jldearmas
Created: 2025-05-14T06:49:54Z | Merged: 2025-05-21T02:35:40Z

Added property **PageNumber** that can be bound with Mode=TwoWay; so it allows to keep updated the page number, but also go to an specific page.

The example was modified to show the usage of the **PageNumber** property using Label and Stepper controls:

```
<Label
    Grid.Row="0"
    Grid.Column="2"
    FontSize="Caption"
    HorizontalTextAlignment="Center"
    Text="{Binding PageNumber, StringFormat='Page number is {0}'}" />

<Stepper
    Grid.Row="1"
    Grid.Column="2"
    Maximum="5"
    Minimum="1"
    Value="{Binding PageNumber, Mode=TwoWay}" />
```

```
<pdf:PdfView
    Grid.Row="1"
    IsHorizontal="{Binding IsHorizontal}"
    MaxZoom="{Binding MaxZoom}"
    PageChangedCommand="{Binding PageChangedCommand}"
    PageNumber="{Binding PageNumber, Mode=TwoWay}"
    Uri="{Binding PdfSource}"/>
```




Diff:
diff --git a/Example/Business/UI/Pages/MainPage.xaml b/Example/Business/UI/Pages/MainPage.xaml
index 9ec6fab..9096606 100644
--- a/Example/Business/UI/Pages/MainPage.xaml
+++ b/Example/Business/UI/Pages/MainPage.xaml
@@ -5,6 +5,8 @@
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:pdf="clr-namespace:Maui.PDFView;assembly=Maui.PDFView"
     xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
+    xmlns:vms="clr-namespace:Example.Business.UI.ViewModels"
+    x:DataType="vms:MainPageViewModel"
     Title="Example">
 
     <ContentPage.Behaviors>
@@ -13,62 +15,81 @@
 
     <Grid RowDefinitions="Auto,*">
 
-        <Grid
-            ColumnDefinitions="Auto,Auto,Auto"
-            ColumnSpacing="8"
-            RowDefinitions="Auto,Auto">
-
-            <Label
-                Grid.Row="0"
-                Grid.Column="0"
-                FontSize="Caption"
-                HorizontalTextAlignment="Center"
-                Text="Horizontal"
-                VerticalOptions="Center" />
-
-            <CheckBox
-                Grid.Row="1"
-                Grid.Column="0"
-                IsChecked="{Binding IsHorizontal}"
-                VerticalOptions="Center" />
-
-            <Label
-                Grid.Row="0"
-                Grid.Column="1"
-                FontSize="Caption"
-                HorizontalTextAlignment="Center"
-                Text="{Binding MaxZoom, StringFormat='Max zoom is {0}'}" />
-
-            <Stepper
-                Grid.Row="1"
-                Grid.Column="1"
-                Maximum="5"
-                Minimum="1"
-                Value="{Binding MaxZoom}" />
-
-            <Button
-                Grid.Row="0"
-                Grid.RowSpan="2"
-                Grid.Column="2"
-                Command="{Binding ChangeUriCommand}"
-                Text="ChangeUri"
-                VerticalOptions="Center" />
-
-        </Grid>
+        <ScrollView Orientation="Horizontal">
+            <Grid
+                ColumnDefinitions="Auto,Auto,Auto,Auto"
+                ColumnSpacing="8"
+                RowDefinitions="Auto,Auto">
+    
+                <Label
+                    Grid.Row="0"
+                    Grid.Column="0"
+                    FontSize="Caption"
+                    HorizontalTextAlignment="Center"
+                    Text="Horizontal"
+                    VerticalOptions="Center" />
+    
+                <CheckBox
+                    Grid.Row="1"
+                    Grid.Column="0"
+                    IsChecked="{Binding IsHorizontal}"
+                    VerticalOptions="Center" />
+    
+                <Label
+                    Grid.Row="0"
+                    Grid.Column="1"
+                    FontSize="Caption"
+                    HorizontalTextAlignment="Center"
+                    Text="{Binding MaxZoom, StringFormat='Max zoom is {0}'}" />
+    
+                <Stepper
+                    Grid.Row="1"
+                    Grid.Column="1"
+                    Maximum="5"
+                    Minimum="1"
+                    Value="{Binding MaxZoom}" />
+    
+                <Label
+                    Grid.Row="0"
+                    Grid.Column="2"
+                    FontSize="Caption"
+                    HorizontalTextAlignment="Center"
+                    Text="{Binding PageIndex, StringFormat='Page index is {0}'}" />
+    
+                <Stepper
+                    Grid.Row="1"
+                    Grid.Column="2"
+                    Maximum="{Binding MaxPageIndex}"
+                    Minimum="0"
+                    Value="{Binding PageIndex, Mode=TwoWay}" />
+    
+                <Button
+                    Grid.Row="0"
+                    Grid.RowSpan="2"
+                    Grid.Column="3"
+                    Command="{Binding ChangeUriCommand}"
+                    Text="ChangeUri"
+                    VerticalOptions="Center" />
+    
+            </Grid>
+        </ScrollView>
+        
 
         <pdf:PdfView
             Grid.Row="1"
             IsHorizontal="{Binding IsHorizontal}"
             MaxZoom="{Binding MaxZoom}"
             PageChangedCommand="{Binding PageChangedCommand}"
+	        PageIndex="{Binding PageIndex, Mode=TwoWay}"
             Uri="{Binding PdfSource}"/>
         
-        <Label Grid.Row="1"
-               VerticalOptions="Start"
-               Text="{Binding Mode=OneWay, Path=PagePosition}"
-               BackgroundColor="WhiteSmoke"
-               HorizontalOptions="Start"
-               TextColor="Black"/>
+        <Label 
+            Grid.Row="1"
+            VerticalOptions="Start"
+            Text="{Binding Mode=OneWay, Path=PagePosition}"
+            BackgroundColor="WhiteSmoke"
+            HorizontalOptions="Start"
+            TextColor="Black"/>
     </Grid>
 
 </ContentPage>
\ No newline at end of file
diff --git a/Example/Business/UI/ViewModels/MainPageViewModel.cs b/Example/Business/UI/ViewModels/MainPageViewModel.cs
index d643a80..4e4b6ed 100644
--- a/Example/Business/UI/ViewModels/MainPageViewModel.cs
+++ b/Example/Business/UI/ViewModels/MainPageViewModel.cs
@@ -15,6 +15,8 @@ internal partial class MainPageViewModel : ObservableObject
         [ObservableProperty] private bool _isHorizontal;
         [ObservableProperty] private float _maxZoom = 4;
         [ObservableProperty] private string _pagePosition;
+        [ObservableProperty] private uint _pageIndex = 0;
+        [ObservableProperty] private uint _maxPageIndex = uint.MaxValue;
 
         [RelayCommand] private void Appearing()
         {
@@ -28,8 +30,10 @@ [RelayCommand] private void ChangeUri()
 
         [RelayCommand] private void PageChanged(PageChangedEventArgs args)
         {
+            MaxPageIndex = (uint)args.TotalPages - 1;
             PagePosition = $"{args.CurrentPage} of {args.TotalPages}";
             Debug.WriteLine($"Current page: {args.CurrentPage} of {args.TotalPages}");
         }
+
     }
 }
diff --git a/Maui.PDFView/Events/PageChangedEventArgs.cs b/Maui.PDFView/Events/PageChangedEventArgs.cs
index b2f57f8..b3fcc5d 100644
--- a/Maui.PDFView/Events/PageChangedEventArgs.cs
+++ b/Maui.PDFView/Events/PageChangedEventArgs.cs
@@ -1,5 +1,3 @@
-using System;
-
 namespace Maui.PDFView.Events
 {
     public class PageChangedEventArgs
diff --git a/Maui.PDFView/IPdfView.cs b/Maui.PDFView/IPdfView.cs
index b68b3f6..9c903f4 100644
--- a/Maui.PDFView/IPdfView.cs
+++ b/Maui.PDFView/IPdfView.cs
@@ -8,6 +8,8 @@ internal interface IPdfView : IView
         bool IsHorizontal { get; set; }
         float MaxZoom { get; set; }
         PageAppearance? PageAppearance { get; set; }
+        uint PageIndex { get; set; }
+
         ICommand PageChangedCommand { get; set; }
     }
 }
diff --git a/Maui.PDFView/PdfView.cs b/Maui.PDFView/PdfView.cs
index 82e2598..2f6f5a9 100644
--- a/Maui.PDFView/PdfView.cs
+++ b/Maui.PDFView/PdfView.cs
@@ -36,6 +36,12 @@ public class PdfView : View, IPdfView
                 declaringType: typeof(PdfView),
                 defaultValue: default(ICommand));
 
+        public static readonly BindableProperty PageIndexProperty = BindableProperty.Create(
+                propertyName: nameof(PageIndex),
+                returnType: typeof(uint),
+                declaringType: typeof(PdfView),
+                defaultValue: (uint)0, defaultBindingMode: BindingMode.TwoWay);
+
         public string Uri
         {
             get => (string)GetValue(UriProperty);
@@ -66,6 +72,12 @@ public ICommand PageChangedCommand
             set => SetValue(PageChangedCommandProperty, value);
         }
 
+        public uint PageIndex
+        {
+            get => (uint)GetValue(PageIndexProperty);
+            set => SetValue(PageIndexProperty, value);
+        }
+
         private static void OnMaxZoomPropertyChanged(BindableObject bindable, object oldValue, object newValue)
         {
             if ((float)newValue < 1f)
diff --git a/Maui.PDFView/Platforms/Android/PdfViewHandler.cs b/Maui.PDFView/Platforms/Android/PdfViewHandler.cs
index 017ebaa..f06b8bb 100644
--- a/Maui.PDFView/Platforms/Android/PdfViewHandler.cs
+++ b/Maui.PDFView/Platforms/Android/PdfViewHandler.cs
@@ -19,6 +19,7 @@ internal class PdfViewHandler : ViewHandler<IPdfView, FrameLayout>
             [nameof(IPdfView.IsHorizontal)] = MapIsHorizontal,
             [nameof(IPdfView.MaxZoom)] = MapMaxZoom,
             [nameof(IPdfView.PageAppearance)] = MapPageAppearance,
+            [nameof(IPdfView.PageIndex)] = MapPageIndex,
         };
 
         private readonly ScreenHelper _screenHelper = new();
@@ -27,6 +28,9 @@ internal class PdfViewHandler : ViewHandler<IPdfView, FrameLayout>
         private readonly DesiredSizeHelper _sizeHelper = new();
         
         private PageAppearance? _pageAppearance;
+        
+        private bool _isScrolling;
+        private bool _isPageIndexLocked;
 
         public PdfViewHandler() : base(PropertyMapper, null)
         {
@@ -56,6 +60,11 @@ static void MapPageAppearance(PdfViewHandler handler, IPdfView pdfView)
             handler._pageAppearance = pdfView.PageAppearance ?? new PageAppearance();
         }
 
+        static void MapPageIndex(PdfViewHandler handler, IPdfView pdfView)
+        {
+            handler.GotoPage(pdfView.PageIndex);
+        }
+
         protected override FrameLayout CreatePlatformView()
         {
             var layout = new FrameLayout(Context)
@@ -165,7 +174,21 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageIndex)
+        {
+            if (_isScrolling)
+                return;
+
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageIndex >= layoutManager.ItemCount)
+                return;
+
+            _isPageIndexLocked = true;
+            layoutManager.ScrollToPositionWithOffset((int)pageIndex,1);
+        }
+
         private class PdfScrollListener : RecyclerView.OnScrollListener
         {
             private readonly PdfViewHandler _handler;
@@ -217,8 +240,21 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                var newPageIndex = (uint)currentPage;
+                if (_handler._isPageIndexLocked)
+                {
+                    _handler._isPageIndexLocked = false;
+                }
+                else if (_handler.VirtualView.PageIndex != newPageIndex)
+                {
+                    _handler._isScrolling = true;
+                    _handler.VirtualView.PageIndex = newPageIndex;
+                    _handler._isScrolling = false;
+                }
+
+                if (_handler.VirtualView.PageChangedCommand?.CanExecute(null) == true)
+                    // Execute the command if available
+                    _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
             }
         }
     }
diff --git a/Maui.PDFView/Platforms/MacCatalyst/PdfViewHandler.cs b/Maui.PDFView/Platforms/MacCatalyst/PdfViewHandler.cs
index 95ac13d..90f70bf 100644
--- a/Maui.PDFView/Platforms/MacCatalyst/PdfViewHandler.cs
+++ b/Maui.PDFView/Platforms/MacCatalyst/PdfViewHandler.cs
@@ -15,11 +15,14 @@ internal class PdfViewHandler : ViewHandler<IPdfView, PdfKit.PdfView>
             [nameof(IPdfView.IsHorizontal)] = MapIsHorizontal,
             [nameof(IPdfView.MaxZoom)] = MapMaxZoom,
             [nameof(IPdfView.PageAppearance)] = MapPageAppearance,
+            [nameof(IPdfView.PageIndex)] = MapPageIndex,
         };
 
         private string _fileName;
         private PageAppearance _appearance = new();
         private readonly DesiredSizeHelper _sizeHelper = new();
+        
+        private bool _isScrolling;
 
         public PdfViewHandler() : base(PropertyMapper, null)
         {
@@ -52,6 +55,11 @@ static void MapPageAppearance(PdfViewHandler handler, IPdfView pdfView)
             SetPageAppearance(handler, appearance);
         }
 
+        static void MapPageIndex(PdfViewHandler handler, IPdfView pdfView)
+        {
+            handler.GotoPage(pdfView.PageIndex);
+        }
+
         private static void SetPageAppearance(PdfViewHandler handler, PageAppearance appearance)
         {
             //  set shadow
@@ -118,6 +126,26 @@ private void RenderPages()
             PlatformView.AutoScales = true;
         }
 
+        private void GotoPage(uint pageIndex)
+        {
+            if (_isScrolling)
+                return;
+
+            var document = PlatformView.Document;
+            if (document is null)
+                return;
+
+            if (pageIndex >= document.PageCount)
+                return;
+
+            var newPage = document.GetPage((nint)pageIndex);
+
+            if (newPage is null)
+                return;
+
+            PlatformView.GoToPage(newPage);
+        }
+
         private void PageChangedNotificationHandler(NSNotification notification)
         {
             var currentPage = PlatformView.CurrentPage;
@@ -128,12 +156,21 @@ private void PageChangedNotificationHandler(NSNotification notification)
             if (document is null)
                 return;
 
-            if (!(VirtualView.PageChangedCommand?.CanExecute(null) ?? false)) 
+            var newPageIndex = (uint)document.GetPageIndex(currentPage);
+            if (VirtualView.PageIndex != newPageIndex)
+            {
+                _isScrolling = true;
+                VirtualView.PageIndex = newPageIndex;
+                _isScrolling = false;
+            }
+
+            if (!(VirtualView.PageChangedCommand?.CanExecute(null) ?? false))
                 return;
 
-            VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs((int)(document.GetPageIndex(currentPage) + 1), (int)document.PageCount));
+            VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs((int)newPageIndex+1, (int)document.PageCount));
+
         }
-        
+
         private void CropPages(PdfKit.PdfDocument pdfdoc, Thickness cropBounds)
         {
             if (cropBounds.IsEmpty) 
diff --git a/Maui.PDFView/Platforms/Windows/PdfViewHandler.cs b/Maui.PDFView/Platforms/Windows/PdfViewHandler.cs
index 0ec377d..60d36b8 100644
--- a/Maui.PDFView/Platforms/Windows/PdfViewHandler.cs
+++ b/Maui.PDFView/Platforms/Windows/PdfViewHandler.cs
@@ -1,10 +1,12 @@
 ﻿using Maui.PDFView.Events;
+using Microsoft.Maui.Controls.Compatibility;
 using Microsoft.Maui.Handlers;
 using Microsoft.UI.Xaml;
 using Microsoft.UI.Xaml.Controls;
 using Microsoft.UI.Xaml.Media;
 using Microsoft.UI.Xaml.Media.Imaging;
 using System.Numerics;
+using System.Reflection.Metadata;
 using Windows.Data.Pdf;
 using Windows.Graphics.Display;
 using Windows.Storage;
@@ -20,6 +22,7 @@ internal class PdfViewHandler : ViewHandler<IPdfView, ScrollViewer>
             [nameof(IPdfView.IsHorizontal)] = MapIsHorizontal,
             [nameof(IPdfView.MaxZoom)] = MapMaxZoom,
             [nameof(IPdfView.PageAppearance)] = MapPageAppearance,
+            [nameof(IPdfView.PageIndex)] = MapPageIndex,
         };
 
         private ScrollViewer _scrollViewer;
@@ -27,6 +30,9 @@ internal class PdfViewHandler : ViewHandler<IPdfView, ScrollViewer>
         private string _fileName;
 
         private PageAppearance _pageAppearance = new PageAppearance();
+        
+        private bool _isScrolling;
+        private bool _isPageIndexLocked;
 
         public PdfViewHandler() : base(PropertyMapper, null)
         {
@@ -55,6 +61,12 @@ static void MapPageAppearance(PdfViewHandler handler, IPdfView pdfView)
             handler._pageAppearance = pdfView.PageAppearance ?? new PageAppearance();
         }
 
+        static void MapPageIndex(PdfViewHandler handler, IPdfView pdfView)
+        {
+            handler.GotoPage(pdfView.PageIndex);
+        }
+
+
         protected override ScrollViewer CreatePlatformView()
         {
             _scrollViewer = new ScrollViewer
@@ -113,6 +125,9 @@ async Task RenderPages()
                     _stack.Children.Add(MakePage(bitmap, _pageAppearance));
                 }
             }
+
+            //  Reset page index
+            VirtualView.PageIndex = 0;
         }
 
         private UIElement MakePage(BitmapImage image, PageAppearance pageAppearance)
@@ -151,7 +166,32 @@ public static void AddShadow(Microsoft.UI.Xaml.Controls.Grid target, int ZDepth)
             target.Translation += new Vector3(0, 0, ZDepth);
         }
 
-        private void OnScrollViewerViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
+       
+
+        private void GotoPage(uint pageIndex)
+        {
+            if (_isScrolling)
+                return;
+
+            var layout = (StackPanel)_scrollViewer.Content;
+            if (pageIndex >= layout.Children.Count)
+                return;
+
+            var child = layout.Children[(int)pageIndex] as FrameworkElement;
+            if (child != null)
+            {
+                var transform = child.TransformToVisual(_scrollViewer);
+                var position = transform.TransformBounds(new(0, 0, child.ActualWidth, child.ActualHeight));
+
+                _isPageIndexLocked = true;
+                if (_stack.Orientation == Orientation.Vertical)
+                    _scrollViewer.ScrollToVerticalOffset(_scrollViewer.ZoomFactor*child.ActualOffset.Y);
+                else
+                    _scrollViewer.ScrollToHorizontalOffset(_scrollViewer.ZoomFactor * child.ActualOffset.X);
+            }
+        }
+
+        private void OnScrollViewerViewChanged(object? sender, ScrollViewerViewChangedEventArgs e)
         {
             // Get the index of the currently visible page
             var layout = (StackPanel)_scrollViewer.Content;
@@ -191,10 +231,20 @@ private void OnScrollViewerViewChanged(object sender, ScrollViewerViewChangedEve
             
             }
 
-            if (currentPage >= 0 && VirtualView.PageChangedCommand?.CanExecute(null) == true)
+            var newPageIndex = (uint)currentPage;
+            if (_isPageIndexLocked)
             {
-                VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs(currentPage + 1, layout.Children.Count));
+                _isPageIndexLocked = false;
+            }
+            else if (VirtualView.PageIndex != newPageIndex)
+            {
+                _isScrolling = true;
+                VirtualView.PageIndex = newPageIndex;
+                _isScrolling = false;
             }
+
+            if (VirtualView.PageChangedCommand?.CanExecute(null) == true)
+                VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs(currentPage + 1, layout.Children.Count));
         }
     }
 }
diff --git a/Maui.PDFView/Platforms/iOS/PdfViewHandler.cs b/Maui.PDFView/Platforms/iOS/PdfViewHandler.cs
index 9e33042..c1420c0 100644
--- a/Maui.PDFView/Platforms/iOS/PdfViewHandler.cs
+++ b/Maui.PDFView/Platforms/iOS/PdfViewHandler.cs
@@ -2,7 +2,9 @@
 using Maui.PDFView.Events;
 using Maui.PDFView.Helpers;
 using Microsoft.Maui.Handlers;
+using Microsoft.Maui.Layouts;
 using PdfKit;
+using System.Reflection.Metadata;
 using UIKit;
 
 namespace Maui.PDFView.Platforms.iOS
@@ -15,11 +17,14 @@ internal class PdfViewHandler : ViewHandler<IPdfView, PdfKit.PdfView>
             [nameof(IPdfView.IsHorizontal)] = MapIsHorizontal,
             [nameof(IPdfView.MaxZoom)] = MapMaxZoom,
             [nameof(IPdfView.PageAppearance)] = MapPageAppearance,
+            [nameof(IPdfView.PageIndex)] = MapPageIndex,
         };
 
         private string _fileName;
         private PageAppearance _appearance = new();
         private readonly DesiredSizeHelper _sizeHelper = new();
+        
+        private bool _isScrolling;
 
         public PdfViewHandler() : base(PropertyMapper, null)
         {
@@ -52,6 +57,11 @@ static void MapPageAppearance(PdfViewHandler handler, IPdfView pdfView)
             SetPageAppearance(handler, appearance);
         }
 
+        static void MapPageIndex(PdfViewHandler handler, IPdfView pdfView)
+        {
+            handler.GotoPage(pdfView.PageIndex);
+        }
+
         private static void SetPageAppearance(PdfViewHandler handler, PageAppearance appearance)
         {
             //  set shadow
@@ -118,6 +128,26 @@ private void RenderPages()
             PlatformView.AutoScales = true;
         }
 
+        private void GotoPage(uint pageIndex)
+        {
+            if (_isScrolling)
+                return;
+
+            var document = PlatformView.Document;
+            if (document is null)
+                return;
+
+            if (pageIndex >= document.PageCount)
+                return;
+
+            var newPage = document.GetPage((nint)pageIndex);
+
+            if (newPage is null)
+                return;
+
+            PlatformView.GoToPage(newPage);
+        }
+
         private void PageChangedNotificationHandler(NSNotification notification)
         {
             var currentPage = PlatformView.CurrentPage;
@@ -128,10 +158,18 @@ private void PageChangedNotificationHandler(NSNotification notification)
             if (document is null)
                 return;
 
-            if (!(VirtualView.PageChangedCommand?.CanExecute(null) ?? false)) 
+            var newPageIndex = (uint)document.GetPageIndex(currentPage);
+            if (VirtualView.PageIndex != newPageIndex)
+            {
+                _isScrolling = true;
+                VirtualView.PageIndex = newPageIndex;
+                _isScrolling = false;
+            }
+                
+            if (!(VirtualView.PageChangedCommand?.CanExecute(null) ?? false))
                 return;
 
-            VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs((int)(document.GetPageIndex(currentPage) + 1), (int)document.PageCount));
+            VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs((int)newPageIndex+1, (int)document.PageCount));
         }
         
         private void CropPages(PdfKit.PdfDocument pdfdoc, Thickness cropBounds)


Reviews:
user: login: vitalii-vov
state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-05-15T13:49:34Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:53:57Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:57:10Z
user: login: vitalii-vov
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-15T14:03:20Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T14:03:33Z
user: login: vitalii-vov
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-15T14:17:19Z
user: login: vitalii-vov
state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-05-15T15:08:54Z
user: login: vitalii-vov
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-15T15:40:06Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T19:53:31Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T20:01:35Z
user: login: vitalii-vov
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-15T20:10:15Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T20:14:53Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T05:04:12Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T05:04:38Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T05:05:12Z
user: login: vitalii-vov
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-16T14:27:28Z
user: login: vitalii-vov
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-16T14:32:13Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T16:59:17Z
user: login: jldearmas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T16:59:30Z
user: login: vitalii-vov
state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-05-20T15:01:08Z
user: login: vitalii-vov
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-20T15:21:55Z

Review comments:
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: Why are you skipping page number 0?
Why don't you do something like this:
```C#
if (pageNumber >= layoutManager.ItemCount)
   return;
```
created_at: 2025-05-14T13:31:08Z
author_association: OWNER
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
+                return;
+
+            layoutManager.ScrollToPosition((int)pageNumber - 1);
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: Does it work during zoomed in?
created_at: 2025-05-14T13:32:38Z
author_association: OWNER
diff_hunk: @@ -209,8 +225,19 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                if (currentPage >= 0)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: Why you check if (currentPage >= 0)?
created_at: 2025-05-14T13:38:05Z
author_association: OWNER
diff_hunk: @@ -217,8 +233,16 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                if (currentPage >= 0)
+                {
+                    var newPage = (uint)currentPage + 1;
+                    if (_handler.VirtualView.PageNumber != newPage)
+                        _handler.VirtualView.PageNumber = newPage;
+
+                    if (_handler.VirtualView.PageChangedCommand?.CanExecute(null) == true)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: The additional `CanExecute` check may be unnecessary, because without it the command works with the example below. Perhaps it should be done when creating `ICommand` manually?
```C#
private bool IsPageChangedExcutable() => false;
[RelayCommand(CanExecute = nameof(IsPageChangedExcutable))] 
private void PageChanged(PageChangedEventArgs args)
{
    PagePosition = $"{args.CurrentPage} of {args.TotalPages}";
    Debug.WriteLine($"Current page: {args.CurrentPage} of {args.TotalPages}");
}
```
created_at: 2025-05-14T14:25:10Z
author_association: OWNER
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: The matter is that PageNumber is not a page index, but the printed page number, so it start at 1 (not at 0)
created_at: 2025-05-15T13:53:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
+                return;
+
+            layoutManager.ScrollToPosition((int)pageNumber - 1);
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: Yes, it works. I'm doing something similar to Mac and iOS and should work too. In the case of Windows Platform there was a bug that I fixed in a new commit I pushed last night. 

By the way, fixing that bug, I also found and fixed another issue (for all platforms) related with update PageNumber during scroll.
created_at: 2025-05-15T13:57:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: I believe we should avoid handling view-related logic (like page number) outside the `ViewModel` layer. Instead, we should just work with indexes and let the `ViewModel` decide how to present them.
Otherwise, we end up introducing unnecessary UI-specific operations across the codebase, such as 
```C#
layoutManager.ScrollToPosition((int)pageNumber - 1);
```
created_at: 2025-05-15T14:03:20Z
author_association: OWNER
diff_hunk: @@ -209,8 +225,19 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                if (currentPage >= 0)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: My bad, that's not necessary, I'll remove it.
created_at: 2025-05-15T14:03:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: I think we should rename `PageNumber` to `PageIndex` in `IPdfView` to consistently work with indexes. The `ViewModel` should be responsible for converting an index into a page number.
created_at: 2025-05-15T14:17:19Z
author_association: OWNER
diff_hunk: @@ -126,8 +126,13 @@ private void RenderPages()
             PlatformView.AutoScales = true;
         }
 
+        private bool isScrolling;
+
         private void GotoPage(uint pageNumber)
         {
+            if (isScrolling)
+                return;
path: Maui.PDFView/Platforms/iOS/PdfViewHandler.cs
user: login: vitalii-vov
body: What problem does this piece of code solve?
If you need to stop scrolling while selecting a page, maybe it's worth considering stopping the scroll animation with `scrollView.setContentOffset(scrollView.contentOffset, animated: false)` before setting the page index?
created_at: 2025-05-15T15:07:01Z
author_association: OWNER
diff_hunk: @@ -171,8 +176,7 @@ private void GotoPage(uint pageNumber)
                 var transform = child.TransformToVisual(_scrollViewer);
                 var position = transform.TransformBounds(new(0, 0, child.ActualWidth, child.ActualHeight));
 
-                //this.pageNumber = pageNumber;
-                _scrollViewer.ChangeView(child.ActualOffset.X, child.ActualOffset.Y, 1, true);
+                _scrollViewer.ScrollToVerticalOffset(_scrollViewer.ZoomFactor*child.ActualOffset.Y);
path: Maui.PDFView/Platforms/Windows/PdfViewHandler.cs
user: login: vitalii-vov
body: Does this work for horizontal scrolling as well?
created_at: 2025-05-15T15:08:49Z
author_association: OWNER
diff_hunk: @@ -191,9 +216,17 @@ private void OnScrollViewerViewChanged(object sender, ScrollViewerViewChangedEve
             
             }
 
-            if (currentPage >= 0 && VirtualView.PageChangedCommand?.CanExecute(null) == true)
+            if (currentPage >= 0)
             {
-                VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs(currentPage + 1, layout.Children.Count));
+                var newPage = (uint)currentPage + 1;
+                if (VirtualView.PageNumber != newPage)
+                {
+                    VirtualView.PageNumber = newPage;
+                    if (VirtualView.PageChangedCommand?.CanExecute(null) == true)
+                    {
+                        VirtualView.PageChangedCommand.Execute(new PageChangedEventArgs(currentPage + 1, layout.Children.Count));
+                    }
path: Maui.PDFView/Platforms/Windows/PdfViewHandler.cs
user: login: vitalii-vov
body: As I see from the code, `currentPage + 1` was originally added by me so that `PageChangedEventArgs` would display the page number instead of the index, so this mistake was initially mine, and you probably followed that example. I think in the future I’ll make a change to fix this and replace `CurrentPage` with `CurrentPageIndex` or something like that.
created_at: 2025-05-15T15:39:52Z
author_association: OWNER
diff_hunk: @@ -217,8 +233,16 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                if (currentPage >= 0)
+                {
+                    var newPage = (uint)currentPage + 1;
+                    if (_handler.VirtualView.PageNumber != newPage)
+                        _handler.VirtualView.PageNumber = newPage;
+
+                    if (_handler.VirtualView.PageChangedCommand?.CanExecute(null) == true)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: That code above (using CommunityToolKit .MVVM), create a **Command** that implemented both methods:
- CanExecute
- Execute
with the actions/delegates supplied. If the programmer don't supply an action for implement **CanExecute**, this method returns true.

But the code that that call a **Command** has the responsibility of check with **CanExecute**. 
created_at: 2025-05-15T19:53:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -126,8 +126,13 @@ private void RenderPages()
             PlatformView.AutoScales = true;
         }
 
+        private bool isScrolling;
+
         private void GotoPage(uint pageNumber)
         {
+            if (isScrolling)
+                return;
path: Maui.PDFView/Platforms/iOS/PdfViewHandler.cs
user: login: jldearmas
body: The matter is that set the scroller to a page's top (at least in Windows Platform, and seems the same in Android) align the page's top with the top of the scroller, so when the user scroll the PDF, if the GotoPage is executed, there is a weird visual effect; so that code it's to avoid that. It doesn't have to do with scroll animation.
created_at: 2025-05-15T20:01:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -126,8 +126,13 @@ private void RenderPages()
             PlatformView.AutoScales = true;
         }
 
+        private bool isScrolling;
+
         private void GotoPage(uint pageNumber)
         {
+            if (isScrolling)
+                return;
path: Maui.PDFView/Platforms/iOS/PdfViewHandler.cs
user: login: vitalii-vov
body: As I see it, there may be a situation of missing a command call, in case of calling it sequentially from the code. For example, if at the moment of `GotoPage` call `isScrolling == true`.
created_at: 2025-05-15T20:10:15Z
author_association: OWNER
diff_hunk: @@ -171,8 +176,7 @@ private void GotoPage(uint pageNumber)
                 var transform = child.TransformToVisual(_scrollViewer);
                 var position = transform.TransformBounds(new(0, 0, child.ActualWidth, child.ActualHeight));
 
-                //this.pageNumber = pageNumber;
-                _scrollViewer.ChangeView(child.ActualOffset.X, child.ActualOffset.Y, 1, true);
+                _scrollViewer.ScrollToVerticalOffset(_scrollViewer.ZoomFactor*child.ActualOffset.Y);
path: Maui.PDFView/Platforms/Windows/PdfViewHandler.cs
user: login: jldearmas
body: I fixed in a version I'll push soon
created_at: 2025-05-15T20:14:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: **Done**
created_at: 2025-05-16T05:04:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -209,8 +225,19 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                if (currentPage >= 0)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: **Done**
created_at: 2025-05-16T05:04:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -171,8 +176,7 @@ private void GotoPage(uint pageNumber)
                 var transform = child.TransformToVisual(_scrollViewer);
                 var position = transform.TransformBounds(new(0, 0, child.ActualWidth, child.ActualHeight));
 
-                //this.pageNumber = pageNumber;
-                _scrollViewer.ChangeView(child.ActualOffset.X, child.ActualOffset.Y, 1, true);
+                _scrollViewer.ScrollToVerticalOffset(_scrollViewer.ZoomFactor*child.ActualOffset.Y);
path: Maui.PDFView/Platforms/Windows/PdfViewHandler.cs
user: login: jldearmas
body: **Done**
created_at: 2025-05-16T05:05:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: It would be great if the line
```C#
if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
```
be changed to the string
```C#
if (pageNumber >= layoutManager.ItemCount)
```
in all platform renderers.
created_at: 2025-05-16T14:27:28Z
author_association: OWNER
diff_hunk: @@ -209,8 +225,19 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                if (currentPage >= 0)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: It still available on [Windows](https://github.com/jldearmas/Maui.PDFView/blob/6afa614b0214ebe16e3879bb2386af768dc9924e/Maui.PDFView/Platforms/Windows/PdfViewHandler.cs#L229)
created_at: 2025-05-16T14:32:13Z
author_association: OWNER
diff_hunk: @@ -209,8 +225,19 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
                     }
                 }
 
-                // Execute the command if available
-                _handler.VirtualView.PageChangedCommand?.Execute(new PageChangedEventArgs(currentPage + 1, layoutManager.ItemCount));
+                if (currentPage >= 0)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: **Done!!**
created_at: 2025-05-16T16:59:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -157,7 +163,17 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private void GotoPage(uint pageNumber)
+        {
+            var layoutManager = (LinearLayoutManager)_recycleView.GetLayoutManager()!;
+
+            if (pageNumber == 0 || layoutManager.ItemCount <= pageNumber - 1)
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: jldearmas
body: **Done!!**
created_at: 2025-05-16T16:59:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -165,7 +171,24 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private bool isScrolling;
+        private bool isPageIndexLocked;
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: Private variables must be declared according to the general coding style, that is, starting with an underscore:
```C#
private bool _isScrolling;
```
instead of 
```C#
private bool isScrolling;
```

They should also be declared before the constructor to maintain the overall code structure.
This rule applies to all code, not just this part.
created_at: 2025-05-20T15:00:55Z
author_association: OWNER
diff_hunk: @@ -165,7 +171,24 @@ void RenderPages()
 
             return matrix;
         }
-        
+
+        private bool isScrolling;
+        private bool isPageIndexLocked;
path: Maui.PDFView/Platforms/Android/PdfViewHandler.cs
user: login: vitalii-vov
body: Fixed
created_at: 2025-05-20T15:21:55Z
author_association: OWNER

PR comments:
user: login: jldearmas
created_at: 2025-05-14T23:28:01Z
body: Testing in Android

![image](https://github.com/user-attachments/assets/13217121-849b-4c5a-bf88-9d8afb48684b)

author_association: CONTRIBUTOR
user: login: jldearmas
created_at: 2025-05-14T23:31:14Z
body: Testing in Windows

![image](https://github.com/user-attachments/assets/821279b4-bc48-4e83-8665-7f86d2633bfb)

author_association: CONTRIBUTOR
user: login: vitalii-vov
created_at: 2025-05-15T00:01:00Z
body: Hi @jldearmas can you answering for the questions about parts of code what I requested?
author_association: OWNER
user: login: jldearmas
created_at: 2025-05-15T00:26:52Z
body: OK... No problem, except I can't find the questions. Where are them? 
author_association: CONTRIBUTOR
user: login: vitalii-vov
created_at: 2025-05-15T00:35:57Z
body: The code review requests are present on this page, but they may be collapsed in your view, which could explain why they are not visible.

<img width="1048" alt="Screenshot 2025-05-14 at 7 32 24 PM" src="https://github.com/user-attachments/assets/7344644a-02f4-40e4-a135-7a933b1629a9" />

author_association: OWNER
user: login: jldearmas
created_at: 2025-05-15T05:37:07Z
body: GitHub is working different for me, see my page, there is no code review section

![image](https://github.com/user-attachments/assets/74df9cfb-ec21-489d-a110-aeeb3c0c3ff3)

author_association: CONTRIBUTOR
user: login: jldearmas
created_at: 2025-05-15T05:59:41Z
body: Anyway, I saw your questions in the screenshot that you post:

1. About **skipping pageNumber 0**. The matter is that PageNumber is not a page index, but the printed page number, so it start at 1 (not at 0)
2. About **setting PageNumber when zoomed in** for Android, Mac and iOS there is no problem. In the case of Windows Platform there was a bug that I fixed. Doing that I also found and fixed another **issue** (for all platforms) related with **update PageNumber during scroll**.
author_association: CONTRIBUTOR
user: login: jldearmas
created_at: 2025-05-16T05:18:22Z
body: **Windows Platform**

![image](https://github.com/user-attachments/assets/2866caa5-2329-48c3-8d47-59a92125b6fb)

author_association: CONTRIBUTOR
user: login: jldearmas
created_at: 2025-05-16T05:28:09Z
body: **Android Platform**

![image](https://github.com/user-attachments/assets/3c989fdf-7c43-4c9c-992b-dfbfb15e1dde)

author_association: CONTRIBUTOR
user: login: vitalii-vov
created_at: 2025-05-17T02:10:46Z
body: Hello @jldearmas ,
I'm trying to test a new feature and encountered some strange behavior on Android, which I demonstrated in the video.

As shown in the video, when switching pages, we sometimes don't receive a callback from the control.
You can see that the page numbers change like 1/5, 3/5, 4/5, etc., meaning that 2/5 is being skipped.
The OnScrolled function is not always triggered.

[android-page-index-bug.webm](https://github.com/user-attachments/assets/64fdcb27-70a7-4c74-a24a-5580dcd89fd9)


**update:**
I have fixed it

author_association: OWNER
user: login: jldearmas
created_at: 2025-05-20T22:06:14Z
body: So, is there something pending?
author_association: CONTRIBUTOR
user: login: vitalii-vov
created_at: 2025-05-21T00:45:24Z
body: Overall, this build looks ready for release on `iOS`, `macOS`, and `Android`, but I haven’t tested it on `Windows` yet. I didn’t have enough time for that today, but I’ll check it as soon as possible.

Also, I’ve been thinking that the `MaxPageIndex` property you initialize [here](https://github.com/jldearmas/Maui.PDFView/blob/58d1dc24c96ded1dcf4375530fbb5b8eeecb955d/Example/Business/UI/ViewModels/MainPageViewModel.cs#L33) could potentially be a `TwoWay` bindable property of the `PdfView` component. However, I’m not entirely sure whether it’s worth modifying the library for that, or if it’s better to accept it as is. 

But in general, I think that after testing on Windows, I will accept your contribution without any additional changes, as it could be quite useful for many users.
author_association: OWNER
user: login: vitalii-vov
created_at: 2025-05-21T02:16:00Z
body: There is some problem on Windows — when we change Uri Current index not change
author_association: OWNER
user: login: jldearmas
created_at: 2025-05-21T02:51:45Z
body: Thanks, was a pleasure work with you
author_association: CONTRIBUTOR
user: login: vitalii-vov
created_at: 2025-05-21T03:09:28Z
body: Thank you, @jldearmas, for your contribution to the library. Your involvement in this feature is greatly appreciated.
author_association: OWNER