@@ -494,6 +494,72 @@ function __scDrawableToBitmap(drawable, targetPx) {
}
}
}
}
FloatBallAppWM . prototype . matchesButtonManagerQuery = function ( btnCfg , query ) {
try {
var q = String ( query || "" ) . replace ( /^\s+|\s+$/g , "" ) . toLowerCase ( ) ;
if ( ! q ) return true ;
var b = btnCfg || { } ;
var hay = String ( b . title || "" ) + " " + String ( b . type || "" ) + " " + String ( b . cmd || "" ) + " " + String ( b . pkg || "" ) + " " + String ( b . action || "" ) + " " + String ( b . intent || "" ) + " " + String ( b . shortcutName || "" ) + " " + String ( b . iconResName || "" ) ;
return hay . toLowerCase ( ) . indexOf ( q ) >= 0 ;
} catch ( e ) { return true ; }
} ;
FloatBallAppWM . prototype . createButtonManagerSummaryCard = function ( parent , totalCount , enabledCount , disabledCount ) {
var isDark = this . isDarkTheme ( ) ;
var C = this . ui . colors ;
var card = new android . widget . LinearLayout ( context ) ;
card . setOrientation ( android . widget . LinearLayout . VERTICAL ) ;
card . setPadding ( this . dp ( 14 ) , this . dp ( 10 ) , this . dp ( 14 ) , this . dp ( 10 ) ) ;
card . setBackground ( this . ui . createRoundDrawable ( isDark ? this . withAlpha ( C . cardDark , 0.88 ) : this . withAlpha ( C . cardLight , 0.92 ) , this . dp ( 14 ) ) ) ;
try { card . setElevation ( this . dp ( 2 ) ) ; } catch ( eElev ) { safeLog ( null , 'e' , "catch " + String ( eElev ) ) ; }
var title = new android . widget . TextView ( context ) ;
title . setText ( "按钮管理首页" ) ;
title . setTextColor ( isDark ? C . textPriDark : C . textPriLight ) ;
title . setTextSize ( android . util . TypedValue . COMPLEX _UNIT _SP , 15 ) ;
title . setTypeface ( null , android . graphics . Typeface . BOLD ) ;
card . addView ( title ) ;
var sub = new android . widget . TextView ( context ) ;
sub . setText ( "共 " + totalCount + " 个 · 已启用 " + enabledCount + " · 已禁用 " + disabledCount ) ;
sub . setTextColor ( isDark ? C . textSecDark : C . textSecLight ) ;
sub . setTextSize ( android . util . TypedValue . COMPLEX _UNIT _SP , 12 ) ;
sub . setPadding ( 0 , this . dp ( 4 ) , 0 , 0 ) ;
card . addView ( sub ) ;
var lp = new android . widget . LinearLayout . LayoutParams ( android . widget . LinearLayout . LayoutParams . MATCH _PARENT , android . widget . LinearLayout . LayoutParams . WRAP _CONTENT ) ;
lp . setMargins ( this . dp ( 2 ) , this . dp ( 2 ) , this . dp ( 2 ) , this . dp ( 8 ) ) ;
parent . addView ( card , lp ) ;
} ;
FloatBallAppWM . prototype . createButtonEditorSectionCard = function ( parent , title , desc ) {
var isDark = this . isDarkTheme ( ) ;
var C = this . ui . colors ;
var box = new android . widget . LinearLayout ( context ) ;
box . setOrientation ( android . widget . LinearLayout . VERTICAL ) ;
box . setPadding ( this . dp ( 12 ) , this . dp ( 10 ) , this . dp ( 12 ) , this . dp ( 10 ) ) ;
box . setBackground ( this . ui . createRoundDrawable ( isDark ? this . withAlpha ( C . cardDark , 0.72 ) : this . withAlpha ( C . cardLight , 0.78 ) , this . dp ( 14 ) ) ) ;
var tv = new android . widget . TextView ( context ) ;
tv . setText ( String ( title || "" ) ) ;
tv . setTextColor ( isDark ? C . textPriDark : C . textPriLight ) ;
tv . setTextSize ( android . util . TypedValue . COMPLEX _UNIT _SP , 14 ) ;
tv . setTypeface ( null , android . graphics . Typeface . BOLD ) ;
box . addView ( tv ) ;
if ( desc ) {
var dv = new android . widget . TextView ( context ) ;
dv . setText ( String ( desc ) ) ;
dv . setTextColor ( isDark ? C . textSecDark : C . textSecLight ) ;
dv . setTextSize ( android . util . TypedValue . COMPLEX _UNIT _SP , 11 ) ;
dv . setPadding ( 0 , this . dp ( 3 ) , 0 , 0 ) ;
box . addView ( dv ) ;
}
var lp = new android . widget . LinearLayout . LayoutParams ( android . widget . LinearLayout . LayoutParams . MATCH _PARENT , android . widget . LinearLayout . LayoutParams . WRAP _CONTENT ) ;
lp . setMargins ( 0 , this . dp ( 8 ) , 0 , this . dp ( 8 ) ) ;
parent . addView ( box , lp ) ;
return box ;
} ;
FloatBallAppWM . prototype . buildButtonEditorPanelView = function ( ) {
FloatBallAppWM . prototype . buildButtonEditorPanelView = function ( ) {
var self = this ;
var self = this ;
// # 状态管理: editingIndex (null=列表, -1=新增, >=0=编辑)
// # 状态管理: editingIndex (null=列表, -1=新增, >=0=编辑)
@@ -578,6 +644,41 @@ FloatBallAppWM.prototype.buildButtonEditorPanelView = function() {
// 暴露 Header 给 DragListener
// 暴露 Header 给 DragListener
panel . setTag ( header ) ;
panel . setTag ( header ) ;
var enabledCount = 0 ;
var disabledCount = 0 ;
try {
for ( var ci = 0 ; ci < buttons . length ; ci ++ ) {
if ( buttons [ ci ] && buttons [ ci ] . enabled === false ) disabledCount ++ ;
else enabledCount ++ ;
}
} catch ( eCnt ) { safeLog ( null , 'e' , "catch " + String ( eCnt ) ) ; }
self . createButtonManagerSummaryCard ( panel , buttons . length , enabledCount , disabledCount ) ;
var searchRow = new android . widget . LinearLayout ( context ) ;
searchRow . setOrientation ( android . widget . LinearLayout . HORIZONTAL ) ;
searchRow . setGravity ( android . view . Gravity . CENTER _VERTICAL ) ;
searchRow . setPadding ( 0 , 0 , 0 , self . dp ( 8 ) ) ;
var searchInput = self . ui . createInputGroup ( self , "搜索按钮" , self . state . buttonManagerQuery || "" , false , "标题 / 类型 / 包名 / 命令" ) ;
var searchInputLp = new android . widget . LinearLayout . LayoutParams ( 0 , android . widget . LinearLayout . LayoutParams . WRAP _CONTENT ) ;
searchInputLp . weight = 1 ;
searchRow . addView ( searchInput . view , searchInputLp ) ;
var btnSearch = self . ui . createFlatButton ( self , "搜索" , C . primary , function ( ) {
try { self . state . buttonManagerQuery = String ( searchInput . getValue ? searchInput . getValue ( ) : "" ) ; } catch ( eQ ) { self . state . buttonManagerQuery = "" ; }
self . state . btnEditorListScrollY = 0 ;
refreshPanel ( ) ;
} ) ;
searchRow . addView ( btnSearch ) ;
var btnClearSearch = self . ui . createFlatButton ( self , "清空" , subTextColor , function ( ) {
self . state . buttonManagerQuery = "" ;
self . state . btnEditorListScrollY = 0 ;
refreshPanel ( ) ;
} ) ;
searchRow . addView ( btnClearSearch ) ;
panel . addView ( searchRow ) ;
var activeQuery = String ( self . state . buttonManagerQuery || "" ) ;
var visibleCount = 0 ;
// 列表区域
// 列表区域
var scroll = new android . widget . ScrollView ( context ) ;
var scroll = new android . widget . ScrollView ( context ) ;
_ _btnEditorListScroll = scroll ; // # 列表滚动位置保持:让 refreshPanel 能拿到当前列表的滚动位置
_ _btnEditorListScroll = scroll ; // # 列表滚动位置保持:让 refreshPanel 能拿到当前列表的滚动位置
@@ -589,6 +690,8 @@ FloatBallAppWM.prototype.buildButtonEditorPanelView = function() {
for ( var i = 0 ; i < buttons . length ; i ++ ) {
for ( var i = 0 ; i < buttons . length ; i ++ ) {
( function ( idx ) {
( function ( idx ) {
var btnCfg = buttons [ idx ] ;
var btnCfg = buttons [ idx ] ;
if ( ! self . matchesButtonManagerQuery ( btnCfg , activeQuery ) ) return ;
visibleCount ++ ;
// # 启用/禁用状态:禁用项在按钮页不显示,但在管理页需要标识出来
// # 启用/禁用状态:禁用项在按钮页不显示,但在管理页需要标识出来
var _ _enabled = true ;
var _ _enabled = true ;
@@ -805,7 +908,7 @@ FloatBallAppWM.prototype.buildButtonEditorPanelView = function() {
}
}
// 空状态提示
// 空状态提示
if ( buttons . length === 0 ) {
if ( visibleCount === 0 ) {
var emptyBox = new android . widget . LinearLayout ( context ) ;
var emptyBox = new android . widget . LinearLayout ( context ) ;
emptyBox . setOrientation ( android . widget . LinearLayout . VERTICAL ) ;
emptyBox . setOrientation ( android . widget . LinearLayout . VERTICAL ) ;
emptyBox . setGravity ( android . view . Gravity . CENTER ) ;
emptyBox . setGravity ( android . view . Gravity . CENTER ) ;
@@ -819,7 +922,7 @@ FloatBallAppWM.prototype.buildButtonEditorPanelView = function() {
emptyBox . addView ( emptyIcon ) ;
emptyBox . addView ( emptyIcon ) ;
var emptyTv = new android . widget . TextView ( context ) ;
var emptyTv = new android . widget . TextView ( context ) ;
emptyTv . setText ( "暂无按钮,点击右上角新增" ) ;
emptyTv . setText ( activeQuery ? "没有匹配的按钮,点清空查看全部" : "暂无按钮,点击右上角新增" ) ;
emptyTv . setTextColor ( subTextColor ) ;
emptyTv . setTextColor ( subTextColor ) ;
emptyTv . setPadding ( 0 , self . dp ( 16 ) , 0 , 0 ) ;
emptyTv . setPadding ( 0 , self . dp ( 16 ) , 0 , 0 ) ;
emptyBox . addView ( emptyTv ) ;
emptyBox . addView ( emptyTv ) ;
@@ -911,6 +1014,8 @@ FloatBallAppWM.prototype.buildButtonEditorPanelView = function() {
editHint . setPadding ( self . dp ( 4 ) , 0 , 0 , self . dp ( 16 ) ) ;
editHint . setPadding ( self . dp ( 4 ) , 0 , 0 , self . dp ( 16 ) ) ;
form . addView ( editHint ) ;
form . addView ( editHint ) ;
self . createButtonEditorSectionCard ( form , "基础信息" , "按钮名称与基础标识" ) ;
// 1. 标题 (Title)
// 1. 标题 (Title)
var topArea = new android . widget . LinearLayout ( context ) ;
var topArea = new android . widget . LinearLayout ( context ) ;
topArea . setOrientation ( android . widget . LinearLayout . HORIZONTAL ) ;
topArea . setOrientation ( android . widget . LinearLayout . HORIZONTAL ) ;
@@ -930,6 +1035,8 @@ FloatBallAppWM.prototype.buildButtonEditorPanelView = function() {
form . addView ( topArea ) ;
form . addView ( topArea ) ;
self . createButtonEditorSectionCard ( form , "图标外观" , "选择图标来源、ShortX 图标和颜色" ) ;
// 1.5 图标选择(文件路径 或 ShortX 内置图标 二选一)
// 1.5 图标选择(文件路径 或 ShortX 内置图标 二选一)
var iconSelectWrap = new android . widget . LinearLayout ( context ) ;
var iconSelectWrap = new android . widget . LinearLayout ( context ) ;
iconSelectWrap . setOrientation ( android . widget . LinearLayout . VERTICAL ) ;
iconSelectWrap . setOrientation ( android . widget . LinearLayout . VERTICAL ) ;
@@ -2097,6 +2204,8 @@ FloatBallAppWM.prototype.buildButtonEditorPanelView = function() {
} ) ) ;
} ) ) ;
self . createButtonEditorSectionCard ( form , "动作设置" , "选择点击后执行的动作类型与参数" ) ;
// 2. 动作类型(自动换行:用 GridLayout 稳定实现)
// 2. 动作类型(自动换行:用 GridLayout 稳定实现)
// 这段代码的主要内容/用途: 把「Shell/App/广播/Intent/快捷方式」做成会自动换行的单选框区域。
// 这段代码的主要内容/用途: 把「Shell/App/广播/Intent/快捷方式」做成会自动换行的单选框区域。
// 说明:之前用"多行 LinearLayout + 手工测量"在部分 ROM/布局时序下会出现宽度为 0 或不渲染,导致"单选框看不见"。
// 说明:之前用"多行 LinearLayout + 手工测量"在部分 ROM/布局时序下会出现宽度为 0 或不渲染,导致"单选框看不见"。