Password popup prototype
authork.stepaniuk <k.stepaniuk@samsung.com>
Fri, 27 Mar 2020 11:53:26 +0000 (12:53 +0100)
committerk.stepaniuk <k.stepaniuk@samsung.com>
Wed, 1 Apr 2020 07:29:20 +0000 (09:29 +0200)
Signed-off-by: k.stepaniuk <k.stepaniuk@samsung.com>
Add password characters and reveal button

Styling popup

Signed-off-by: k.stepaniuk <k.stepaniuk@samsung.com>
Replacing password entry

Signed-off-by: k.stepaniuk <k.stepaniuk@samsung.com>
Connecting correction

Signed-off-by: k.stepaniuk <k.stepaniuk@samsung.com>
14 files changed:
Oobe/OobeCommon/Styles/ButtonStyles.cs
Oobe/OobeCommon/Utils/Popup.cs
Oobe/OobeCommon/res/button/02_butt_2_empty_action.png [new file with mode: 0644]
Oobe/OobeCommon/res/button/02_butt_2_empty_disabled.png [new file with mode: 0644]
Oobe/OobeCommon/res/button/02_butt_2_empty_pressed.png [new file with mode: 0644]
Oobe/OobeWifi/Controls/Wifi/PasswordEntry.cs [new file with mode: 0644]
Oobe/OobeWifi/Controls/Wifi/WifiPasswordPopup.cs [new file with mode: 0644]
Oobe/OobeWifi/Controls/Wifi/WifiView.cs
Oobe/OobeWifi/WifiStep.cs
Oobe/OobeWifi/res/08_popup_body.png [new file with mode: 0644]
Oobe/OobeWifi/res/12_icon_eye_pw_hidden.png [new file with mode: 0644]
Oobe/OobeWifi/res/12_icon_eye_pw_hidden.svg [new file with mode: 0644]
Oobe/OobeWifi/res/12_icon_eye_pw_visible.png [new file with mode: 0644]
Oobe/OobeWifi/res/12_icon_eye_pw_visible.svg [new file with mode: 0644]

index 79bbeb1fe3aa52e6511cc4ffdbf4fd9aeeccfe24..8ba17e153275a386669968ac0b552c524bf718e5 100644 (file)
@@ -7,8 +7,21 @@ namespace Oobe.Common.Styles
     public class ButtonStyles
     {
         public static ButtonStyle Next = GetNextButtonStyle();
-        public static ButtonStyle Previous = new ButtonStyle
+        public static ButtonStyle Previous = GetPreviousButtonStyle();
+        public static ButtonStyle Skip = GetSkipButtonStyle();
+        public static ButtonStyle OK = GetOKButtonStyle();
+        public static ButtonStyle Cancel = GetCancelButtonStyle();
+        public static ButtonStyle Scan = GetScanButtonStyle();
+        public static ButtonStyle TurnOnOff = GetTurnOnOffButtonStyle();
+        public static ButtonStyle Reveal = GetRevealButtonStyle();
+        private static ButtonStyle GetPreviousButtonStyle() => new ButtonStyle
         {
+            BackgroundImage = new Selector<string>
+            {
+                Normal = NUIApplication.Current.DirectoryInfo.Resource + "button/02_butt_2_empty_action.png",
+                Pressed = NUIApplication.Current.DirectoryInfo.Resource + "button/02_butt_2_empty_pressed.png",
+                Disabled = NUIApplication.Current.DirectoryInfo.Resource + "button/02_butt_2_empty_disabled.png",
+            },
             Text = new TextLabelStyle
             {
                 PointSize = new Selector<float?>
@@ -22,12 +35,19 @@ namespace Oobe.Common.Styles
                 {
                     Normal = new Color(0.0f, 20.0f / 255.0f, 71 / 255.0f, 1.0f),
                     Pressed = new Color(41.0f / 255.0f, 91.0f / 255.0f, 178 / 255.0f, 1.0f),
-                }
+                },
+                FontFamily = GetNavigationFont(),
             },
             Size2D = new Size2D(240, 72),
         };
