Jelajahi Sumber

Interim Update

Frank van den Bos 1 tahun lalu
induk
melakukan
2a445d68d9

+ 56 - 48
InABox.Client.RPC/Transports/Socket/RPCClientSocketTransport.cs

@@ -103,66 +103,74 @@ namespace InABox.Rpc
         
         private WebSocket? CreateSocket(string url, bool secure, CancellationToken ct)
         {
-            //WebsocketClient client;
-
-            //WebSocket socket = null;
+            WebSocket? client = null;
+            
             var address = $"{(secure ? "wss" : "ws")}://{url}";
-            var client = new WebSocket(address);
-
-            var openEvent = new ManualResetEventSlim();
-            var open = false;
-            void onOpen(object s, EventArgs e)
-            {
-                open = true;
-                openEvent.Set();
-            }
-            void onClose(object s, EventArgs e)
+            try
             {
-                openEvent.Set();
-            }
+                client = new WebSocket(address);
 
-            client.Opened += onOpen;
-            client.Closed += onClose;
+                var openEvent = new ManualResetEventSlim();
+                var open = false;
+                void onOpen(object s, EventArgs e)
+                {
+                    open = true;
+                    openEvent.Set();
+                }
+                void onClose(object s, EventArgs e)
+                {
+                    openEvent.Set();
+                }
 
-            client.Error += Client_Error;
-            client.MessageReceived += Client_MessageReceived;
-            client.DataReceived += Client_DataReceived;
-            client.Open();
+                client.Opened += onOpen;
+                client.Closed += onClose;
 
-            openEvent.Wait(ct);
+                client.Error += Client_Error;
+                client.MessageReceived += Client_MessageReceived;
+                client.DataReceived += Client_DataReceived;
+                client.Open();
 
-            if (!open)
-            {
-                return null;
-            }
+                openEvent.Wait(ct);
 
-            client.Opened -= onOpen;
-            client.Closed -= onClose;
+                if (!open)
+                {
+                    return null;
+                }
 
-            client.Opened += Client_Opened;
-            client.Closed += Client_Closed;
+                client.Opened -= onOpen;
+                client.Closed -= onClose;
+
+                client.Opened += Client_Opened;
+                client.Closed += Client_Closed;
 
-            DoOpen();
-            _host = url;
-
-            // Time to wait before disconnect - the default meant that the client disconnected during debugging, since the ping would fail
-            /*socket.WaitTime = TimeSpan.FromSeconds(20);
-            socket.OnOpen -= Socket_OnOpen;
-            socket.OnError -= Socket_OnError;
-            socket.OnClose -= Socket_OnClose;
-            socket.OnMessage -= Socket_OnMessage;
-            socket.Connect();
-            if (socket.ReadyState == WebSocketState.Open)
-            {
                 DoOpen();
+                _host = url;
+
+                // Time to wait before disconnect - the default meant that the client disconnected during debugging, since the ping would fail
+                /*socket.WaitTime = TimeSpan.FromSeconds(20);
+                socket.OnOpen -= Socket_OnOpen;
+                socket.OnError -= Socket_OnError;
+                socket.OnClose -= Socket_OnClose;
+                socket.OnMessage -= Socket_OnMessage;
+                socket.Connect();
+                if (socket.ReadyState == WebSocketState.Open)
+                {
+                    DoOpen();
 
-                socket.OnOpen += Socket_OnOpen;
-                socket.OnError += Socket_OnError;
-                socket.OnClose += Socket_OnClose;
-                socket.OnMessage += Socket_OnMessage;
+                    socket.OnOpen += Socket_OnOpen;
+                    socket.OnError += Socket_OnError;
+                    socket.OnClose += Socket_OnClose;
+                    socket.OnMessage += Socket_OnMessage;
 
-                return socket;
-            }*/
+                    return socket;
+                }*/
+            }
+            catch (Exception e)
+            {
+                Console.WriteLine(e);
+                throw;
+            }
+            
             return client;
         }
 

+ 9 - 7
InABox.Mobile/InABox.Mobile.Shared/Components/MobileCheckBox/MobileCheckBox.xaml

