Prototype of popup
authorKrzysztof Wieclaw <k.wieclaw@samsung.com>
Thu, 2 Apr 2020 16:40:44 +0000 (18:40 +0200)
committerk.stepaniuk <k.stepaniuk@samsung.com>
Fri, 10 Apr 2020 08:19:07 +0000 (10:19 +0200)
Oobe/Oobe/Managers/ProcessManager.cs
Oobe/OobeWifi/Controls/SequenceLinearLayout.cs
Oobe/OobeWifi/Controls/Wifi/AddNewNetworkPupup.cs [new file with mode: 0644]
Oobe/OobeWifi/Controls/Wifi/WifUISecurityType.cs [new file with mode: 0644]
Oobe/OobeWifi/Controls/Wifi/WifiPasswordPopup.cs
Oobe/OobeWifi/Controls/Wifi/WifiView.cs
Oobe/oobe.diff [new file with mode: 0644]

index df93299..4dc3bd6 100644 (file)
@@ -11,9 +11,9 @@ using System.IO;
 using Oobe.Terms;
 
 namespace Oobe
-{
-    public class ProcessManager : IProcessNavigation
-    {
+ {
+     public class ProcessManager : IProcessNavigation
+     {
         private MainView ui;
         private LinkedList<Lazy<ProcessStep>> steps;
         private LinkedListNode<Lazy<ProcessStep>> current;
@@ -59,7 +59,8 @@ namespace Oobe
         public ProcessManager()
         {
             //TODO consider loading this from xaml, xml or something...
-            steps = new LinkedList<Lazy<ProcessStep>>(new[]{
+            steps = new LinkedList<Lazy<ProcessStep>>(new []{
+                new Lazy<ProcessStep>(() => new WifiStep()),
                 new Lazy<ProcessStep>(() => new LanguageStep()),
                 new Lazy<ProcessStep>(() => new RegionStep()),
                 new Lazy<ProcessStep>(() => new TermsStep()),
@@ -88,15 +89,14 @@ namespace Oobe
         /// </summary>
         public void Next()
         {
-            if (current.Next != null)
+            // do not show pagination on last page
+            if (current.Next == null)
             {
-                current = current.Next;
-                ui.Push(current.Value.Value.CreateView(new NavigationController(this, current.Value.Value)));
-                current.Next?.Value.Value.Initialize();
-                // do not show pagination on last page
-                if (current.Next == null)
-                    ui.PaginationVisible = false;
+                ui.PaginationVisible = false;
             }
+            current = current.Next;
+            ui.Push(current.Value.Value.CreateView(new NavigationController(this, current.Value.Value)));
+            current.Next?.Value.Value.Initialize();
         }
 
         /// <summary>
@@ -108,7 +108,9 @@ namespace Oobe
             {
                 step.Value.Shutdown();
             }
+            #if RELEASE
             SetDone();
+            #endif
             NUIApplication.Current.Exit();
         }
 
index 44ea308..5400925 100644 (file)
@@ -16,6 +16,7 @@ namespace Oobe.Wifi.Controls
                 {
                     LayoutChildren.Add(item);
                     RequestLayout();
+
                 }
             }
         }
diff --git a/Oobe/OobeWifi/Controls/Wifi/AddNewNetworkPupup.cs b/Oobe/OobeWifi/Controls/Wifi/AddNewNetworkPupup.cs
new file mode 100644 (file)
index 0000000..fcc72d2
--- /dev/null
@@ -0,0 +1,357 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Oobe.Common.Styles;
+using Tizen.Network.WiFi;
+
+namespace Oobe.Wifi.Controls.Wifi
+{
+    class AddNewNetworkPupup : View
+    {
+        public event Action OnDismiss;
+        enum NewNetworkViewMode
+        {
+            NoPassword,
+            PasswordOnly,
+            UserPassword
+        };
+        NewNetworkViewMode currentViewMode;
+        TextLabel titleLabel;
+        TextLabel ssidLabel;
+        TextField ssidTextField;
+        TextLabel securityTypeLabel;
+        Button securityTypeButton;
+        TextLabel usernameLabel;
+        TextField usernameTextField;
+        TextLabel passwordLabel;
+        PasswordEntry passwordEntry;
+        Button cancelButton;
+        Button addButton;
+        TextLabel failureLabel;
+        WifUISecurityType currentSecurityType;
+        private string backgroundImagePath = System.IO.Path.Combine(NUIApplication.Current.DirectoryInfo.Resource, "08_popup_body.png");
+
+        static Color largeTextColor => new Color(0.0f, 0x14 / 255.0f, 0x47 / 255.0f, 1.0f);
+        static Color smallTextColor => new Color(0.0f, 0xC / 255.0f, 0x2B / 255.0f, 1.0f);
+        static Size labelSize => new Size(600, 17);
+        static Size textControlSize => new Size(583, 26);
+        int labelFontSize = 14;
+        int textFontSize = 22;
+
+        public AddNewNetworkPupup()
+        {
+            InitializeStaticElements();
+
+            ResetViewTo(WifUISecurityType.None);
+        }
+
+        TextLabel CreateTextLabel(string text, Position2D position = null)
+        {
+            position ??= new Position2D();
+            return new TextLabel
+            {
+                Position = position,
+                Size = labelSize,
+                PixelSize = labelFontSize,
+                Text = text,
+                FontFamily = "BreezeSans",
+                FontStyle = new PropertyMap().AddRegularFontStyle(),
+                TextColor = smallTextColor,
+                HorizontalAlignment = HorizontalAlignment.Begin,
+                VerticalAlignment = VerticalAlignment.Center,
+                BackgroundColor = new Color(0.0f, 1.0f, 0.0f, 1.0f)
+            };
+        }
+
+        TextField CreateTextField(Position2D position = null)
+        {
+            position = position ?? new Position2D();
+            return new TextField
+            {
+                Position = position,
+                Size = textControlSize,
+                PixelSize = textFontSize,
+                FontFamily = "BreezeSans",
+                FontStyle = new PropertyMap().AddRegularFontStyle(),
+                TextColor = largeTextColor,
+                HorizontalAlignment = HorizontalAlignment.Begin,
+                VerticalAlignment = VerticalAlignment.Center,
+                BackgroundColor = new Color(0.0f, 1.0f, 0.0f, 1.0f)
+            };
+        }
+
+        PasswordEntry CreatePasswordEntry(Position2D position = null)
+        {
+            position = position ?? new Position2D();
+            return new PasswordEntry
+            {
+                Position = position,
+                Size = textControlSize,
+                PixelSize = textFontSize,
+                FontFamily = "BreezeSans",
+                FontStyle = new PropertyMap().AddRegularFontStyle(),
+                TextColor = largeTextColor,
+                HorizontalAlignment = HorizontalAlignment.Begin,
+                VerticalAlignment = VerticalAlignment.Center,
+                BackgroundColor = new Color(0.0f, 1.0f, 0.0f, 1.0f)
+            };
+        }
+
+        void InitializeStaticElements()
+        {
+            this.BackgroundImage = backgroundImagePath;
+            titleLabel = new TextLabel
+            {
+                Position = new Position2D(104, 24),
+                Size = new Size(600, 31),
+                PixelSize = 26,
+                Text = "Add network",
+                FontFamily = "BreezeSans",
+                FontStyle = new PropertyMap().AddLightFontStyle(),
+                TextColor = largeTextColor,
+                HorizontalAlignment = HorizontalAlignment.Center,
+                VerticalAlignment = VerticalAlignment.Center
+            };
+            this.Add(titleLabel);
+
+            ssidLabel = CreateTextLabel("Name", new Position2D(104, 80));
+            this.Add(ssidTextField);
+
+            ssidTextField = CreateTextField(new Position2D(121, 97));
+            this.Add(ssidTextField);
+
+            securityTypeLabel = CreateTextLabel("Security type", new Position2D(104, 144));
+            this.Add(securityTypeLabel);
+
+            securityTypeButton = new Button
+            {
+                Size = textControlSize,
+                Position2D = new Position2D(121, 161),
+                Text = currentSecurityType.GetUIName(),
+                BackgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.0f),
+                TextAlignment = HorizontalAlignment.Begin
+            };
+
+            securityTypeButton.ClickEvent += (s, e) => OpenSecurityTypePopup();
+            this.Add(securityTypeButton);
+
+            cancelButton = new Button(ButtonStyles.Cancel)
+            {
+                Size = new Size(240, 72)
+            };
+            cancelButton.ClickEvent += (s, e) => OnDismiss?.Invoke();
+            this.Add(cancelButton);
+
+            addButton = new Button(ButtonStyles.OK)
+            {
+                Size = new Size(240, 72),
+                Text = "Add"
+            };
+            addButton.ClickEvent += async (s, e) => 
+            {
+                var wifiAp = new WiFiAP(ssidTextField.Text, true);
+                if (!(passwordEntry is null))
+                {
+                    wifiAp.SecurityInformation.SetPassphrase(passwordEntry.Password);
+                }
+                wifiAp.SecurityInformation.SecurityType = currentSecurityType.GetApSecurityType();
+                Tizen.Log.Debug("oobe", $"Adding new network: SSID: {ssidTextField.Text}, " +
+                    $"Password: {passwordEntry?.Password ?? "not set"}, " +
+                    $"Security type: {currentSecurityType.GetUIName()}");
+                bool success = await (wifiAp.ConnectAsync() as Task<bool>);
+                if(success)
+                {
+                    OnDismiss?.Invoke();
+                }
+                else
+                {
+                    ShowFailureLabel();
+                }
+            };
+            this.Add(addButton);
+
+            failureLabel = new TextLabel
+            {
+                Size = new Size2D(),
+                PixelSize = 12,
+                FontFamily = "BreezeSans",
+                FontStyle = new PropertyMap().AddRegularFontStyle(),
+                TextColor = new Color(0xAA / 255.0f, 0x18 / 255.0f, 0x18 / 255.0f, 1.0f),
+                HorizontalAlignment = HorizontalAlignment.Begin,
+                VerticalAlignment = VerticalAlignment.Center
+            };
+            failureLabel.Hide();
+            this.Add(failureLabel);
+        }
+
+        void OpenSecurityTypePopup()
+        {
+            //Temporary solution for no popup stack
+            switch (currentSecurityType)
+            {
+                case WifUISecurityType.None:
+                    ResetViewTo(WifUISecurityType.EAP);
+                    break;
+                case WifUISecurityType.EAP:
+                    ResetViewTo(WifUISecurityType.WEP);
+                    break;
+                case WifUISecurityType.WEP:
+                    ResetViewTo(WifUISecurityType.WPAPSK);
+                    break;
+                case WifUISecurityType.WPAPSK:
+                    ResetViewTo(WifUISecurityType.WPA2PSK);
+                    break;
+                case WifUISecurityType.WPA2PSK:
+                    ResetViewTo(WifUISecurityType.None);
+                    break;
+            }
+        }
+
+        void ResetViewToNoPassword()
+        {
+            Size = new Size(808, 322);
+            Position = new Position2D(236, 118);
+
+            addButton.Position = new Position2D(488, ((int)Size.Height) - 96);
+            cancelButton.Position = new Position2D(80, ((int)Size.Height) - 96);
+
+            if (!(usernameLabel is null))
+            {
+                usernameLabel.Dispose();
+            }
+
+            if (!(usernameTextField is null))
+            {
+                usernameTextField.Dispose();
+            }
+
+            if (!(passwordLabel is null))
+            {
+                passwordLabel.Dispose();
+            }
+
+            if (!(passwordEntry is null))
+            {
+                passwordEntry.Dispose();
+            }
+
+            currentViewMode = NewNetworkViewMode.NoPassword;
+        }
+
+        void ResetViewToPasswordOnly()
+        {
+            Size = new Size2D(808, 382);
+            Position = new Position2D(236, 59);
+
+            addButton.Position = new Position2D(488, ((int)Size.Height) - 96);
+            cancelButton.Position = new Position2D(80, ((int)Size.Height) - 96);
+
+            if (!(usernameLabel is null))
+            {
+                usernameLabel.Dispose();
+            }
+
+            if (!(usernameTextField is null))
+            {
+                usernameTextField.Dispose();
+            }
+
+            if (passwordLabel is null)
+            {
+                passwordLabel = CreateTextLabel("Security key");
+                this.Add(passwordLabel);
+            }
+
+            if (passwordEntry is null)
+            {
+                passwordEntry = CreatePasswordEntry();
+                this.Add(passwordEntry);
+            }
+
+            passwordLabel.Position = new Position2D(104, 208);
+            passwordEntry.Position = new Position2D(121, 225);
+
+            currentViewMode = NewNetworkViewMode.PasswordOnly;
+        }
+
+        void ResetViewToUserPassword()
+        {
+            Size = new Size2D(808, 440);
+            Position = new Position2D(236, 0);
+
+            addButton.Position = new Position2D(488, ((int)Size.Height) - 96);
+            cancelButton.Position = new Position2D(80, ((int)Size.Height) - 96);
+
+            if (usernameLabel is null)
+            {
+                usernameLabel = CreateTextLabel("Username");
+                this.Add(usernameLabel);
+            }
+
+            if (usernameTextField is null)
+            {
+                usernameTextField = CreateTextField();
+                this.Add(usernameTextField);
+            }
+
+            if (passwordLabel is null)
+            {
+                passwordLabel = CreateTextLabel("Security key");
+                this.Add(passwordLabel);
+            }
+
+            if (passwordEntry is null)
+            {
+                passwordEntry = CreatePasswordEntry();
+                this.Add(passwordEntry);
+            }
+
+            usernameLabel.Position2D = new Position2D(104, 208);
+            usernameTextField.Position2D = new Position2D(121, 225);
+            passwordLabel.Position2D = new Position2D(104, 272);
+            passwordEntry.Position2D = new Position2D(121, 289);
+
+            currentViewMode = NewNetworkViewMode.UserPassword;
+        }
+
+        void ResetViewTo(WifUISecurityType securityType)
+        {
+            failureLabel.Hide();
+            currentSecurityType = securityType;
+            switch (securityType)
+            {
+                case WifUISecurityType.None:
+                    ResetViewToNoPassword();
+                    break;
+                case WifUISecurityType.EAP:
+                case WifUISecurityType.WEP:
+                case WifUISecurityType.WPAPSK:
+                case WifUISecurityType.WPA2PSK:
+                    ResetViewToPasswordOnly();
+                    break;
+                default:
+                    throw new NotImplementedException($"UI for Security type {securityType.GetUIName()} was not implemented");
+            }
+        }
+
+        void ShowFailureLabel()
+        {
+            failureLabel.Show();
+            if(currentViewMode == NewNetworkViewMode.NoPassword)
+            {
+                failureLabel.Text = "Invalid name";
+                failureLabel.Position2D = ssidTextField.Position2D + new Position2D(0, (int)ssidTextField.Size.Height);
+            }
+            else
+            {
+                failureLabel.Text = "Invalid password";
+                failureLabel.Position2D = passwordEntry.Position2D + new Position2D(0, (int)passwordEntry.Size.Height);
+            }
+        }
+    }
+}
diff --git a/Oobe/OobeWifi/Controls/Wifi/WifUISecurityType.cs b/Oobe/OobeWifi/Controls/Wifi/WifUISecurityType.cs
new file mode 100644 (file)
index 0000000..686e29e
--- /dev/null
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tizen.Network.Connection;
+
+namespace Oobe.Wifi.Controls.Wifi
+{
+    enum WifUISecurityType
+    {
+        None,
+        EAP,
+        WEP,
+        WPAPSK,
+        WPA2PSK
+    }
+
+    static class WifUISecurityTypeExtensions
+    {
+        public static string GetUIName(this WifUISecurityType type)
+        {
+            switch (type)
+            {
+                case WifUISecurityType.None: return "Open";
+                case WifUISecurityType.EAP: return "EAP";
+                case WifUISecurityType.WEP: return "WEP";
+                case WifUISecurityType.WPAPSK: return "WPA PSK";
+                case WifUISecurityType.WPA2PSK: return "WPA2 PSK";
+                default:
+                    throw new ArgumentException("Unknown security type");
+            }
+        }
+
+        public static WiFiSecurityType GetApSecurityType(this WifUISecurityType type)
+        {
+            switch (type)
+            {
+                case WifUISecurityType.None: return WiFiSecurityType.None;
+                case WifUISecurityType.EAP: return WiFiSecurityType.Eap;
+                case WifUISecurityType.WEP: return WiFiSecurityType.Wep;
+                case WifUISecurityType.WPAPSK: return WiFiSecurityType.WpaPsk;
+                case WifUISecurityType.WPA2PSK: return WiFiSecurityType.Wpa2Psk;
+                default:
+                    throw new ArgumentException("Unknown security type");
+            }
+        }
+    }
+}
index 0a0e902..08646c7 100644 (file)
@@ -3,7 +3,6 @@ using System.Threading.Tasks;
 using Tizen.NUI;
 using Tizen.NUI.BaseComponents;
 using Tizen.NUI.Components;
-using OobeCommon;
 using Tizen.Network.WiFi;
 using Oobe.Common.Styles;
 using OobeWifi.Controls.Wifi;
index 3536f04..fbde20b 100644 (file)
@@ -60,11 +60,14 @@ namespace Oobe.Wifi.Controls.Wifi
                 Layout = new AbsoluteLayout(),
             };
 
-            manualWifi.Add(new Button(ButtonStyles.AddNetwork)
+            var addNewButton = new Button(ButtonStyles.AddNetwork)
             {
                 Position = new Position(29, 20),
                 Size = new Size(42, 42),
-            });
+            };
+
+            addNewButton.ClickEvent += (s, e) => ShowAddNetworkPopup();
+            manualWifi.Add(addNewButton);
 
             manualWifi.Add(new TextLabel()
             {
@@ -77,8 +80,16 @@ namespace Oobe.Wifi.Controls.Wifi
             });
             return manualWifi;
         }
+        
+        private static async void ShowAddNetworkPopup()
+        {
+            var view = new AddNewNetworkPupup();
+            var popup = new Common.Utils.Popup(view);
+            view.OnDismiss += popup.Dismiss;
+            popup.Show();
+        }
 
-        private static void ShowPasswordPopup(Tizen.Network.WiFi.WiFiAP wifiAp)
+        private static async void ShowPasswordPopup(Tizen.Network.WiFi.WiFiAP wifiAp)
         {
             var view = new WifiPasswordPopup(wifiAp);
             var popup = new Common.Utils.Popup(view);
diff --git a/Oobe/oobe.diff b/Oobe/oobe.diff
new file mode 100644 (file)
index 0000000..fcf7bfd
--- /dev/null
@@ -0,0 +1,443 @@
+commit c3e9d3231beda8f23cff851b8c4e8e073428c9d8
+Author:     Krzysztof Wieclaw <k.wieclaw@samsung.com>
+AuthorDate: Mon Mar 30 20:34:13 2020 +0200
+Commit:     Krzysztof Wieclaw <k.wieclaw@samsung.com>
+CommitDate: Mon Mar 30 20:34:13 2020 +0200
+
+    Add password characters and reveal button
+
+diff --git a/Oobe/OobeCommon/Styles/ButtonStyles.cs b/Oobe/OobeCommon/Styles/ButtonStyles.cs
+index fb27803..23e27aa 100644
+--- a/Oobe/OobeCommon/Styles/ButtonStyles.cs
++++ b/Oobe/OobeCommon/Styles/ButtonStyles.cs
+@@ -7,7 +7,13 @@ 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();
++        private static ButtonStyle GetPreviousButtonStyle() => new ButtonStyle
+         {
+             Text = new TextLabelStyle
+             {
+@@ -26,9 +32,28 @@ namespace Oobe.Common.Styles
+             },
+             Size2D = new Size2D(240, 72),
+         };
+-        public static ButtonStyle Skip = GetSkipButtonStyle();
+-        public static ButtonStyle OK = GetOKButtonStyle();
+-        public static ButtonStyle Scan = new ButtonStyle
++
++        private static ButtonStyle GetOKButtonStyle()
++        {
++            var style = GetNextButtonStyle();
++            style.Text.Text = "OK";
++            return style;
++        }
++
++        private static ButtonStyle GetSkipButtonStyle()
++        {
++            var style = GetNextButtonStyle();
++            style.Text.Text = "SKIP";
++            return style;
++        }
++
++        private static ButtonStyle GetCancelButtonStyle()
++        {
++            var style = GetNextButtonStyle();
++            style.Text.Text = "CANCEL";
++            return style;
++        }
++        private static ButtonStyle GetScanButtonStyle() => new ButtonStyle
+         {
+             BackgroundImage = new Selector<string>
+             {
+@@ -38,7 +63,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>
+             {
+@@ -49,7 +74,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>
+             {
+@@ -59,20 +85,6 @@ 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();
+-            style.Text.Text = "SKIP";
+-            return style;
+-        }
+-
+         private static ButtonStyle GetNextButtonStyle() => new ButtonStyle
+         {
+             BackgroundImage = new Selector<string>
+diff --git a/Oobe/OobeCommon/Utils/Popup.cs b/Oobe/OobeCommon/Utils/Popup.cs
+index e80457f..45c278f 100644
+--- a/Oobe/OobeCommon/Utils/Popup.cs
++++ b/Oobe/OobeCommon/Utils/Popup.cs
+@@ -41,7 +41,7 @@ namespace OobeCommon.Utils
+             Window.Instance.AddLayer(layer);
+         }
+-        private static void Dismiss()
++        public static void Dismiss()
+         {
+             if (layer != null)
+             {
+diff --git a/Oobe/OobeWifi/Controls/Wifi/PasswordEntry.cs b/Oobe/OobeWifi/Controls/Wifi/PasswordEntry.cs
+new file mode 100644
+index 0000000..44404a1
+--- /dev/null
++++ b/Oobe/OobeWifi/Controls/Wifi/PasswordEntry.cs
+@@ -0,0 +1,119 @@
++using System;
++using System.Collections.Generic;
++using System.Linq;
++using System.Text;
++using System.Threading.Tasks;
++using Tizen;
++using Tizen.NUI;
++using Tizen.NUI.BaseComponents;
++
++namespace Oobe.Wifi.Controls.Wifi
++{
++    class PasswordEntry : Tizen.NUI.BaseComponents.TextField
++    {
++        private string previousText;
++        private string password;
++        public string Password => password;
++        private char passwordChar;
++        private bool revealed = false;
++        private bool callbackStop = false;
++        public bool Revealed { 
++            get => revealed; 
++            set {
++                revealed = value;
++                if (revealed)
++                    revealPassword();
++                else
++                    hidePassword();
++            } 
++        }
++        
++        public PasswordEntry(char passwordChar)
++        {
++            this.passwordChar = passwordChar;
++            previousText = "";
++            password = "";
++            this.TextChanged += PasswordEntryTextChanged;
++        }
++
++        private void PasswordEntryTextChanged(object sender, TextChangedEventArgs e)
++        {
++            if(callbackStop)
++            {
++                return;
++            }
++
++            if(revealed)
++            {
++                password = e.TextField.Text;
++                previousText = e.TextField.Text;
++                return;
++            }
++
++            string newText = e.TextField.Text;
++            Tizen.Log.Debug("oobe", $"{nameof(newText)} = {newText}");
++
++            if(this.previousText.Length > newText.Length) //If text was removed
++            {
++                //Temporary solution - trim charachters to fit new length
++                password = password.Substring(0, newText.Length);
++                //It assumes that deleted chars were the last ones (which can be false)
++            }
++            else
++            {
++                try
++                {
++                    Tizen.Log.Debug("oobe", $"Character entered");
++                    (char c, int i) = newText.Select((c, i) => (c, i)).First(x => x.c != passwordChar);
++                    Tizen.Log.Debug("oobe", $"Charachter {c} entered on position {i}");
++                    password = password.Substring(0, i) + c + (i < password.Length? password.Substring(i) : "");
++                }
++                catch(InvalidOperationException)
++                {
++                    Tizen.Log.Debug("oobe", $"Password character {passwordChar} entered");
++
++                    //User entered passwordchar directly - and we don't know were, so we assume that was on the last position
++                    password += passwordChar;
++                }
++                catch(Exception)
++                {
++                    Tizen.Log.Debug("oobe", "Failed to add charcter to password");
++                    throw;
++                }
++            }
++            
++            previousText = new String(passwordChar, password.Length);
++            e.TextField.Text = previousText;
++            Tizen.Log.Debug("oobe", $"{nameof(previousText)} = {previousText}");
++            Tizen.Log.Debug("oobe", $"{nameof(password)} = {password}");
++        }
++
++        public void Clear()
++        {
++            callbackStop = true;
++            password = "";
++            previousText = "";
++            Text = "";
++            callbackStop = false;
++        }
++
++        private void revealPassword()
++        {
++            callbackStop = true;
++            Tizen.Log.Debug("oobe", "Revealing password");
++            previousText = password;
++            Text = password;
++            Tizen.Log.Debug("oobe", "Password revealed");
++            callbackStop = false;
++        }
++        private void hidePassword()
++        {
++            callbackStop = true;
++            Tizen.Log.Debug("oobe", "Hiding password");
++            previousText = new String(passwordChar, password.Length);
++            Text = previousText;
++            Tizen.Log.Debug("oobe", "Password hidden");
++            callbackStop = false;
++        }
++    }
++}
+diff --git a/Oobe/OobeWifi/Controls/Wifi/WifiPasswordPopup.cs b/Oobe/OobeWifi/Controls/Wifi/WifiPasswordPopup.cs
+new file mode 100644
+index 0000000..240dfe4
+--- /dev/null
++++ b/Oobe/OobeWifi/Controls/Wifi/WifiPasswordPopup.cs
+@@ -0,0 +1,136 @@
++using Oobe.Common.Styles;
++using System;
++using System.Threading.Tasks;
++using Tizen.NUI;
++using Tizen.NUI.BaseComponents;
++using Tizen.NUI.Components;
++using OobeCommon;
++
++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 string hiddenRevealButtonBackgroundImagePath = System.IO.Path.Combine(NUIApplication.Current.DirectoryInfo.Resource, "12_icon_eye_pw_hidden.svg");
++        private string visibleRevealButtonBackgroundImagePath = System.IO.Path.Combine(NUIApplication.Current.DirectoryInfo.Resource, "12_icon_eye_pw_visible.svg");
++        public string Password => passwordEntry.Password;
++        private Tizen.Network.WiFi.WiFiAP wifiAp;
++        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(104, 138),
++                MaxLength = maxPasswordLength
++            };
++            this.Add(passwordEntry);
++            passwordEntry.TextChanged += (s, e) =>
++            {
++                okButton.IsEnabled = Password.Length >= minPasswordLength;
++            };
++
++            var titleLabel = new TextLabel
++            {
++                Size = new Size(600, 35),
++                Position = new Position(104, 20),
++                Text = "Enter password",
++                HorizontalAlignment = HorizontalAlignment.Center,
++                VerticalAlignment = VerticalAlignment.Center,
++            };
++            this.Add(titleLabel);
++
++            var subtitleLabel = new TextLabel
++            {
++                Size = new Size(600, 22),
++                Position = new Position(104, 71),
++                Text = $"Enter password to join \"{wifiAp.NetworkInformation.Essid}\"",
++                HorizontalAlignment = HorizontalAlignment.Center,
++                VerticalAlignment = VerticalAlignment.Center
++                
++            };
++            this.Add(subtitleLabel);
++
++            connectionFailure = new TextLabel
++            {
++                Size = new Size(216, 18),
++                Position = new Position(104, 162),
++                Text = "",
++            };
++
++            revealButton = new Button()
++            {
++                Size = new Size(32, 32),
++                Position = new Position(696, 128),
++                BackgroundImage = hiddenRevealButtonBackgroundImagePath,
++                Text = ""
++            };
++            revealButton.ClickEvent += (s, e) =>
++            {
++                if (passwordEntry.Revealed)
++                    hidePassword();
++                else
++                    revealPassword();
++            };
++            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) =>
++            {
++                try
++                {
++                    Tizen.Log.Debug("oobe", $"connecting to wifi {wifiAp.NetworkInformation.Essid} with password {Password}");
++                    wifiAp.SecurityInformation.SetPassphrase(Password);
++                    await wifiAp.ConnectAsync();
++                    if (wifiAp.NetworkInformation.ConnectionState == Tizen.Network.WiFi.WiFiConnectionState.Connected)
++                        OobeCommon.Utils.Popup.Dismiss();
++                    else
++                        connectionFailure.Text = "Invalid password!";
++                }
++                catch (Exception ex)
++                {
++                    Tizen.Log.Error("oobe", $"{ex.ToString()}");
++                }
++            };
++            this.Add(okButton);
++        }
++
++        private void revealPassword()
++        {
++            passwordEntry.Revealed = true;
++            revealButton.BackgroundImage = visibleRevealButtonBackgroundImagePath;
++        }
++        private void hidePassword()
++        {
++            passwordEntry.Revealed = false;
++            revealButton.BackgroundImage = hiddenRevealButtonBackgroundImagePath;
++        }
++    }
++}
+diff --git a/Oobe/OobeWifi/Controls/Wifi/WifiView.cs b/Oobe/OobeWifi/Controls/Wifi/WifiView.cs
+index 6bb8d24..7fef9a1 100644
+--- a/Oobe/OobeWifi/Controls/Wifi/WifiView.cs
++++ b/Oobe/OobeWifi/Controls/Wifi/WifiView.cs
+@@ -77,41 +77,8 @@ namespace Oobe.Wifi.Controls.Wifi
+         
+         private static View CreatePasswordPopup(Tizen.Network.WiFi.WiFiAP wifiAp)
+         {
+-            var view = new View()
+-            {
+-                BackgroundImage = System.IO.Path.Combine(NUIApplication.Current.DirectoryInfo.Resource, "08_popup_body.png"),
+-                Size = new Size(808, 304),
+-            };
+-
+-            var text = new Tizen.NUI.BaseComponents.TextField()
+-            {
+-                Size = new Size(584, 22),
+-                Position = new Position(104, 138),
+-            };
+-            view.Add(text);
+-
+-            var ok = new Button(ButtonStyles.OK)
+-            {
+-                Size = new Size(240, 72),
+-                Position = new Position(488, 200),
+-            };
+-            ok.ClickEvent += async (s, e) =>
+-            {
+-                try
+-                {
+-                    Tizen.Log.Debug("oobe", $"connecting to wifi {wifiAp.NetworkInformation.Essid} with password {text.Text}");
+-                    wifiAp.SecurityInformation.SetPassphrase(text.Text);
+-                    await wifiAp.ConnectAsync();
+-                }
+-                catch (Exception ex)
+-                {
+-                    Tizen.Log.Error("oobe", $"{ex.ToString()}");
+-                }
+-                //if connected OobeCommon.Utils.Popup.Dismiss();
+-                //if not connected show red error
+-            };
+-            view.Add(ok);
+-            return view;
++            var popup = new WifiPasswordPopup(wifiAp);
++            return popup;
+         }
+         private static void OnApTapped(Tizen.Network.WiFi.WiFiAP wifiAp)
+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
+index 0000000..7d36fbb
+--- /dev/null
++++ b/Oobe/OobeWifi/res/12_icon_eye_pw_hidden.svg
+@@ -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.svg b/Oobe/OobeWifi/res/12_icon_eye_pw_visible.svg
+new file mode 100644
+index 0000000..d49e634
+--- /dev/null
++++ b/Oobe/OobeWifi/res/12_icon_eye_pw_visible.svg
+@@ -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