-        public static ButtonStyle Skip = GetSkipButtonStyle();
-        public static ButtonStyle Scan = new ButtonStyle
+
+        private static ButtonStyle GetCancelButtonStyle()
+        {
+            var style = GetPreviousButtonStyle();
+            style.Text.Text = "CANCEL";
+            return style;
+        }
+        private static ButtonStyle GetScanButtonStyle() => new ButtonStyle
         {
             BackgroundImage = new Selector<string>
             {
@@ -37,7 +57,7 @@ namespace Oobe.Common.Styles
             },
             Size2D = new Size2D(72, 32),
         };
-        public static ButtonStyle TurnOnOff = new ButtonStyle
+        private static ButtonStyle GetTurnOnOffButtonStyle() => new ButtonStyle
         {
             BackgroundImage = new Selector<string>
             {
@@ -48,7 +68,8 @@ namespace Oobe.Common.Styles
             },
             Size2D = new Size2D(72, 32),
         };
-        public static ButtonStyle AddNetwork = new ButtonStyle
+        public static ButtonStyle AddNetwork = GetAddNetworkButtonStyle();
+        private static ButtonStyle GetAddNetworkButtonStyle() => new ButtonStyle
         {
             BackgroundImage = new Selector<string>
             {
@@ -58,6 +79,13 @@ namespace Oobe.Common.Styles
             Size2D = new Size2D(42, 42),
         };
 
+        private static ButtonStyle GetOKButtonStyle()
+        {
+            var style = GetNextButtonStyle();
+            style.Text.Text = "OK";
+            return style;
+        }
+
         private static ButtonStyle GetSkipButtonStyle()
         {
             var style = GetNextButtonStyle();
@@ -81,9 +109,28 @@ namespace Oobe.Common.Styles
                     Pressed = 24.0f
                 },
                 TextColor = Color.White,
-                TranslatableText = "CONTINUE",
+                Text = "CONTINUE",
+                FontFamily = GetNavigationFont(),
             },
             Size2D = new Size2D(240, 72),
         };
+
+        private static ButtonStyle GetRevealButtonStyle() => new ButtonStyle
+        {
+            BackgroundImage = new Selector<string>
+            {
+                Normal = System.IO.Path.Combine(NUIApplication.Current.DirectoryInfo.Resource, "12_icon_eye_pw_hidden.png"),
+                Selected = System.IO.Path.Combine(NUIApplication.Current.DirectoryInfo.Resource, "12_icon_eye_pw_visible.png"),
+            },
+            Size2D = new Size2D(72, 32),
+        };
+
+        private static Selector<string> GetNavigationFont()
+        {
+            return new Selector<string>
+            {
+                Normal = "BreezeSans",
+            };
+        }
     }
 }
