mirror of
https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation.git
synced 2026-08-09 15:19:11 +02:00
feat: make package descriptions selectable and copyable (#1010)
* feat: make package descriptions selectable and copyable - Replace text widget with text_editor for package descriptions - Add read-only text_editor that allows text selection and copying - Implement Clone manually for List struct to handle text_editor::Content - Add text_editor StyleSheet implementation to match app theme This improves UX by allowing users to copy package descriptions for research or sharing purposes while maintaining the same visual appearance. --------- Co-authored-by: Samuele Domenico Ruffino <sdruffino@it.iliad.com>
This commit is contained in:
parent
bb1f245bc2
commit
d471b798c9
3 changed files with 67 additions and 5 deletions
|
|
@ -42,7 +42,7 @@ pub struct UpdateState {
|
|||
uad_list: UadListState,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default)]
|
||||
pub struct UadGui {
|
||||
view: View,
|
||||
apps_view: AppsView,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::core::theme::Theme;
|
||||
use iced::overlay::menu;
|
||||
use iced::widget::text_editor;
|
||||
use iced::widget::{
|
||||
button, checkbox, container, pick_list, radio, rule, scrollable, text, text_input,
|
||||
};
|
||||
|
|
@ -565,6 +566,50 @@ impl radio::StyleSheet for Theme {
|
|||
}
|
||||
}
|
||||
|
||||
impl text_editor::StyleSheet for Theme {
|
||||
type Style = ();
|
||||
|
||||
fn active(&self, _style: &Self::Style) -> text_editor::Appearance {
|
||||
let p = self.palette();
|
||||
text_editor::Appearance {
|
||||
background: Background::Color(p.base.foreground),
|
||||
border: Border {
|
||||
width: 0.0,
|
||||
radius: 0.0.into(),
|
||||
color: Color::TRANSPARENT,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn focused(&self, style: &Self::Style) -> text_editor::Appearance {
|
||||
self.active(style)
|
||||
}
|
||||
|
||||
fn placeholder_color(&self, _style: &Self::Style) -> Color {
|
||||
self.palette().normal.surface
|
||||
}
|
||||
|
||||
fn value_color(&self, _style: &Self::Style) -> Color {
|
||||
self.palette().bright.surface
|
||||
}
|
||||
|
||||
fn disabled_color(&self, _style: &Self::Style) -> Color {
|
||||
self.palette().normal.surface
|
||||
}
|
||||
|
||||
fn selection_color(&self, _style: &Self::Style) -> Color {
|
||||
let p = self.palette();
|
||||
Color {
|
||||
a: 0.3,
|
||||
..p.normal.primary
|
||||
}
|
||||
}
|
||||
|
||||
fn disabled(&self, style: &Self::Style) -> text_editor::Appearance {
|
||||
self.active(style)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub enum Rule {
|
||||
#[default]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::gui::widgets::package_row::{Message as RowMessage, PackageRow};
|
|||
use crate::gui::widgets::text;
|
||||
use iced::widget::{
|
||||
Column, Space, button, checkbox, column, container, horizontal_space, pick_list, radio, row,
|
||||
scrollable, text_input, tooltip, vertical_rule,
|
||||
scrollable, text_editor, text_input, tooltip, vertical_rule,
|
||||
};
|
||||
use iced::{Alignment, Command, Element, Length, Renderer, alignment};
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ pub enum LoadingState {
|
|||
FailedToUpdate,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
#[derive(Default, Debug)]
|
||||
#[allow(clippy::struct_excessive_bools, reason = "Not a state-machine")]
|
||||
pub struct List {
|
||||
pub loading_state: LoadingState,
|
||||
|
|
@ -57,6 +57,7 @@ pub struct List {
|
|||
all_selected: bool,
|
||||
pub input_value: String,
|
||||
description: String,
|
||||
description_content: text_editor::Content,
|
||||
selection_modal: bool,
|
||||
error_modal: Option<String>,
|
||||
export_modal: bool,
|
||||
|
|
@ -89,6 +90,7 @@ pub enum Message {
|
|||
GoToUrl(PathBuf),
|
||||
ExportSelection,
|
||||
SelectionExported(Result<bool, String>),
|
||||
DescriptionEdit(text_editor::Action),
|
||||
}
|
||||
|
||||
pub struct SummaryEntry {
|
||||
|
|
@ -280,6 +282,8 @@ impl List {
|
|||
}
|
||||
RowMessage::PackagePressed => {
|
||||
self.description = package.clone().description;
|
||||
self.description_content =
|
||||
text_editor::Content::with_text(&package.description);
|
||||
package.current = true;
|
||||
if self.current_package_index != i_package {
|
||||
self.phone_packages[i_user][self.current_package_index].current = false;
|
||||
|
|
@ -352,6 +356,18 @@ impl List {
|
|||
Command::none()
|
||||
}
|
||||
Message::Nothing => Command::none(),
|
||||
Message::DescriptionEdit(action) => {
|
||||
match action {
|
||||
text_editor::Action::Edit(_) => {
|
||||
// Do nothing - ignore all editing operations
|
||||
}
|
||||
// Allow all other actions (movement, selection, clicking, scrolling, etc.)
|
||||
_ => {
|
||||
self.description_content.perform(action);
|
||||
}
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -487,8 +503,9 @@ impl List {
|
|||
.height(Length::FillPortion(6))
|
||||
.style(style::Scrollable::Packages);
|
||||
|
||||
let description_scroll = scrollable(text(&self.description).width(Length::Fill))
|
||||
.style(style::Scrollable::Description);
|
||||
let description_scroll =
|
||||
scrollable(text_editor(&self.description_content).on_action(Message::DescriptionEdit))
|
||||
.style(style::Scrollable::Description);
|
||||
|
||||
let description_panel = container(description_scroll)
|
||||
.padding(6)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue