# How the Package Row Widget Displays and Handles Package Information in UAD-ng

> Learn how the PackageRow widget in UAD-ng displays and handles package info, adapting UI elements like buttons and checkboxes to various package states.

- Repository: [Universal-Debloater-Alliance/universal-android-debloater-next-generation](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation)
- Tags: internals
- Published: 2026-06-18

---

**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`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/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`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/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 details
- `ActionPressed` — 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`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/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`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/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:

```rust
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.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/widgets/package_row.rs) encapsulates 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`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/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`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/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.