index 3ca64139e1f99968d884aa735f99c144685834ce..45c278f85230734bbdbbc4c6565ebc095aceaa63 100644 (file)
@@ -6,6 +6,8 @@ namespace OobeCommon.Utils
 {
     public static class Popup
     {
+        private static Layer layer = null;
+
         public static void ShowCentered(View view)
         {
             view.PositionUsesPivotPoint = true;
@@ -16,7 +18,8 @@ namespace OobeCommon.Utils
 
         public static void Show(View view)
         {
-            var layer = new Layer();
+            Dismiss();
+            layer = new Layer();
             var gray = new Tizen.NUI.Components.Control()
             {
                 WidthResizePolicy = ResizePolicyType.FillToParent,
@@ -27,8 +30,7 @@ namespace OobeCommon.Utils
             {
                 if (e.Touch.GetState(0) == PointStateType.Up)
                 {
-                    Window.Instance.RemoveLayer(layer);
-                    layer.Dispose();
+                    Dismiss();
                 }
                 return true;
             };
@@ -39,9 +41,14 @@ namespace OobeCommon.Utils
             Window.Instance.AddLayer(layer);
         }
 
-        private static bool Gray_TouchEvent(object source, View.TouchEventArgs e)
+        public static void Dismiss()
         {
-            throw new NotImplementedException();
+            if (layer != null)
+            {
+                Window.Instance.RemoveLayer(layer);
+                layer.Dispose();
+                layer = null;
+            }
         }
     }
 }
diff --git a/Oobe/OobeCommon/res/button/02_butt_2_empty_action.png b/Oobe/OobeCommon/res/button/02_butt_2_empty_action.png
new file mode 100644 (file)
index 0000000..064e783
Binary files /dev/null and b/Oobe/OobeCommon/res/button/02_butt_2_empty_action.png differ
diff --git a/Oobe/OobeCommon/res/button/02_butt_2_empty_disabled.png b/Oobe/OobeCommon/res/button/02_butt_2_empty_disabled.png
new file mode 100644 (file)
index 0000000..7a46210
Binary files /dev/null and b/Oobe/OobeCommon/res/button/02_butt_2_empty_disabled.png differ
diff --git a/Oobe/OobeCommon/res/button/02_butt_2_empty_pressed.png b/Oobe/OobeCommon/res/button/02_butt_2_empty_pressed.png
new file mode 100644 (file)
index 0000000..4c44848
Binary files /dev/null and b/Oobe/OobeCommon/res/button/02_butt_2_empty_pressed.png differ
diff --git a/Oobe/OobeWifi/Controls/Wifi/PasswordEntry.cs b/Oobe/OobeWifi/Controls/Wifi/PasswordEntry.cs
new file mode 100644 (file)
index 0000000..42e3a91
--- /dev/null
@@ -0,0 +1,38 @@
+using Tizen.NUI;
+
+namespace Oobe.Wifi.Controls.Wifi
+{
+    public class PasswordEntry : Tizen.NUI.BaseComponents.TextField
+    {
+        private bool revealed = false;
+        public string Password => Text;
+
+        public bool Revealed
+        {
+            get => revealed;
+            set
+            {
+                revealed = value;
+                if (revealed)
+                    revealPassword();
+                else
+                    hidePassword();
+                Text = Text; //for refreshing - causes resetting cursor
+            }
+        }
+
+        private void revealPassword()
+        {
+            var map = new PropertyMap();
+            map.Add("mode", new PropertyValue(0));
+            HiddenInputSettings = map;
+        }
+        private void hidePassword()
+        {
+            var map = new PropertyMap();
+            map.Add("mode", new PropertyValue(4));
+            map.Add("show_last_character_duration", new PropertyValue(500));
+            HiddenInputSettings = map;
+        }
+    }
+}
diff --git a/Oobe/OobeWifi/Controls/Wifi/WifiPasswordPopup.cs b/Oobe/OobeWifi/Controls/Wifi/WifiPasswordPopup.cs
new file mode 100644 (file)
index 0000000..317d98b
--- /dev/null
@@ -0,0 +1,159 @@
+using Oobe.Common.Styles;
+using System;
+using System.Threading.Tasks;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using OobeCommon;
+using Tizen.Network.WiFi;
+
+namespace Oobe.Wifi.Controls.Wifi
+{
+    class WifiPasswordPopup : View
+    {
+        private PasswordEntry passwordEntry = null;
+        private Button okButton;
+        private Button cancelButton;
+        private Button revealButton;
+        private TextLabel connectionFailure;
+        private const int minPasswordLength = 8;
+        private const int maxPasswordLength = 63;
+        private string backgroundImagePath = System.IO.Path.Combine(NUIApplication.Current.DirectoryInfo.Resource, "08_popup_body.png");
+        private WiFiAP wifiAp;
+
+        public string Password => passwordEntry.Password;
+
+        public WifiPasswordPopup(Tizen.Network.WiFi.WiFiAP wifiAp)
+        {
+            BackgroundImage = backgroundImagePath;
+            Size = new Size(808, 304);
+            Position = new Position(new Position2D(236, 116));
+            this.wifiAp = wifiAp;
+
+            passwordEntry = new PasswordEntry()
+            {
+                Size = new Size(584, 22),
+                Position = new Position(112, 144),
+                MaxLength = maxPasswordLength,
+                PixelSize = 15,
+                TextColor = new Color(0, 0x0C / 255.0f, 0x2B / 255.0f, 1.0f),
+                FontFamily = "BreezeSans",
+                FontStyle = FontsStyles.Regular(),
+                Revealed = false,
+            };
+            passwordEntry.TextChanged += (s, e) => okButton.IsEnabled = Password.Length >= minPasswordLength;
+
+            this.Add(passwordEntry);
+
+            this.Add(new View()
+            {
+                Size = new Size(584, 1),
+                Position = new Position(104, 160),
+                BackgroundColor = new Color(0xC3 / 255.0f, 0xCA / 255.0f, 0xD2 / 255.0f, 1.0f),
+            });
+
+            var titleLabel = new TextLabel
+            {
+                Size = new Size(808, 35),
+                Position = new Position(0, 20),
+                Text = "Enter password",
+                PixelSize = 28,
+                TextColor = new Color(0, 0x14 / 255.0f, 0x47 / 255.0f, 1.0f),
+                FontFamily = "BreezeSans",
+                FontStyle = FontsStyles.Light(),
+                HorizontalAlignment = HorizontalAlignment.Center,
+                VerticalAlignment = VerticalAlignment.Center,
+            };
+            this.Add(titleLabel);
+
+            var subtitleLabel = new TextLabel
+            {
+                Size = new Size(808, 25),
+                Position = new Position(0, 69),
+                Text = $"Enter password to join \"{wifiAp.NetworkInformation.Essid}\"",
+                PixelSize = 20,
+                TextColor = new Color(0, 0x14 / 255.0f, 0x47 / 255.0f, 1.0f),
+                FontFamily = "BreezeSans",
+                FontStyle = FontsStyles.Regular(),
+                HorizontalAlignment = HorizontalAlignment.Center,
+                VerticalAlignment = VerticalAlignment.Center,
+            };
+            this.Add(subtitleLabel);
+
+            connectionFailure = new TextLabel
+            {
+                Size = new Size(120, 16),
+                Position = new Position(116, 166),
+                Text = "Invalid password",
+                PixelSize = 12,
+                TextColor = new Color(0xAA / 255.0f, 0x18 / 255.0f, 0x18 / 255.0f, 1.0f),
+                FontFamily = "BreezeSans",
+                FontStyle = FontsStyles.Regular(),
+                HorizontalAlignment = HorizontalAlignment.Begin,
+                VerticalAlignment = VerticalAlignment.Center,
+            };
+            connectionFailure.Hide();
+            this.Add(connectionFailure);
+
+            revealButton = new Button(ButtonStyles.Reveal)
+            {
+                Size = new Size(22, 13),
+                Position = new Position(702, 138),
+            };
+            revealButton.ClickEvent += (s, e) => TogglePasswordVisibility();
+            this.Add(revealButton);
+
+            cancelButton = new Button(ButtonStyles.Cancel)
+            {
+                Size = new Size(240, 72),
+                Position = new Position(80, 200)
+            };
+            cancelButton.ClickEvent += (s, e) =>
+            {
+                OobeCommon.Utils.Popup.Dismiss();
+            };
+            this.Add(cancelButton);
+
+            okButton = new Button(ButtonStyles.OK)
+            {
+                Size = new Size(240, 72),
+                Position = new Position(488, 200),
+                IsEnabled = false
+            };
+            okButton.ClickEvent += async (s, e) =>
+            {
+                okButton.IsEnabled = false;
+                try
+                {
+                    Tizen.Log.Debug("oobe", $"connecting to wifi {wifiAp.NetworkInformation.Essid} with password {Password}");
+                    wifiAp.SecurityInformation.SetPassphrase(Password);
+                    await wifiAp.ConnectAsync();
+                }
+                catch (Exception ex)
+                {
+                    Tizen.Log.Error("oobe", $"{ex.ToString()}");
+                }
+                finally
+                {
+                    okButton.IsEnabled = true;
+                    if (wifiAp.NetworkInformation.ConnectionState == WiFiConnectionState.Congfiguration
+                        || wifiAp.NetworkInformation.ConnectionState == WiFiConnectionState.Connected)
+                    {
+                        OobeCommon.Utils.Popup.Dismiss();
+                    }
+                    else //there should exist explicit password error path
+                    {
+                        connectionFailure.Show();
+                    }
+                }
+            };
+            this.Add(okButton);
+        }
+
+        private void TogglePasswordVisibility()
+        {
+            passwordEntry.Revealed = !passwordEntry.Revealed;
+            revealButton.IsSelected = !revealButton.IsSelected;
+        }
+    }
+}
index 92708d6ca63e9be6109e0f4153c17242ec6e80c2..cf347300ba0202a3ec19e674b48c948a48ef6e06 100644 (file)
@@ -74,24 +74,23 @@ namespace Oobe.Wifi.Controls.Wifi
             });
             return manualWifi;
         }