@@ -8,13 +8,15 @@
         <mobile:CheckBoxImageConverter x:Key="CheckBoxImageConverter" Checked="checked" Unchecked="unchecked"/>
     </ContentView.Resources>
     <ContentView.ControlTemplate>
-        <ControlTemplate>
-            <ImageButton 
-                Source="{TemplateBinding IsChecked, Converter={StaticResource CheckBoxImageConverter}}" 
-                Clicked="ToggleCheck" 
-                HeightRequest="30"
-                WidthRequest="30"
-              />           
+        <ControlTemplate >
+            <Grid BindingContext="{TemplateBinding BindingContext.DataContext}">
+                <ImageButton 
+                    Source="{TemplateBinding IsChecked, Converter={StaticResource CheckBoxImageConverter}}" 
+                    Clicked="ToggleCheck" 
+                    HeightRequest="30"
+                    WidthRequest="30"
+                  />   
+            </Grid>
         </ControlTemplate>
     </ContentView.ControlTemplate>
 </ContentView>

+ 8 - 2
InABox.Mobile/InABox.Mobile.Shared/Components/MobileCheckBox/MobileCheckBox.xaml.cs

@@ -20,7 +20,9 @@ namespace InABox.Mobile
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotImplementedException();
+            if (value is FileImageSource file)
+                return String.Equals(file.File, "checked");
+            return false;
         }
     }
     
@@ -37,7 +39,11 @@ namespace InABox.Mobile
         public bool IsChecked
         {
             get => (bool)GetValue(IsCheckedProperty);
-            set => SetValue(IsCheckedProperty,value);
+            set
+            {
+                SetValue(IsCheckedProperty, value);
+                OnPropertyChanged(nameof(IsChecked));
+            }
         }
 
         public event EventHandler Changed;

+ 9 - 3
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuButton.xaml.cs

