Docs GitHub
-- --
Theme:
Language:
EN فا

رابط کاربری (UI)#

رابط کاربری پایانی (Terminal UI) ابزار bgscan بر پایه فریم‌ورک BubbleTea (نسخه فورک شده Elvish v2 در مسیر charm.land/bubbletea/v2) و ابزار استایل‌دهی [Lipgloss] توسعه یافته است. معماری این بخش به صورت یک درخت کامپوننت (Component Tree) همراه با یک سیستم دیالوگ لایه‌ای (Overlay) و یک مدیریت‌کننده چیدمان مرکزی (Layout Manager) طراحی شده است.


نقشه پکیج‌ها (Package Map)#

پکیجوظیفه و مسئولیت
ui/main/appمدل ریشه (Root) در BubbleTea. مدیریت چیدمان، هدر/بدنه/فوتر و پشته‌ی دیالوگ‌های لایه‌ای.
ui/main/headerنوار بالایی — شامل نام برنامه و برندینگ آن.
ui/main/bodyبخش محتوای مرکزی — پشته‌ای از کامپوننت‌ها را نگه می‌دارد (منوی اصلی ← زیرصفحه‌ها).
ui/main/footerنوار وضعیت پایین — نسخه برنامه، نام صفحه فعلی، تعداد گوروتین‌ها و میزان مصرف حافظه رم.
ui/components/basicویجت‌های قابل استفاده مجدد: تاییدیه، مدیریت داده (CRUD)، فیلد ورودی، بازرس (Inspector)، نمایش لاگ، منو، اعلان، انتخاب‌گر فایل، نوار پیشرفت، جدول و تب‌ها.
ui/components/inspectorفرم‌های تنظیمات اختصاصی هر پروتکل (DNS، عمومی، HTTP، ICMP، TCP، Xray).
ui/components/menusمنوهای سطح صفحه: ورودی اصلی (Entry)، لاگ‌ها، آوتباندها، نوع اسکن، تنظیمات، منبع هدف.
ui/components/tablesجدول‌های داده: لیست آی‌پی، نمایشگر آی‌پی، آوتباندها، لیست نتایج.
ui/components/scannerنمای زنده اسکن — نوارهای پیشرفت تب‌بندی‌شده + جدول نتایج به ازای هر مرحله.
ui/sharedزیرساخت‌های مشترک: چیدمان هندسی، دیالوگ، محیط (کلیدها/حالت‌ها)، اینترفیس کامپوننت و اعتبارسنجی.
ui/themeپالت‌های رنگی تاریک/روشن/خودکار + آداپتور تم برای فرم‌های کتابخانه huh.

اینترفیس کامپوننت (Component Interface)#

تمام صفحه‌ها، ویجت‌ها و دیالوگ‌ها اینترفیس ui.shared.ui.Component را پیاده‌سازی می‌کنند:

type Component interface {
    ID() ComponentID
    Name() string
    Init() tea.Cmd
    Update(tea.Msg) (Component, tea.Cmd)
    View() string
    OnClose() tea.Cmd
    Mode() env.Mode
}
  • ID — یک شناسه یکتا (UUID) که توسط NewComponentID() تولید می‌شود و برای تطبیق پیام‌های باز/بسته شدن کاربرد دارد.
  • Name — یک نام قابل فهم برای انسان که در نوار وضعیت فوتر نشان داده می‌شود.
  • Init — یک‌بار در زمان سوار شدن (Mount) کامپوننت فراخوانی می‌شود و یک tea.Cmd را برای تنظیمات ناهمگام برمی‌گرداند.
  • Update — مسیریاب پیام‌ها (Message Router). کامپوننت به‌روزرسانی شده و دستورات جدید را برمی‌گرداند.
  • View — کامپوننت را رندر کرده و خروجی را به صورت رشته (String) خروجی می‌دهد.
  • OnClose — عملیات پاک‌سازی و آزادسازی منابع هنگام حذف کامپوننت از پشته.
  • Mode — تعیین می‌کند کدام کلیدها به عنوان کلید بازگشت یا خروج عمل کنند (بخش حالت‌های ورودی را ببینید).