+        
+        private static View CreatePasswordPopup(Tizen.Network.WiFi.WiFiAP wifiAp)
+        {
+            var popup = new WifiPasswordPopup(wifiAp);
+            return popup;
+        }
 
-        private static async void OnApTapped(Tizen.Network.WiFi.WiFiAP wifiAp)
+        private static void OnApTapped(Tizen.Network.WiFi.WiFiAP wifiAp)
         {
             if (wifiAp.NetworkInformation.ConnectionState == Tizen.Network.WiFi.WiFiConnectionState.Connected)
             {
                 Tizen.Log.Debug("oobe", $"Already connected to {wifiAp.NetworkInformation.Essid}");
                 return;
             }
-            try
-            {
-                Tizen.Log.Debug("oobe", $"connecting to wifi {wifiAp.NetworkInformation.Essid}");
-                wifiAp.SecurityInformation.SetPassphrase("");//type your passphrase
-                await wifiAp.ConnectAsync();
-            }
-            catch (Exception ex)
-            {
-                Tizen.Log.Error("oobe", $"{ex.ToString()}");
-            }
+            //show center requires correction
+            //OobeCommon.Utils.Popup.ShowCentered(CreatePasswordPopup());
+            OobeCommon.Utils.Popup.Show(CreatePasswordPopup(wifiAp));
         }
 
         private View CreateHeader(int width, int height)