@@ -10,6 +10,7 @@ using XF.Material.Forms.UI;
 namespace InABox.Mobile
 {
     
+    
     [XamlCompilation(XamlCompilationOptions.Compile)]
     public partial class MobileMenuButton
     {
@@ -18,10 +19,12 @@ namespace InABox.Mobile
 
         private MobileMenuButtonMenu _menu;
 
-        public IList<MobileMenuItem> Items => _menu.Items;
+        public IList<MobileMenuEntry> Items => _menu.Items;
         
         public RelativePosition Position { get; set; }
         
+        public event EventHandler Appearing;
+        
         public ImageSource Image
         {
             get => _image.Source;
@@ -33,14 +36,16 @@ namespace InABox.Mobile
         public MobileMenuButton()
         {
             _menu = new MobileMenuButtonMenu();
+            _menu.ItemClicked += (sender,args) => _popup.Dismiss();
             InitializeComponent();
             _popup = new SfPopupLayout();
             Position = RelativePosition.AlignToLeftOf;
         }
-        
+
         private void _image_OnClicked(object sender, EventArgs e)
         {
-            if (Items.Any())
+            Appearing?.Invoke(this, EventArgs.Empty);
+            if (_menu.Items.Any())
             {
                 _popup.PopupView.ContentTemplate = new DataTemplate(() => _menu);
                 _popup.PopupView.ShowFooter = false;
@@ -49,6 +54,7 @@ namespace InABox.Mobile
                 _popup.PopupView.PopupStyle.CornerRadius = 5;
                 _popup.Padding = new Thickness(5);
                 GetOffset(out double x, out double y);
+                
                 _popup.ShowRelativeToView(this, Position, x, y);
             }
             else

+ 67 - 19
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuButtonMenu.xaml

@@ -5,34 +5,82 @@
              xmlns:mobile="clr-namespace:InABox.Mobile;assembly=InABox.Mobile.Shared"
              x:Class="InABox.Mobile.MobileMenuButtonMenu" Padding="5">
     <ContentView.BindingContext>
-        <mobile:MobileMenuButtonMenuViewModel x:Name="_viewModel"/>
+        <mobile:MobileMenuButtonMenuViewModel 
+            x:Name="_viewModel" 
+            LayoutChanged="_viewModel_OnLayoutChanged" 
+            ItemClicked="_viewModel_OnItemClicked"/>
     </ContentView.BindingContext>
     <ContentView.Content>
-        <StackLayout 
+        <Grid 
             x:Name="_menu" 
-            Orientation="Vertical"
             VerticalOptions="StartAndExpand" 
             HorizontalOptions="StartAndExpand"
             Margin="0,5,0,0"
-            Spacing="10"
-            BindableLayout.ItemsSource = "{Binding Items}"
-            BindableLayout.EmptyView="Nothing!">
+            RowSpacing="5"
+            BindableLayout.ItemsSource = "{Binding VisibleItems}"
+            >
+            <BindableLayout.EmptyView>
+                <Label 
+                    FontSize="Micro"
+                    Text="(No Options)"
+                    TextColor="Silver"/>
+            </BindableLayout.EmptyView>
+            
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="Auto"/>
+            </Grid.ColumnDefinitions>
+            
             <BindableLayout.ItemTemplate>
-                <DataTemplate x:DataType="mobile:MobileMenuItem">
-                    <Label Text="{Binding Text}" 
-                           VerticalOptions="CenterAndExpand" 
-                           HorizontalOptions="FillAndExpand" 
-                           HorizontalTextAlignment="Start"
-                           VerticalTextAlignment="Center"
-                           FontSize="Small"
-                           Padding="2,5,2,2">
-                        <Label.GestureRecognizers>
-                            <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" />
-                        </Label.GestureRecognizers>    
-                    </Label>
+                <DataTemplate x:DataType="mobile:MobileMenuEntry">
+                    
+                    <StackLayout
+                        Orientation="Vertical"
+                        IsVisible="{Binding IsVisible}"
+                        HorizontalOptions="Fill"
+                        Grid.Row="{Binding Index}">
+                        
+                        <Label 
+                            Text="{Binding Text}" 
+                            VerticalOptions="CenterAndExpand" 
+                            HorizontalOptions="Fill" 
+                            HorizontalTextAlignment="Start"
+                            VerticalTextAlignment="Center"
+                            FontSize="Micro"
+                            Padding="2,5,2,2"
+                            IsVisible="False">
+                            
+                            <Label.GestureRecognizers>
+                                <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" />
+                            </Label.GestureRecognizers>    
+                            
+                            <Label.Triggers>
+                                <DataTrigger TargetType="Label" Binding="{Binding Type}" Value="Item">
+                                    <Setter Property="IsVisible" Value="True" />
+                                </DataTrigger>
+                            </Label.Triggers>
+                            
+                        </Label>
+                        
+                        <BoxView
+                            HeightRequest="1"
+                            VerticalOptions="Center"
+                            HorizontalOptions="Fill"
+                            BackgroundColor="Silver"
+                            Opacity="0.5"
+                            Margin="2,5,2,2"
+                            IsVisible="False">
+                            <BoxView.Triggers>
+                                <DataTrigger TargetType="BoxView" Binding="{Binding Type}" Value="Separator">
+                                    <Setter Property="IsVisible" Value="True" />
+                                </DataTrigger>
+                            </BoxView.Triggers>
+                        </BoxView>
+                        
+                    </StackLayout>
+                    
                 </DataTemplate>
             </BindableLayout.ItemTemplate>
             
-        </StackLayout>
+        </Grid>
     </ContentView.Content>
 </ContentView>

+ 16 - 26
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuButtonMenu.xaml.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -10,34 +9,12 @@ using Xamarin.Forms.Xaml;
 
 namespace InABox.Mobile
 {
-
-    
-    public class MobileMenuItem : BindableObject
-    {
-        public String Text { get; set; }
-        
-        public event EventHandler Clicked;
-
-        public void DoClicked()
-        {
-            Clicked?.Invoke(this, EventArgs.Empty);
-        }
-    }
-    
-    public class MobileMenuButtonMenuViewModel : BindableObject
-    {
-        public IList<MobileMenuItem> Items { get; private set; }
-        
-        public MobileMenuButtonMenuViewModel()
-        {
-            Items = new ObservableCollection<MobileMenuItem>();
-        }
-    }
-    
     [XamlCompilation(XamlCompilationOptions.Compile)]
     public partial class MobileMenuButtonMenu
     {
-        public IList<MobileMenuItem> Items => _viewModel.Items;
+        public IList<MobileMenuEntry> Items => _viewModel.Items;
+        
+        public IList<MobileMenuEntry> VisibleItems => _viewModel.VisibleItems;
         
         public MobileMenuButtonMenu()
         {
@@ -49,6 +26,19 @@ namespace InABox.Mobile
             if ((sender as Label)?.BindingContext is MobileMenuItem item)
                 item.DoClicked();
         }
+
+        private void _viewModel_OnLayoutChanged(object sender, MobileMenuButtonLayoutChangedEventArgs args)
+        {
+            _menu.RowDefinitions.Clear();
+            for (int i=0; i< args.RowCount; i++)
+                _menu.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto});
+        }
+
+        public event EventHandler ItemClicked;
         
+        private void _viewModel_OnItemClicked(object sender, EventArgs e)
+        {
+            ItemClicked?.Invoke(this, EventArgs.Empty);
+        }
     }
 }

+ 60 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuButtonMenuViewModel.cs

@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Xamarin.Forms;
+
+namespace InABox.Mobile
+{
+    
+    public class MobileMenuButtonLayoutChangedEventArgs : EventArgs
+    {
+        public int RowCount { get; private set; }
+
+        public MobileMenuButtonLayoutChangedEventArgs(int rowcount)
+        {
+            RowCount = rowcount;
+        }
+    }
+    public delegate void MobileMenuButtonLayoutChangedEvent(object sender, MobileMenuButtonLayoutChangedEventArgs args);
+    
+    public class MobileMenuButtonMenuViewModel : BindableObject
+    {
+        private readonly ObservableCollection<MobileMenuEntry> _items;
+        public IList<MobileMenuEntry> Items => _items;
+
+        private readonly ObservableCollection<MobileMenuEntry> _visibleItems;
+        public IList<MobileMenuEntry> VisibleItems => _visibleItems;
+        
+        public event MobileMenuButtonLayoutChangedEvent LayoutChanged;
+
+        public event EventHandler ItemClicked;
+        
+        public MobileMenuButtonMenuViewModel()
+        {
+            _items = new ObservableCollection<MobileMenuEntry>();
+
+            _visibleItems = new ObservableCollection<MobileMenuEntry>();
+            _items.CollectionChanged += (sender, args) =>
+            {
+                
+                DoLayout();
+            };
+        }
+
+        private void DoLayout()
+        {
+            VisibleItems.Clear();
+            int iRow = 0;
+            foreach (var item in Items.Where(x => x.IsVisible))
+            {
+                item.Index = iRow;
+                item.VisibleChanged = DoLayout;
+                item.AfterClick = () => ItemClicked?.Invoke(this, EventArgs.Empty);
+                VisibleItems.Add(item);
+                iRow++;
+            }
+            LayoutChanged?.Invoke(this,new MobileMenuButtonLayoutChangedEventArgs(iRow));
+        }
+    }
+}

+ 28 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuEntry.cs

@@ -0,0 +1,28 @@
+using System;
+using Xamarin.Forms;
+
+namespace InABox.Mobile
+{
+    public abstract class MobileMenuEntry : BindableObject
+    {
+        private bool _isVisible;
+
+        public Action VisibleChanged;
+        
+        public Action AfterClick;
+
+        public bool IsVisible
+        {
+            get => _isVisible;
+            set
+            {
+                _isVisible = value;
+                VisibleChanged?.Invoke();
+            } 
+        }
+
+        public abstract MobileMenuEntryType Type { get; }
+        public int Index { get; set; }
+        public string Text { get; set; }
+    }
+}

+ 8 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuEntryType.cs

@@ -0,0 +1,8 @@
+namespace InABox.Mobile
+{
+    public enum MobileMenuEntryType
+    {
+        Separator,
+        Item
+    }
+}

+ 25 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuItem.cs

@@ -0,0 +1,25 @@
+using System;
+
+namespace InABox.Mobile
+{
+    public class MobileMenuItem : MobileMenuEntry
+    {
+        
+        public override MobileMenuEntryType Type => MobileMenuEntryType.Item;
+        
+        public event EventHandler Clicked;
+
+        
+
+        public void DoClicked()
+        {
+            Clicked?.Invoke(this, EventArgs.Empty);
+            AfterClick?.Invoke();
+        }
+
+        public MobileMenuItem()
+        {
+            IsVisible = true;
+        }
+    }
+}

+ 12 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileMenuButton/MobileMenuSeparator.cs

@@ -0,0 +1,12 @@
+namespace InABox.Mobile
+{
+    public class MobileMenuSeparator : MobileMenuEntry
+    {
+        public override MobileMenuEntryType Type => MobileMenuEntryType.Separator;
+        
+        public MobileMenuSeparator()
+        {
+            IsVisible = true;
+        }
+    }
+}

+ 1 - 1
InABox.Mobile/InABox.Mobile.Shared/Components/MobileSearchBar/MobileSearchBar.xaml

@@ -48,7 +48,7 @@
                         BackgroundColor="{TemplateBinding TextBackgroundColor}"
                         TextColor="{TemplateBinding TextColor}"
                         Placeholder="{Binding PlaceHolder}"
-                        Margin="10,10,10,10"
+                        Margin="0"
                         Keyboard="Plain" VerticalTextAlignment="Center"
                     />
                     

+ 11 - 2
InABox.Mobile/InABox.Mobile.Shared/Components/MobileTabStrip/MobileTabStrip.xaml

@@ -11,11 +11,19 @@
         <Frame
             HasShadow="False" 
             Margin="0" 
-            Padding="0" 
+
             BorderColor="{Binding Source={RelativeSource AncestorType={x:Type mobile:MobileTabStrip}}, Path='UnselectedBackground'}" 
             BackgroundColor="{Binding Source={RelativeSource AncestorType={x:Type mobile:MobileTabStrip}}, Path='SeparatorColor'}" 
             CornerRadius="{Binding Source={RelativeSource AncestorType={x:Type mobile:MobileTabStrip}}, Path='CornerRadius'}"
             IsClippedToBounds="True">
+            <Frame.Padding>
+                <OnPlatform x:TypeArguments="Thickness">
+                    <OnPlatform.Platforms>
+                        <On Platform="iOS" Value="0" />
+                        <On Platform="Android" Value="1" />
+                    </OnPlatform.Platforms>
+                </OnPlatform>
+            </Frame.Padding>
             
             <Grid x:Name="_grid" ColumnSpacing="0">
                 
@@ -39,11 +47,12 @@
                         <Frame
                             HasShadow="False" 
                             Margin="0" 
-                            Padding="0" 
+                            Padding="0"
                             BorderColor="{Binding Source={RelativeSource AncestorType={x:Type mobile:MobileTabStrip}}, Path='UnselectedBackground'}" 
                             BackgroundColor="{Binding Source={RelativeSource AncestorType={x:Type mobile:MobileTabStrip}}, Path='SeparatorColor'}" 
                             CornerRadius="{Binding Source={RelativeSource AncestorType={x:Type mobile:MobileTabStrip}}, Path='CornerRadius'}"
                             IsClippedToBounds="True">
+
                             <Label 
                                 Grid.Row="0" 
                                 x:Name="_label"

+ 1 - 1
InABox.Mobile/InABox.Mobile.Shared/Components/MobileToolGrid/MobileToolItem.cs

@@ -40,7 +40,7 @@ namespace InABox.Mobile
             get { return (string)GetValue(IndicatorProperty); }
             set { 
                 SetValue(IndicatorProperty, value);
-                UpdateIndicator(); 
+                OnPropertyChanged(nameof(HasIndicator));
             }
         }