مدل ریشه (App)#

پکیج ui/main/app بالاترین سطح مدل در BubbleTea است. این مدل سه کامپوننت پایه و یک پشته از دیالوگ‌ها را مدیریت می‌کند:

type model struct {
    layout           *layout.Layout
    dialog           []ui.Component
    dialogPlacements map[ui.ComponentID]*dialogPosition
    header           ui.Component
    body             ui.Component
    footer           ui.Component
}

مسیریابی پیام‌ها (app/update.go)#

متد Update در مدل ریشه، هماهنگ‌کننده اصلی است:

  1. tea.WindowSizeMsg — ابعاد چیدمان را دوباره محاسبه می‌کند: layout.Update(width, height).
  2. tea.KeyPressMsg — فشردن کلید ctrl+c برنامه را فوراً می‌بندد؛ کلید ctrl+t وضعیت گوروتین‌ها را تخلیه (Dump) می‌کند.
  3. رهگیری لایه‌ها (Overlay) — اگر دیالوگی باز باشد، بالاترین دیالوگ تمام ورودی‌های کیبورد را مصرف می‌کند و کلیدهای بازگشت/خروج آن را می‌بندند.
  4. dialog.OpenDialogMsg — یک دیالوگ لایه‌ای جدید را همراه با متادیتای موقعیت مکانی‌اش به بالای پشته اضافه می‌کند.
  5. ui.CloseComponentMsg — دیالوگ لایه‌ای مطابقت‌یافته را بر اساس ID حذف کرده و متد OnClose آن را اجرا می‌کند.
  6. توزیع پایه — اگر هیچ دیالوگی مسیر ورودی را مسدود نکرده باشد، پیام به صورت هم‌زمان به هدر، بدنه و فوتر فرستاده می‌شود.

رندر کردن نهایی (app/view.go)#

متد View در مدل ریشه ساختار زیر را رندر می‌کند:

┌─────────────────────────────────┐
│           header                │
├─────────────────────────────────┤
│                                 │
│           body                  │  ← پشته کامپوننت‌ها (منو ← صفحه فعلی)
│                                 │
├─────────────────────────────────┤
│           footer                │  ← نسخه · وضعیت · گوروتین‌ها · حافظه
└─────────────────────────────────┘
   + دیالوگ‌های لایه‌ای (وسط‌چین شده یا دارای موقعیت خاص)

لایه‌های رویی به کمک کتابخانه bubbletea-overlay روی چیدمان پایه رندر می‌شوند. حداقل اندازه ترمینال برای اجرای برنامه ۳۵×۷۵ است؛ در ابعاد کوچک‌تر، پیام “terminal too small” (ترمینال خیلی کوچک است) به نمایش درمی‌آید.


بدنه — پشته کامپوننت‌ها (Component Stack)#

پکیج ui/main/body یک پشته (Stack) از کامپوننت‌ها را درون خود نگه می‌دارد. کامپوننتی که در بالای پشته قرار دارد، همان صفحه فعال و نمایان است.

components[0] = mainMenu (منوی اصلی)       ← همیشه وجود دارد
components[1] = scan source picker (منبع)  ← به بالای پشته اضافه شده
components[2] = scan type picker (نوع اسکن) ← به بالای پشته اضافه شده
components[3] = scanner view (نمای اسکنر)  ← به بالای پشته اضافه شده

پیام‌های جابه‌جایی و ناوبری:

پیامنتیجه و اثر
ui.OpenComponentMsgاضافه کردن (Push) یک کامپوننت جدید به بالای پشته
ui.CloseComponentMsgحذف کردن (Pop) یک کامپوننت مشخص بر اساس ID آن
ui.ResetComponentStacksMsgپاک‌سازی کامل پشته و بازگشت به منوی ریشه
کلید بازگشت (b / Esc)حذف کردن کامپوننت بالایی (اگر طول پشته بزرگتر از ۱ باشد)
کلید خروج (q)نمایش دیالوگ تاییدیه خروج از برنامه

