mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-04-21 10:53:59 +00:00
OOBE GUI版
This commit is contained in:
@@ -1 +1 @@
|
|||||||
2026-04-04 17:44:58
|
2026-04-04 18:04:06
|
||||||
@@ -1 +1 @@
|
|||||||
c189be5
|
1341f10
|
||||||
@@ -212,8 +212,16 @@ namespace CMLeonOS.Gui
|
|||||||
|
|
||||||
Logger.Logger.Instance.Info("Gui", "Memory management service started");
|
Logger.Logger.Instance.Info("Gui", "Memory management service started");
|
||||||
|
|
||||||
|
if (!Kernel.userSystem.HasUsers)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Starting OOBE...");
|
||||||
|
ProcessManager.AddProcess(windowManager, new ShellComponents.Oobe()).Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Console.WriteLine("Starting lock screen...");
|
Console.WriteLine("Starting lock screen...");
|
||||||
ProcessManager.AddProcess(windowManager, new ShellComponents.Lock()).Start();
|
ProcessManager.AddProcess(windowManager, new ShellComponents.Lock()).Start();
|
||||||
|
}
|
||||||
|
|
||||||
guiRunning = true;
|
guiRunning = true;
|
||||||
|
|
||||||
|
|||||||
265
Gui/ShellComponents/Oobe.cs
Normal file
265
Gui/ShellComponents/Oobe.cs
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
using CMLeonOS;
|
||||||
|
using CMLeonOS.Gui.UILib;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using Sys = Cosmos.System;
|
||||||
|
|
||||||
|
namespace CMLeonOS.Gui.ShellComponents
|
||||||
|
{
|
||||||
|
internal class Oobe : Process
|
||||||
|
{
|
||||||
|
internal Oobe() : base("OOBE", ProcessType.Application) { }
|
||||||
|
|
||||||
|
private readonly WindowManager wm = ProcessManager.GetProcess<WindowManager>();
|
||||||
|
private AppWindow window;
|
||||||
|
private readonly List<Window> stepWindows = new List<Window>();
|
||||||
|
|
||||||
|
private int step = 0;
|
||||||
|
private bool acceptedTerms = false;
|
||||||
|
|
||||||
|
private TextBox usernameBox;
|
||||||
|
private TextBox passwordBox;
|
||||||
|
private TextBox confirmBox;
|
||||||
|
private TextBox hostnameBox;
|
||||||
|
private TextBlock statusText;
|
||||||
|
|
||||||
|
private Button backButton;
|
||||||
|
private Button nextButton;
|
||||||
|
|
||||||
|
private void AddStepWindow(Window w)
|
||||||
|
{
|
||||||
|
stepWindows.Add(w);
|
||||||
|
wm.AddWindow(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearStepWindows()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < stepWindows.Count; i++)
|
||||||
|
{
|
||||||
|
wm.RemoveWindow(stepWindows[i]);
|
||||||
|
}
|
||||||
|
stepWindows.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowStatus(string text, Color color)
|
||||||
|
{
|
||||||
|
statusText.Text = text;
|
||||||
|
statusText.Foreground = color;
|
||||||
|
statusText.Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderStep()
|
||||||
|
{
|
||||||
|
ClearStepWindows();
|
||||||
|
|
||||||
|
window.Clear(UITheme.Surface);
|
||||||
|
window.DrawRectangle(0, 0, window.Width, window.Height, UITheme.SurfaceBorder);
|
||||||
|
window.DrawString("CMLeonOS Setup", UITheme.TextPrimary, 16, 12);
|
||||||
|
window.DrawString($"Step {step + 1}/4", UITheme.TextSecondary, window.Width - 92, 12);
|
||||||
|
|
||||||
|
int contentX = 16;
|
||||||
|
int contentY = 44;
|
||||||
|
int contentW = window.Width - 32;
|
||||||
|
int contentH = window.Height - 108;
|
||||||
|
|
||||||
|
Window content = new Window(this, window, contentX, contentY, contentW, contentH);
|
||||||
|
content.Clear(Color.FromArgb(246, 249, 253));
|
||||||
|
content.DrawRectangle(0, 0, content.Width, content.Height, UITheme.SurfaceBorder);
|
||||||
|
AddStepWindow(content);
|
||||||
|
|
||||||
|
switch (step)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
content.DrawString("Welcome", UITheme.TextPrimary, 12, 12);
|
||||||
|
content.DrawString("Let's configure your first administrator account.", UITheme.TextSecondary, 12, 34);
|
||||||
|
content.DrawString("Press Next to continue.", UITheme.TextSecondary, 12, 56);
|
||||||
|
backButton.Text = "Cancel";
|
||||||
|
nextButton.Text = "Next";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
content.DrawString("Terms and Conditions", UITheme.TextPrimary, 12, 12);
|
||||||
|
content.DrawString("Please read and accept to continue.", UITheme.TextSecondary, 12, 34);
|
||||||
|
|
||||||
|
TextBox terms = new TextBox(content, 12, 58, content.Width - 24, content.Height - 112);
|
||||||
|
terms.ReadOnly = true;
|
||||||
|
terms.MultiLine = true;
|
||||||
|
terms.Text =
|
||||||
|
"1. This system is provided as-is without warranty.\n" +
|
||||||
|
"2. You are responsible for your data and backups.\n" +
|
||||||
|
"3. Unauthorized access attempts may be logged.\n" +
|
||||||
|
"4. Administrators can access local system data.\n" +
|
||||||
|
"5. Data is stored locally on this device.\n" +
|
||||||
|
"6. Updates may change behavior and compatibility.\n" +
|
||||||
|
"7. Use implies acceptance of these terms.";
|
||||||
|
AddStepWindow(terms);
|
||||||
|
|
||||||
|
Switch accept = new Switch(content, 12, content.Height - 44, content.Width - 24, 18);
|
||||||
|
accept.Text = "I accept these terms";
|
||||||
|
accept.Checked = acceptedTerms;
|
||||||
|
accept.CheckBoxChanged = v => acceptedTerms = v;
|
||||||
|
AddStepWindow(accept);
|
||||||
|
|
||||||
|
backButton.Text = "Back";
|
||||||
|
nextButton.Text = "Next";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
content.DrawString("Administrator Account", UITheme.TextPrimary, 12, 12);
|
||||||
|
content.DrawString("Create your first admin user.", UITheme.TextSecondary, 12, 34);
|
||||||
|
|
||||||
|
TextBlock userLabel = new TextBlock(content, 12, 66, 94, 20);
|
||||||
|
userLabel.Text = "Username";
|
||||||
|
userLabel.Foreground = UITheme.TextSecondary;
|
||||||
|
userLabel.Background = Color.FromArgb(246, 249, 253);
|
||||||
|
AddStepWindow(userLabel);
|
||||||
|
|
||||||
|
usernameBox = new TextBox(content, 110, 64, content.Width - 122, 24);
|
||||||
|
AddStepWindow(usernameBox);
|
||||||
|
|
||||||
|
TextBlock passLabel = new TextBlock(content, 12, 100, 94, 20);
|
||||||
|
passLabel.Text = "Password";
|
||||||
|
passLabel.Foreground = UITheme.TextSecondary;
|
||||||
|
passLabel.Background = Color.FromArgb(246, 249, 253);
|
||||||
|
AddStepWindow(passLabel);
|
||||||
|
|
||||||
|
passwordBox = new TextBox(content, 110, 98, content.Width - 122, 24);
|
||||||
|
passwordBox.Shield = true;
|
||||||
|
AddStepWindow(passwordBox);
|
||||||
|
|
||||||
|
TextBlock confirmLabel = new TextBlock(content, 12, 134, 94, 20);
|
||||||
|
confirmLabel.Text = "Confirm";
|
||||||
|
confirmLabel.Foreground = UITheme.TextSecondary;
|
||||||
|
confirmLabel.Background = Color.FromArgb(246, 249, 253);
|
||||||
|
AddStepWindow(confirmLabel);
|
||||||
|
|
||||||
|
confirmBox = new TextBox(content, 110, 132, content.Width - 122, 24);
|
||||||
|
confirmBox.Shield = true;
|
||||||
|
AddStepWindow(confirmBox);
|
||||||
|
|
||||||
|
content.DrawString("Username cannot include: < > : \" | ? * / \\ or space", UITheme.TextSecondary, 12, 168);
|
||||||
|
|
||||||
|
backButton.Text = "Back";
|
||||||
|
nextButton.Text = "Next";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
content.DrawString("Device Name", UITheme.TextPrimary, 12, 12);
|
||||||
|
content.DrawString("Set a hostname for this device.", UITheme.TextSecondary, 12, 34);
|
||||||
|
|
||||||
|
TextBlock hostLabel = new TextBlock(content, 12, 74, 94, 20);
|
||||||
|
hostLabel.Text = "Hostname";
|
||||||
|
hostLabel.Foreground = UITheme.TextSecondary;
|
||||||
|
hostLabel.Background = Color.FromArgb(246, 249, 253);
|
||||||
|
AddStepWindow(hostLabel);
|
||||||
|
|
||||||
|
hostnameBox = new TextBox(content, 110, 72, content.Width - 122, 24);
|
||||||
|
AddStepWindow(hostnameBox);
|
||||||
|
|
||||||
|
content.DrawString("Example: CMLEON-PC", UITheme.TextSecondary, 12, 108);
|
||||||
|
|
||||||
|
backButton.Text = "Back";
|
||||||
|
nextButton.Text = "Finish";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm.Update(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BackClicked(int x, int y)
|
||||||
|
{
|
||||||
|
if (step == 0)
|
||||||
|
{
|
||||||
|
Sys.Power.Reboot();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
step--;
|
||||||
|
ShowStatus(string.Empty, UITheme.TextSecondary);
|
||||||
|
RenderStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NextClicked(int x, int y)
|
||||||
|
{
|
||||||
|
if (step == 1 && !acceptedTerms)
|
||||||
|
{
|
||||||
|
ShowStatus("Please accept terms to continue.", UITheme.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step == 2)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(usernameBox.Text))
|
||||||
|
{
|
||||||
|
ShowStatus("Username cannot be empty.", UITheme.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(passwordBox.Text))
|
||||||
|
{
|
||||||
|
ShowStatus("Password cannot be empty.", UITheme.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (passwordBox.Text != confirmBox.Text)
|
||||||
|
{
|
||||||
|
ShowStatus("Passwords do not match.", UITheme.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step == 3)
|
||||||
|
{
|
||||||
|
string error;
|
||||||
|
if (!Kernel.userSystem.CreateInitialAdminFromOobe(usernameBox.Text, passwordBox.Text, hostnameBox.Text, out error))
|
||||||
|
{
|
||||||
|
ShowStatus("Setup failed: " + error, Color.FromArgb(198, 72, 72));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowStatus("Setup complete. Rebooting...", UITheme.Success);
|
||||||
|
Sys.Power.Reboot();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
step++;
|
||||||
|
ShowStatus(string.Empty, UITheme.TextSecondary);
|
||||||
|
RenderStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
|
||||||
|
int width = 760;
|
||||||
|
int height = 500;
|
||||||
|
window = new AppWindow(this, (int)(wm.ScreenWidth / 2 - width / 2), (int)(wm.ScreenHeight / 2 - height / 2), width, height);
|
||||||
|
window.Title = "CMLeonOS OOBE";
|
||||||
|
window.Icon = AppManager.DefaultAppIcon;
|
||||||
|
window.CanClose = false;
|
||||||
|
window.CanMove = false;
|
||||||
|
window.CanResize = false;
|
||||||
|
wm.AddWindow(window);
|
||||||
|
|
||||||
|
backButton = new Button(window, 16, window.Height - 42, 100, 26);
|
||||||
|
backButton.Text = "Cancel";
|
||||||
|
backButton.OnClick = BackClicked;
|
||||||
|
wm.AddWindow(backButton);
|
||||||
|
|
||||||
|
nextButton = new Button(window, window.Width - 116, window.Height - 42, 100, 26);
|
||||||
|
nextButton.Text = "Next";
|
||||||
|
nextButton.OnClick = NextClicked;
|
||||||
|
wm.AddWindow(nextButton);
|
||||||
|
|
||||||
|
statusText = new TextBlock(window, 126, window.Height - 40, window.Width - 252, 20);
|
||||||
|
statusText.Text = string.Empty;
|
||||||
|
statusText.Background = UITheme.Surface;
|
||||||
|
statusText.Foreground = UITheme.TextSecondary;
|
||||||
|
wm.AddWindow(statusText);
|
||||||
|
|
||||||
|
RenderStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Run()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,10 +96,7 @@ namespace CMLeonOS
|
|||||||
Console.BackgroundColor = ConsoleColor.Black;
|
Console.BackgroundColor = ConsoleColor.Black;
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
bool userDatExists = UserDatExists();
|
string[] options = new[] { "CMLeonOS Shell", "CMLeonOS Desktop", "Reboot", "Shutdown" };
|
||||||
string[] options = userDatExists
|
|
||||||
? new[] { "CMLeonOS Shell", "CMLeonOS Desktop", "Reboot", "Shutdown" }
|
|
||||||
: new[] { "CMLeonOS Shell", "Reboot", "Shutdown" };
|
|
||||||
|
|
||||||
int width = Console.WindowWidth;
|
int width = Console.WindowWidth;
|
||||||
int height = Console.WindowHeight;
|
int height = Console.WindowHeight;
|
||||||
@@ -152,14 +149,13 @@ namespace CMLeonOS
|
|||||||
|
|
||||||
Console.CursorVisible = true;
|
Console.CursorVisible = true;
|
||||||
|
|
||||||
bool userDatExists = UserDatExists();
|
|
||||||
int optionIndex = 0;
|
int optionIndex = 0;
|
||||||
|
|
||||||
if (selIdx == optionIndex++)
|
if (selIdx == optionIndex++)
|
||||||
{
|
{
|
||||||
return BootMenuAction.NormalBoot;
|
return BootMenuAction.NormalBoot;
|
||||||
}
|
}
|
||||||
if (userDatExists && selIdx == optionIndex++)
|
if (selIdx == optionIndex++)
|
||||||
{
|
{
|
||||||
return BootMenuAction.GuiBoot;
|
return BootMenuAction.GuiBoot;
|
||||||
}
|
}
|
||||||
@@ -179,7 +175,7 @@ namespace CMLeonOS
|
|||||||
|
|
||||||
public static BootMenuAction Show()
|
public static BootMenuAction Show()
|
||||||
{
|
{
|
||||||
if (Settings.SettingsManager.SkipToGui && UserDatExists())
|
if (Settings.SettingsManager.SkipToGui)
|
||||||
{
|
{
|
||||||
return BootMenuAction.GuiBoot;
|
return BootMenuAction.GuiBoot;
|
||||||
}
|
}
|
||||||
@@ -235,7 +231,7 @@ namespace CMLeonOS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxOptionIndex = UserDatExists() ? 3 : 2;
|
int maxOptionIndex = 3;
|
||||||
|
|
||||||
if (selIdx < 0)
|
if (selIdx < 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -827,6 +827,69 @@ namespace CMLeonOS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CreateInitialAdminFromOobe(string username, string password, string hostname, out string error)
|
||||||
|
{
|
||||||
|
error = string.Empty;
|
||||||
|
|
||||||
|
username = (username ?? string.Empty).Trim();
|
||||||
|
password = (password ?? string.Empty).Trim();
|
||||||
|
hostname = (hostname ?? string.Empty).Trim();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
|
{
|
||||||
|
error = "Username cannot be empty.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ContainsInvalidChars(username))
|
||||||
|
{
|
||||||
|
error = "Username contains invalid characters.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(password))
|
||||||
|
{
|
||||||
|
error = "Password cannot be empty.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(hostname))
|
||||||
|
{
|
||||||
|
error = "Hostname cannot be empty.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (User user in users)
|
||||||
|
{
|
||||||
|
if (user.Username.Equals(username, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
error = "Username already exists.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
User admin = new User
|
||||||
|
{
|
||||||
|
Username = username,
|
||||||
|
Password = password,
|
||||||
|
IsAdmin = true,
|
||||||
|
Hostname = hostname
|
||||||
|
};
|
||||||
|
|
||||||
|
users.Add(admin);
|
||||||
|
SaveUsers();
|
||||||
|
CreateUserFolder(username);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
error = ex.Message;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool DeleteUser(string username)
|
public bool DeleteUser(string username)
|
||||||
{
|
{
|
||||||
Console.WriteLine("====================================");
|
Console.WriteLine("====================================");
|
||||||
|
|||||||
Reference in New Issue
Block a user