--- /dev/null
+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);
+ }
+ }
+ }
+}
--- /dev/null
+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