تنها کامپوننت بالای پشته پیام‌های Update را دریافت می‌کند. وقتی این کامپوننت حذف می‌شود، کامپوننت زیرین آن فعال می‌گردد. نوار وضعیت فوتر نیز نام خود را بر اساس خروجی ()Name کامپوننت بالایی جدید به‌روزرسانی می‌کند.


سیستم دیالوگ لایه‌ای (Overlay)#

پکیج ui/shared/dialog دیالوگ‌های پاپ‌آپی را فراهم می‌کند که بالاتر از چیدمان پایه رندر می‌شوند.

type OpenDialogMsg struct {
    Component ui.Component
    XPos      DialogPosition   // بالا، راست، پایین، چپ، مرکز
    YPos      DialogPosition
    XOffset   int
    YOffset   int
}

دیالوگ‌ها برای تنظیم موقعیت خود از کتابخانه rmhubbert/bubbletea-overlay استفاده می‌کنند. بیشتر دیالوگ‌ها در مرکز صفحه قرار می‌گیرند؛ اما انتخاب‌گرهای فایل و دیالوگ‌های تاییدیه ممکن است موقعیت‌های متفاوتی داشته باشند.

پشته دیالوگ‌ها در app.model از چندین لایه تودرتو پشتیبانی می‌کند — لایه‌ای که بالاتر از همه است، تمام ورودی‌ها را به خود اختصاص می‌دهد.


حالت‌های ورودی (Input Modes)#

فایل ui/shared/env/type.go سه حالت مختلف را تعریف می‌کند که نحوه تفسیر ورودی‌های کیبورد را کنترل می‌کنند:

حالتتوصیفکلیدهای بازگشتکلیدهای خروج
NormalModeناوبری پیش‌فرض در منوهاb، Backspace، Escq، ctrl+c
InputModeتایپ درون یک فیلد متنی یا انتخاب‌گرEscctrl+c
ScanModeاسکن در حال اجرا است(هیچ‌کدام — کنترلرهای UI توقف/پایان را مدیریت می‌کنند)ctrl+c

توابع IsBackKey(msg, mode) و IsQuitKey(msg, mode) در مسیر env/keys.go کلیدها را بر اساس حالت فعلی بررسی می‌کنند. این کار باعث می‌شود زمانی که کاربر در حال تایپ داخل یک فیلد متنی است، کلیدهای خروج یا بازگشت به اشتباه تحریک نشوند.


چیدمان (Layout)#

فایل ui/shared/layout/layout.go یک محاسبه‌گر هندسی وضعیت‌دار است. این پکیج موقعیت و ابعاد هر ناحیه (هدر، بدنه، فوتر) را در هر بار تغییر سایز ترمینال از پیش محاسبه می‌کند:

type Layout struct {
    Terminal TerminalSize   // ابعاد خام ترمینال
    Content  ContentSize    // ناحیه قابل ترسیم (پس از اعمال حاشیه‌ها)
    Header   ComponentSize
    Body     ComponentSize
    Footer   ComponentSize
}

متد Layout.Update(width, height) در پاسخ به هر پیام tea.WindowSizeMsg فراخوانی می‌شود. تمام کامپوننت‌ها یک ارجاع به این ساختار مشترک *Layout دریافت می‌کنند تا بتوانند بدون نیاز به محاسبه مجدد، ابعاد ناحیه خود را استعلام کنند.


ویجت‌های قابل استفاده مجدد (Basic)#

پوشه ui/components/basic/ حاوی ویجت‌های پایه‌ای و ساختاری است که در سراسر صفحه‌ها استفاده می‌شوند:

