How the Package Row Widget Displays and Handles Package Information in UAD-ng
The PackageRow widget encapsulates all UI state for individual Android packages, dynamically rendering action buttons and checkboxes that adapt to package states (Enabled, Disabled, Uninstalled) while respecting expert-mode and disable-mode safety settings.
The Universal Android Debloater Next Generation (UAD-ng) implements a sophisticated widget-based architecture using the Iced GUI framework to manage Android package lists. The package row widget serves as the fundamental interface element that bridges core package data with user interactions, displaying package identifiers, selection states, and context-sensitive action controls. This widget implementation in crates/uad-gui/src/widgets/package_row.rs handles the complex logic of visual state management and event propagation throughout the application.
Core Architecture of the Package Row Widget
The PackageRow Struct and Data Model
The PackageRow struct (defined at lines 12-21 in crates/uad-gui/src/widgets/package_row.rs) stores all UI-relevant data for a single Android package. It maintains fields for the package name, description, removal type, current state, list category, and selection flags. The struct implements conversion traits From<CorePackage> and From<&CorePackage> (lines 49-100) to seamlessly ingest data from the core library's uad_core::sync::CorePackage type, ensuring the GUI layer remains synchronized with underlying package metadata.
Message-Based Communication
User interactions propagate through the Message enum (lines 23-28), which defines three distinct variants that the parent view must handle:
PackagePressed— Emitted when the user clicks the entire row to select or view detailsActionPressed— Triggered by the primary action button (Uninstall/Enable/Restore)ToggleSelection(bool)— Fired when the user toggles the selection checkbox
State-Driven Rendering Logic
Package State Mapping
The view method (lines 60-146) implements pattern matching on self.state to determine both the action button text and visual styling. The widget maps each package state to specific UI representations:
| Package State | Button Text | Style Applied |
|---|---|---|
Enabled |
Uninstall (or Disable when disable-mode is active) | Button::UninstallPackage |
Disabled |
Enable | Button::RestorePackage |
Uninstalled |
Restore | Button::RestorePackage |
| Other | Error | Button::RestorePackage (with logging) |
Expert Mode and Safety Controls
The widget consults the Settings reference (passed to view at line 62) to enforce safety restrictions defined in crates/uad-gui/src/views/settings.rs. When expert-mode is disabled, unsafe packages cannot be removed, and the checkbox applies style::CheckBox::PackageDisabled instead of PackageEnabled (lines 95-99). The disable-mode flag alters the primary action text from "Uninstall" to "Disable" for enabled packages, changing the underlying operation while maintaining the same UI structure.
Interactive UI Components
Checkbox Implementation
The selection checkbox uses iced::widget::checkbox(self.selected) with on_press handling that emits Message::ToggleSelection. Its visual state derives from style::CheckBox::PackageEnabled or PackageDisabled (defined in crates/uad-gui/src/style.rs), providing immediate visual feedback on selection capability based on current safety settings.
Action Button and Row Composition
The action button construction utilizes iced::widget::button(text(action_text)) with .on_press(Message::ActionPressed) and receives its styling from the previously determined button_style function. The entire row nests this checkbox, package name text, and action button within a larger clickable button that emits Message::PackagePressed when tapped. The outer button applies Button::SelectedPackage style when self.current is true, otherwise Button::NormalPackage, creating a clear visual hierarchy for active selections.
The Update Method
Currently, the update method (lines 52-58) functions as a placeholder returning iced::Command::none(), indicating that state mutations occur at the parent view level rather than within the widget itself. This architecture separates presentation logic from state management, following the Elm pattern used throughout UAD-ng.
Implementation Example
The following example demonstrates converting a core package to a UI row and handling its messages within a parent view:
use uad_gui::widgets::package_row::{PackageRow, Message};
use uad_gui::views::settings::Settings;
use uad_core::sync::CorePackage;
// Convert core package data to UI representation
let core_pkg = CorePackage {
name: "com.example.app".into(),
description: "Example app".into(),
removal: uad_core::uad_lists::Removal::Safe,
state: uad_core::uad_lists::PackageState::Enabled,
list: uad_core::uad_lists::UadList::System,
};
let mut pkg_row = PackageRow::from(core_pkg);
// Render with current settings and phone placeholder
let settings = Settings::load();
let phone = Phone::new(); // Placeholder for future device-specific logic
let element = pkg_row.view(&settings, &phone);
// Handle widget messages in parent view
match msg {
Message::PackagePressed => {
// Handle row selection (e.g., show details)
}
Message::ActionPressed => {
// Trigger uninstall, enable, or restore operation
}
Message::ToggleSelection(selected) => {
pkg_row.selected = selected;
}
}
Summary
- The PackageRow widget in
crates/uad-gui/src/widgets/package_row.rsencapsulates all UI state for individual Android packages within UAD-ng. - State-driven rendering matches package states (Enabled, Disabled, Uninstalled) to specific action buttons and visual styles defined in
crates/uad-gui/src/style.rs. - Expert-mode and disable-mode settings dynamically alter widget behavior and styling without changing the core data model.
- The widget communicates user interactions through the Message enum variants (
PackagePressed,ActionPressed,ToggleSelection). - Visual styling delegates to dedicated style functions including
Button::UninstallPackage,Button::RestorePackage, and checkbox variants.
Frequently Asked Questions
How does the package row widget determine which action button to display?
The widget matches on self.state in the view method to select the appropriate button text and style. Enabled packages display "Uninstall" (or "Disable" in disable-mode) with Button::UninstallPackage styling, while Disabled and Uninstalled packages show "Enable" and "Restore" respectively, both using Button::RestorePackage.
What is the purpose of the expert mode check in the package row?
The expert mode validation (lines 95-99) prevents users from removing unsafe packages unless explicitly enabled in settings. When disabled, the checkbox renders with CheckBox::PackageDisabled styling and the action button becomes non-interactive for unsafe packages, serving as a safety guard against system instability.
How does the PackageRow widget communicate user interactions to the parent view?
The widget defines a Message enum with three variants emitted through Iced's reactive framework: PackagePressed for row clicks, ActionPressed for the primary button, and ToggleSelection(bool) for checkbox state changes. The parent view matches these messages in its own update logic to modify application state.
Where are the visual styles for the package row defined?
Visual styles reside in crates/uad-gui/src/style.rs, specifically the Button::UninstallPackage and Button::RestorePackage implementations for action buttons, plus CheckBox::PackageEnabled and PackageDisabled for selection controls. These style functions return iced::widget::button::Appearance and checkbox appearance structs respectively.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →