Imports System.Drawing.Drawing2D Imports System.Threading Public Class FrmLogin Dim api As New ApiInterface Private loginTimer As System.Windows.Forms.Timer Private isLoggingIn As Boolean = False Private lastServerResponse As String = "" Private Sub FrmLogin_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' تنظیم متن توکن از تنظیمات TokenTextBox.Text = My.Settings.token.ToString ' تنظیم آدرس API از تنظیمات ApiUrlTextBox.Text = My.Settings.apiUrl.ToString ' تنظیم فوکوس روی فیلد توکن TokenTextBox.Focus() TokenTextBox.SelectAll() ' تنظیم انیمیشن‌های دکمه‌ها SetupButtonAnimations() ' اضافه کردن event handlers AddHandler SettingsButton.Click, AddressOf SettingsButton_Click AddHandler ApiUrlTextBox.TextChanged, AddressOf ApiUrlTextBox_TextChanged End Sub Private Sub SetupButtonAnimations() ' تنظیم افکت hover برای دکمه ورود AddHandler LoginButton.MouseEnter, Sub(sender, e) LoginButton.BackColor = Color.FromArgb(0, 100, 200) End Sub AddHandler LoginButton.MouseLeave, Sub(sender, e) LoginButton.BackColor = Color.FromArgb(0, 120, 215) End Sub ' تنظیم افکت hover برای دکمه خروج AddHandler ExitButton.MouseEnter, Sub(sender, e) ExitButton.BackColor = Color.FromArgb(120, 120, 120) End Sub AddHandler ExitButton.MouseLeave, Sub(sender, e) ExitButton.BackColor = Color.FromArgb(100, 100, 100) End Sub End Sub Private Sub LoginButton_Click(sender As Object, e As EventArgs) Handles LoginButton.Click If isLoggingIn Then Return ' بررسی خالی نبودن فیلد توکن If String.IsNullOrWhiteSpace(TokenTextBox.Text) Then ShowStatus("لطفاً توکن خود را وارد کنید", True) TokenTextBox.Focus() Return End If ' شروع فرآیند ورود StartLoginProcess() End Sub Private Sub StartLoginProcess() isLoggingIn = True ' نمایش پنل بارگذاری LoadingPanel.Visible = True LoginPanel.Enabled = False ' تنظیم متن بارگذاری LoadingLabel.Text = "در حال بررسی توکن..." ' شروع تایمر برای شبیه‌سازی بارگذاری loginTimer = New System.Windows.Forms.Timer() loginTimer.Interval = 2000 ' 2 ثانیه AddHandler loginTimer.Tick, AddressOf LoginTimer_Tick loginTimer.Start() ' شروع فرآیند ورود در thread جداگانه Dim loginThread As New Thread(AddressOf PerformLogin) loginThread.IsBackground = True loginThread.Start() End Sub Private Sub LoginTimer_Tick(sender As Object, e As EventArgs) loginTimer.Stop() loginTimer.Dispose() ' تغییر متن بارگذاری LoadingLabel.Text = "در حال اتصال به سرور..." End Sub Private Sub PerformLogin() Try ' ذخیره توکن در تنظیمات My.Settings.token = TokenTextBox.Text.Trim ' فراخوانی API و دریافت پاسخ خام سرور Dim serverResponse As String = api.loginWithResponse(TokenTextBox.Text.Trim) lastServerResponse = serverResponse ' ذخیره آخرین پاسخ سرور ' بازگشت به UI thread Me.Invoke(Sub() ' نمایش پاسخ سرور ShowServerResponse(serverResponse) ' بررسی نتیجه ورود Dim serializer As New System.Web.Script.Serialization.JavaScriptSerializer() Try Dim result As Dictionary(Of String, Object) = serializer.Deserialize(Of Dictionary(Of String, Object))(serverResponse) If result.Count = 0 Then ' ورود ناموفق LoginFailed(serverResponse) Else ' ورود موفق LoginSuccessful(serverResponse) End If Catch ' اگر JSON نباشد، احتمالاً خطا است LoginFailed(serverResponse) End Try End Sub) Catch ex As Exception ' خطا در فرآیند ورود Me.Invoke(Sub() LoginFailed("خطا در اتصال به سرور: " & ex.Message) ShowStatus("خطا در اتصال به سرور: " & ex.Message, True) End Sub) End Try End Sub Private Sub LoginSuccessful(serverResponse As String) ' پنهان کردن پنل بارگذاری LoadingPanel.Visible = False LoginPanel.Enabled = True ' نمایش پیام موفقیت ShowStatus("ورود موفق! در حال انتقال...", False) ' فعال کردن منو و تایمر اصلی My.Forms.Form1.MenuStrip1.Enabled = True My.Forms.Form1.Timer1.Enabled = True Form1.isLogin = True ' بستن فرم ورود بعد از 1 ثانیه Dim closeTimer As New System.Windows.Forms.Timer() closeTimer.Interval = 1000 AddHandler closeTimer.Tick, Sub(sender, e) closeTimer.Stop() closeTimer.Dispose() Me.Close() End Sub closeTimer.Start() End Sub Private Sub LoginFailed(serverResponse As String) ' پنهان کردن پنل بارگذاری LoadingPanel.Visible = False LoginPanel.Enabled = True ' پاک کردن فیلد توکن TokenTextBox.Text = "" TokenTextBox.Focus() ' نمایش پیام خطا ShowStatus("توکن وارد شده صحیح نیست", True) ' نمایش MessageBox با پاسخ سرور Dim message As String = "توکن وارد شده صحیح نیست" & vbCrLf & vbCrLf & "پاسخ سرور:" & vbCrLf & serverResponse MessageBox.Show(message, "خطا در ورود", MessageBoxButtons.OK, MessageBoxIcon.Warning) ' نمایش پاسخ سرور در فرم جداگانه برای خوانایی بهتر ShowServerResponseDialog(serverResponse) isLoggingIn = False End Sub Private Sub ShowServerResponseDialog(serverResponse As String) ' ایجاد فرم برای نمایش پاسخ سرور Dim responseForm As New Form() responseForm.Text = "پاسخ سرور" responseForm.Size = New Size(600, 400) responseForm.StartPosition = FormStartPosition.CenterParent responseForm.FormBorderStyle = FormBorderStyle.FixedDialog responseForm.MaximizeBox = False responseForm.MinimizeBox = False ' ایجاد TextBox برای نمایش پاسخ Dim responseTextBox As New TextBox() responseTextBox.Multiline = True responseTextBox.ScrollBars = ScrollBars.Vertical responseTextBox.ReadOnly = True responseTextBox.Font = New Font("Consolas", 9) responseTextBox.Text = serverResponse responseTextBox.Dock = DockStyle.Fill ' ایجاد دکمه بستن Dim closeButton As New Button() closeButton.Text = "بستن" closeButton.Dock = DockStyle.Bottom closeButton.Height = 30 AddHandler closeButton.Click, Sub(sender, e) responseForm.Close() ' اضافه کردن کنترل‌ها به فرم responseForm.Controls.Add(responseTextBox) responseForm.Controls.Add(closeButton) ' نمایش فرم responseForm.ShowDialog(Me) End Sub Private Sub ShowServerResponse(serverResponse As String) ' نمایش پاسخ سرور در StatusLabel StatusLabel.Text = "پاسخ سرور: " & serverResponse StatusLabel.ForeColor = Color.FromArgb(255, 255, 100) ' رنگ زرد برای پاسخ سرور ' پاک کردن پیام بعد از 5 ثانیه (بیشتر از معمول) Dim clearTimer As New System.Windows.Forms.Timer() clearTimer.Interval = 5000 AddHandler clearTimer.Tick, Sub(sender, e) StatusLabel.Text = "" clearTimer.Stop() clearTimer.Dispose() End Sub clearTimer.Start() End Sub Private Sub ShowStatus(message As String, isError As Boolean) StatusLabel.Text = message If isError Then StatusLabel.ForeColor = Color.FromArgb(255, 100, 100) Else StatusLabel.ForeColor = Color.FromArgb(100, 255, 100) End If ' پاک کردن پیام بعد از 3 ثانیه Dim clearTimer As New System.Windows.Forms.Timer() clearTimer.Interval = 3000 AddHandler clearTimer.Tick, Sub(sender, e) StatusLabel.Text = "" clearTimer.Stop() clearTimer.Dispose() End Sub clearTimer.Start() End Sub Private Sub ExitButton_Click(sender As Object, e As EventArgs) Handles ExitButton.Click Application.Exit() End Sub Private Sub TokenTextBox_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TokenTextBox.KeyPress ' اجازه ورود فقط کاراکترهای مجاز If e.KeyChar = ChrW(Keys.Enter) Then LoginButton_Click(sender, e) End If End Sub Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean ' کلید میانبر Ctrl+R برای نمایش آخرین پاسخ سرور If keyData = (Keys.Control Or Keys.R) Then ShowLastServerResponse() Return True End If ' کلید میانبر Ctrl+S برای باز کردن تنظیمات API If keyData = (Keys.Control Or Keys.S) Then ShowApiUrlSettings() Return True End If Return MyBase.ProcessCmdKey(msg, keyData) End Function ' متد برای نمایش آخرین پاسخ سرور (می‌تواند از خارج فراخوانی شود) Public Sub ShowLastServerResponse() If Not String.IsNullOrEmpty(lastServerResponse) Then ShowServerResponseDialog(lastServerResponse) Else MessageBox.Show("هنوز هیچ پاسخی از سرور دریافت نشده است.", "اطلاع", MessageBoxButtons.OK, MessageBoxIcon.Information) End If End Sub ' متدهای مربوط به تنظیمات API URL Private Sub SettingsButton_Click(sender As Object, e As EventArgs) ShowApiUrlSettings() End Sub Private Sub ApiUrlTextBox_TextChanged(sender As Object, e As EventArgs) ' ذخیره تغییرات در تنظیمات My.Settings.apiUrl = ApiUrlTextBox.Text.Trim My.Settings.Save() End Sub Private Sub ShowApiUrlSettings() Dim settingsForm As New Form() settingsForm.Text = "تنظیمات API" settingsForm.Size = New Size(500, 350) settingsForm.StartPosition = FormStartPosition.CenterParent settingsForm.FormBorderStyle = FormBorderStyle.FixedDialog settingsForm.MaximizeBox = False settingsForm.MinimizeBox = False ' ایجاد کنترل‌ها Dim titleLabel As New Label() titleLabel.Text = "تنظیمات آدرس سرور API" titleLabel.Font = New Font("Segoe UI", 14, FontStyle.Bold) titleLabel.Location = New Point(20, 20) titleLabel.Size = New Size(450, 30) titleLabel.TextAlign = ContentAlignment.MiddleCenter Dim urlLabel As New Label() urlLabel.Text = "آدرس سرور API:" urlLabel.Font = New Font("Segoe UI", 10) urlLabel.Location = New Point(20, 70) urlLabel.Size = New Size(450, 25) Dim urlTextBox As New TextBox() urlTextBox.Text = My.Settings.apiUrl.ToString urlTextBox.Font = New Font("Consolas", 10) urlTextBox.Location = New Point(20, 100) urlTextBox.Size = New Size(450, 25) urlTextBox.Multiline = False Dim infoLabel As New Label() infoLabel.Text = "مثال: https://hesabix.ir" & vbCrLf & "یا: http://localhost:8080" infoLabel.Font = New Font("Segoe UI", 9) infoLabel.ForeColor = Color.Gray infoLabel.Location = New Point(20, 135) infoLabel.Size = New Size(450, 40) Dim presetLabel As New Label() presetLabel.Text = "URL های پیش‌فرض:" presetLabel.Font = New Font("Segoe UI", 9, FontStyle.Bold) presetLabel.Location = New Point(20, 180) presetLabel.Size = New Size(100, 20) Dim presetComboBox As New ComboBox() presetComboBox.DropDownStyle = ComboBoxStyle.DropDownList presetComboBox.Items.AddRange({"https://hesabix.ir", "https://ac.hunamick.com", "https://app.hesabix.ir", "http://localhost:8080", "http://127.0.0.1:8080", "https://rc.hesabix.ir"}) presetComboBox.Location = New Point(130, 180) presetComboBox.Size = New Size(200, 25) presetComboBox.Font = New Font("Consolas", 9) Dim usePresetButton As New Button() usePresetButton.Text = "استفاده" usePresetButton.Font = New Font("Segoe UI", 9) usePresetButton.Location = New Point(340, 180) usePresetButton.Size = New Size(60, 25) usePresetButton.BackColor = Color.FromArgb(100, 150, 200) usePresetButton.ForeColor = Color.White usePresetButton.FlatStyle = FlatStyle.Flat Dim testButton As New Button() testButton.Text = "تست اتصال" testButton.Font = New Font("Segoe UI", 10) testButton.Location = New Point(20, 220) testButton.Size = New Size(100, 30) testButton.BackColor = Color.FromArgb(0, 120, 215) testButton.ForeColor = Color.White testButton.FlatStyle = FlatStyle.Flat Dim saveButton As New Button() saveButton.Text = "ذخیره" saveButton.Font = New Font("Segoe UI", 10) saveButton.Location = New Point(300, 220) saveButton.Size = New Size(80, 30) saveButton.BackColor = Color.FromArgb(100, 200, 100) saveButton.ForeColor = Color.White saveButton.FlatStyle = FlatStyle.Flat Dim cancelButton As New Button() cancelButton.Text = "لغو" cancelButton.Font = New Font("Segoe UI", 10) cancelButton.Location = New Point(390, 220) cancelButton.Size = New Size(80, 30) cancelButton.BackColor = Color.FromArgb(200, 100, 100) cancelButton.ForeColor = Color.White cancelButton.FlatStyle = FlatStyle.Flat ' اضافه کردن کنترل‌ها به فرم settingsForm.Controls.AddRange({titleLabel, urlLabel, urlTextBox, infoLabel, presetLabel, presetComboBox, usePresetButton, testButton, saveButton, cancelButton}) ' Event handlers AddHandler usePresetButton.Click, Sub(sender, e) If presetComboBox.SelectedItem IsNot Nothing Then urlTextBox.Text = presetComboBox.SelectedItem.ToString() End If End Sub AddHandler testButton.Click, Sub(sender, e) TestApiConnection(urlTextBox.Text) End Sub AddHandler saveButton.Click, Sub(sender, e) My.Settings.apiUrl = urlTextBox.Text.Trim My.Settings.Save() ApiUrlTextBox.Text = urlTextBox.Text.Trim settingsForm.Close() ShowStatus("آدرس API با موفقیت ذخیره شد", False) End Sub AddHandler cancelButton.Click, Sub(sender, e) settingsForm.Close() End Sub ' نمایش فرم settingsForm.ShowDialog(Me) End Sub Private Sub TestApiConnection(testUrl As String) Try ' اعتبارسنجی URL If Not IsValidUrl(testUrl) Then MessageBox.Show("آدرس وارد شده صحیح نیست. لطفاً آدرس کامل را وارد کنید (مثال: https://api.hesabix.ir)", "خطا", MessageBoxButtons.OK, MessageBoxIcon.Warning) Return End If ' ذخیره موقت URL برای تست Dim originalUrl As String = My.Settings.apiUrl My.Settings.apiUrl = testUrl.Trim Dim testApi As New ApiInterface() Dim result As String = testApi.TestSSLConnection() ' بازگرداندن URL اصلی My.Settings.apiUrl = originalUrl MessageBox.Show($"نتیجه تست اتصال:" & vbCrLf & result, "تست اتصال", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MessageBox.Show($"خطا در تست اتصال:" & vbCrLf & ex.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub Private Function IsValidUrl(url As String) As Boolean Try If String.IsNullOrWhiteSpace(url) Then Return False ' بررسی وجود http یا https If Not url.StartsWith("http://") AndAlso Not url.StartsWith("https://") Then Return False End If ' بررسی با Uri.TryCreate Dim uri As Uri = Nothing Return Uri.TryCreate(url, UriKind.Absolute, uri) AndAlso (uri.Scheme = Uri.UriSchemeHttp OrElse uri.Scheme = Uri.UriSchemeHttps) Catch Return False End Try End Function Protected Overrides Sub OnPaint(e As PaintEventArgs) MyBase.OnPaint(e) ' رسم گرادیانت پس‌زمینه Dim rect As New Rectangle(0, 0, Me.Width, Me.Height) Using brush As New LinearGradientBrush(rect, Color.FromArgb(30, 30, 30), Color.FromArgb(50, 50, 50), 135.0F) e.Graphics.FillRectangle(brush, rect) End Using ' رسم خط تزئینی در پایین Using pen As New Pen(Color.FromArgb(0, 120, 215), 2) e.Graphics.DrawLine(pen, 0, Me.Height - 2, Me.Width, Me.Height - 2) End Using End Sub Private Sub CleanupTimers() If loginTimer IsNot Nothing Then loginTimer.Stop() loginTimer.Dispose() loginTimer = Nothing End If End Sub End Class