ویجتهدف و کاربرد
confirmدیالوگ تاییدیه بله/خیر (مورد استفاده برای خروج، حذف)
crudاینترفیس جدول مدیریت داده عمومی (لیست‌های آی‌پی، آوتباندها) همراه با انتزاع Provider
inputپوسته دیالوگ ورودی + ویجت‌های ورودی تایپ‌شده (متنی، چندخطی، تک‌انتخابی، چندانتخابی، سوییچ)
inspectorویرایشگر عمومی تنظیمات کلید-مقدار همراه با فرمت‌دهی فیلدها و آداپتورهای نوع داده
logviewنمایشگر استریم و اسکرول‌شونده لاگ‌ها (هسته/رابط کاربری/دباگ)
menuلیست منوی عمودی با قابلیت ناوبری از طریق کیبورد
noticeبنر اعلان‌های گذرا و موقت
pickerدیالوگ انتخاب‌گر فایل
progressنوار پیشرفت انیمیشنی همراه با نمایش زمان تخمینی پایان (ETA) و نرخ ارسال پکت
tableجدول داده با قابلیت مرتب‌سازی و اسکرول
tabsکانتینر تب‌بندی‌شده (مورد استفاده در نمای اسکنر برای تفکیک مراحل)

هر ویجت از اینترفیس استاندارد Component پیروی می‌کند و به گونه‌ای طراحی شده تا بتواند در صفحه‌های بزرگتر ترکیب و استفاده شود.


بازرس‌های تنظیمات (Settings Inspectors)#

پوشه ui/components/inspector/ حاوی فرم‌های تنظیمات اختصاصی به ازای هر پروتکل است:

فرمتنظیماتی که ویرایش می‌کند
generalgeneral_settings.toml
icmpicmp_settings.toml
tcptcp_settings.toml
httphttp_settings.toml
dnsdns_settings.toml
xrayxray_settings.toml

هر بازرس تنظیمات فعلی را از طریق متدهای ()config.GetXxx می‌خواند، فیلدهای قابل ویرایش را رندر می‌کند و هنگام ذخیره، متد ()config.SaveXxxConfig را صدا می‌زند. فیلدها می‌توانند پویا باشند — برای مثال، گزینه‌های TLS تنها زمانی ظاهر می‌شوند که HTTPS انتخاب شده باشد، و فیلدهای DNSTT/SlipStream تنها در صورت فعال بودن آن پروب‌ها به نمایش درمی‌آیند.

ویجت عمومی basic/inspector وظیفه رندر فیلدها، فرمت‌دهی و تبدیل انواع داده را بر عهده دارد؛ پکیج‌های اختصاصی هر پروتکل صرفاً تعریف می‌کنند چه فیلدهایی نشان داده شوند و چگونه به ساختار تنظیمات (Config Struct) نگاشت گردند.


منوها و جدول‌ها#

منوها (ui/components/menus)#

منونقطه تحریک و فراخوانیآنچه نمایش می‌دهد
entryشروع برنامهمنوی اصلی (اجرای اسکن، فایل‌های آی‌پی، فایل‌های نتایج، تنظیمات، آوتباندهای Xray، لاگ‌ها)
targetsourceانتخاب گزینه اجرای اسکنانتخاب‌گر منبع ورودی (لیست آی‌پی در مقابل لیست نتایج قبلی)
scantypeپس از انتخاب منبع ورودیانتخاب‌گر نوع اسکن (ICMP، TCP، HTTP، DNS، Xray)
settingsآیتم منوی تنظیماتانتخاب‌گر دسته‌بندی تنظیمات
outboundmenuآیتم منوی آوتباندهای Xrayمدیریت و پیکربندی آوتباندها
logsآیتم منوی لاگ‌هاانتخاب‌گر دسته‌بندی لاگ (هسته/رابط کاربری/دباگ)

جدول‌ها (ui/components/tables)#

جدولمنبع دادهتامین‌کننده (Provider)
iplistدایرکتوری ips/iplist.Registry
resultlistدایرکتوری results/result.Registry
outboundsکانفیگ‌های آوتباند Xrayپکیج xray
ipviewerمجموعه نتایج درون حافظه (In-memory)کامپوننت اسکنر

جدول‌ها از ویجت ابزار basic/table و یک اینترفیس Provider استفاده می‌کنند که سطرها را تامین کرده و مرتب‌سازی ستون‌ها را هندل می‌کند.


نمای اسکنر (Scanner View)#