@@ -149,7 +148,7 @@ namespace Oobe.Wifi.Controls.Wifi
         private View CreateListViewPlaceHolder()
         {
             var view = new View();
-            var listView = new ListView(480, 317)//480, 335
+            var listView = new ListView(480, 314)//480, 335
             {
                 Footer = CreateManualWifiView(),
                 Items = ApManager.Views,
index 16f2055366facc42ad458f9f867d4ccd76613eb3..f8ed04173c99b133679a70cf23169204636a7567 100644 (file)
@@ -4,15 +4,21 @@ using Tizen.NUI.Components;
 using Tizen.NUI;
 using Tizen.NUI.BaseComponents;
 using Oobe.Wifi.Controls.Wifi;
+using Tizen.Network.WiFi;
+using System;
+using System.Collections.Generic;
 
 namespace Oobe.Wifi
 {
     public class WifiStep : ProcessStep
     {
-        private WifiView wifiView;
+        private WifiView wifiView = null;
+        private EventHandler<ConnectionStateChangedEventArgs> connectionChanged;
 
         public override View CreateView(IProcessNavigation nav)
         {
+            DisposeView();
+
             var view = new View()
             {
                 Layout = new LinearLayout()
@@ -28,7 +34,7 @@ namespace Oobe.Wifi
                 WidthResizePolicy = ResizePolicyType.FillToParent,
                 Margin = new Extents(0, 0, 20, 8),
                 PixelSize = 48.0f,
-                TextColor = new Color(0, 14.0f / 255.0f, 47.0f / 255.0f, 1.0f),
+                TextColor = new Color(0, 0x14 / 255.0f, 0x47 / 255.0f, 1.0f),
                 FontFamily = "BreezeSans",
                 FontStyle = FontsStyles.Light(),
                 HorizontalAlignment = HorizontalAlignment.Center,
@@ -61,21 +67,34 @@ namespace Oobe.Wifi
             prev.ClickEvent += (s, e) => nav.Previous();
             view.Add(prev);
 
-            var next = new Button(ButtonStyles.Skip)
+            var next = new Button()
             {
                 Position = new Position(888, 10),
                 Size2D = new Size2D(240, 72),
             };
             next.ClickEvent += (s, e) => nav.Next();
             view.Add(next);
+
+            void applyStyle(bool isConnected) => next.ApplyStyle(isConnected ? ButtonStyles.Next : ButtonStyles.Skip);
+            applyStyle(WiFiManager.ConnectionState == WiFiConnectionState.Connected);
+
+            connectionChanged = (s, e) => applyStyle(e.State == WiFiConnectionState.Connected);
+            WiFiManager.ConnectionStateChanged += connectionChanged;
             return view;
         }
 
         public override void OnShutdown()
         {
             base.OnShutdown();
+            DisposeView();
+        }
+
+        private void DisposeView()
+        {
             wifiView?.Dispose();
             wifiView = null;
+            WiFiManager.ConnectionStateChanged -= connectionChanged;
+            connectionChanged = null;
         }
     }
 }
diff --git a/Oobe/OobeWifi/res/08_popup_body.png b/Oobe/OobeWifi/res/08_popup_body.png
new file mode 100644 (file)
index 0000000..864a52a
Binary files /dev/null and b/Oobe/OobeWifi/res/08_popup_body.png differ
diff --git a/Oobe/OobeWifi/res/12_icon_eye_pw_hidden.png b/Oobe/OobeWifi/res/12_icon_eye_pw_hidden.png
new file mode 100644 (file)
index 0000000..31471c7
Binary files /dev/null and b/Oobe/OobeWifi/res/12_icon_eye_pw_hidden.png differ
diff --git a/Oobe/OobeWifi/res/12_icon_eye_pw_hidden.svg b/Oobe/OobeWifi/res/12_icon_eye_pw_hidden.svg
new file mode 100644 (file)
index 0000000..7d36fbb
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="21.496" height="12.372" viewBox="0 0 21.496 12.372"><defs><style>.a{fill:#c3cad2;}</style></defs><path class="a" d="M1037.079,248.059a19.1,19.1,0,0,0-2.71-2.623l.9-.449a.75.75,0,1,0-.67-1.342l-1.6.8a11.642,11.642,0,0,0-6.289-2.1c-5.7,0-10.18,5.482-10.369,5.716l-.379.47.379.471a18.9,18.9,0,0,0,2.552,2.5l-.468.234a.75.75,0,0,0,.336,1.421.738.738,0,0,0,.334-.079l1.147-.573a11.785,11.785,0,0,0,6.468,2.215c5.7,0,10.18-5.482,10.369-5.715l.379-.471Zm-6.227.47a4.1,4.1,0,0,1-.8,2.452h0a4.128,4.128,0,0,1-6.69-.039l7.286-3.644A4.092,4.092,0,0,1,1030.852,248.529Zm-8.131,1.054a4.071,4.071,0,0,1-.153-1.054,4.125,4.125,0,0,1,7.375-2.557Zm8.471-4.467c.074.04.147.08.22.122l-.094.047C1031.278,245.227,1031.235,245.172,1031.192,245.116Zm-13.268,3.412a17.79,17.79,0,0,1,4.308-3.418,5.6,5.6,0,0,0-.886,5.161l-.957.479A19.147,19.147,0,0,1,1017.924,248.528Zm4.073,3.094c.073.11.151.216.231.32-.138-.075-.278-.15-.412-.23Zm9.2.316c.018-.024.039-.044.056-.068a5.605,5.605,0,0,0,.755-5.255l.857-.429a19.105,19.105,0,0,1,2.627,2.343A17.891,17.891,0,0,1,1031.2,251.938Z" transform="translate(-1015.962 -242.343)"/><circle class="a" cx="2.036" cy="2.036" r="2.036" transform="translate(8.848 4.15)"/></svg>
\ No newline at end of file
diff --git a/Oobe/OobeWifi/res/12_icon_eye_pw_visible.png b/Oobe/OobeWifi/res/12_icon_eye_pw_visible.png
new file mode 100644 (file)
index 0000000..d4ceeed
Binary files /dev/null and b/Oobe/OobeWifi/res/12_icon_eye_pw_visible.png differ
diff --git a/Oobe/OobeWifi/res/12_icon_eye_pw_visible.svg b/Oobe/OobeWifi/res/12_icon_eye_pw_visible.svg
new file mode 100644 (file)
index 0000000..d49e634
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="21.495" height="12.372" viewBox="0 0 21.495 12.372"><defs><style>.a{fill:#295bb2;}</style></defs><path class="a" d="M953.688,250.092c-.188-.233-4.671-5.716-10.368-5.716s-10.18,5.483-10.369,5.716l-.379.471.379.47c.189.234,4.672,5.715,10.369,5.715s10.18-5.481,10.368-5.715l.379-.47Zm-7.029,2.923h0a4.143,4.143,0,1,1,.8-2.452A4.1,4.1,0,0,1,946.659,253.015Zm-12.125-2.453a17.79,17.79,0,0,1,4.308-3.419,5.6,5.6,0,0,0,0,6.833A17.865,17.865,0,0,1,934.534,250.562Zm13.276,3.409c.018-.023.039-.044.056-.067a5.622,5.622,0,0,0-.064-6.755,17.846,17.846,0,0,1,4.3,3.414A17.863,17.863,0,0,1,947.81,253.971Z" transform="translate(-932.572 -244.376)"/><circle class="a" cx="2.036" cy="2.036" r="2.036" transform="translate(8.848 4.15)"/></svg>
\ No newline at end of file