پکیج ui/components/scanner همان داشبورد زنده اسکن است. این بخش ساختار Scanner را به لایه رابط کاربری متصل می‌کند:

  • یک تب (Tab) به ازای هر مرحله از اسکن (از طریق basic/tabs).
  • هر تب شامل یک نوار پیشرفت (basic/progress) و یک جدول نتایج زنده (tables/ipviewer) است.
  • وضعیت هر مرحله به صورت مجزا رهگیری می‌شود: Waiting ← PreProcess → Scanning → Ended / Error.
  • به‌روزرسانی‌های پیشرفت از مسیر engine.ScanHooks.OnProgress ← پیام Progress ← متد Update کامپوننت اسکنر جریان می‌یابند.
  • نتایج موفقیت‌آمیز در دسته‌های کوچک به ازای هر مرحله بافر شده و در جدول ipviewer رندر می‌شوند.

کلیدهای کنترلی در طول اسکن: توقف/ادامه (Pause/Resume)، پایان دادن به اسکن (Stop)، جابه‌جایی بین تب‌ها برای مشاهده مراحل مختلف.


تم و ظاهر (Theming)#

فایل ui/theme/theme.go پالت رنگی متمرکز برنامه را فراهم می‌کند:

type Theme struct {
    Primary       color.Color
    Secondary     color.Color
    Border        color.Color
    BorderActive  color.Color
    Text          color.Color
    Muted         color.Color
    Info          color.Color
    Error         color.Color
    Success       color.Color
    Orange        color.Color
    Yellow        color.Color
    Purple        color.Color
    ProgressStart color.Color
    ProgressEnd   color.Color
}

حالت‌ها (Modes)#

حالتنحوه رفتار
ModeAutoرنگ پس‌زمینه ترمینال را از طریق متغیر $COLORFGBG تشخیص داده و تم تاریک/روشن را انتخاب می‌کند.
ModeDarkپالت رنگی تاریک (Dark) را اجبار می‌کند.
ModeLightپالت رنگی روشن (Light) را اجبار می‌کند.

متد theme.Init() در زمان راه‌اندازی برنامه فراخوانی می‌شود. کامپوننت‌ها پالت فعال را از طریق ()theme.Current دریافت می‌کنند — رنگ‌ها نباید به صورت هاردکد (Hardcode) درون کامپوننت‌ها نوشته شوند.

یکپارچه‌سازی با Huh#

فایل ui/theme/huh.go یک ساختار huh.Theme را بر اساس پالت رنگی متمرکز برنامه می‌سازد تا فیلدهای فرم (انتخاب، تاییدیه، ورودی متنی) که توسط کتابخانه huh رندر می‌شوند، با بقیه بخش‌های رابط کاربری هماهنگ باشند و از رنگ‌های پیش‌فرض خود کتابخانه استفاده نکنند. این ابزار در ویجت‌های ورودی (input) و بازرس (inspector) کاربرد دارد.


عیب‌یابی (Debugging)#

تخلیه وضعیت گوروتین‌ها (Goroutine Dump)#

فشردن کلید Ctrl+T در هر زمان، تابع ()dumpGoroutines را در مسیر app/update.go تحریک می‌کند:

  • تعداد کل گوروتین‌های فعال را لاگ می‌کند.
  • پروفایل کامل گوروتین‌های runtime/pprof را در لاگ دباگ می‌نویسد.
  • خطوط حاوی عبارات [chan receive] ،[chan send] ،[select] ،[IO wait] و [sleep] را فیلتر و ثبت می‌کند — این کار برای پیدا کردن ورکرهای قفل‌شده یا نشت پروب‌ها فوق‌العاده مفید است.

آمارهای زمان اجرا (Runtime Stats)#

کامپوننت فوتر معیارهای زمان اجرای Go (Runtime Metrics) را هر ثانیه یک‌بار استعلام می‌کند:

  • ()runtime.NumGoroutine — تعداد گوروتین‌های فعال
  • ()runtime.ReadMemStats — میزان حافظه تخصیص یافته به Heap و کل حافظه سیستم

این آمارها در نوار وضعیت پایین نمایش داده می‌شوند و برای نظارت زنده بر میزان مصرف منابع سیستم در طول اسکن بسیار کاربردی هستند.


صفحات مرتبط#