mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-28 00:33:06 +08:00
[ui] unify mobile privacy screen icons by state
This commit is contained in:
@@ -59,7 +59,7 @@ final class MobileUi {
|
||||
Icon glyph=new Icon(context,icon,INK);FrameLayout.LayoutParams p=new FrameLayout.LayoutParams(dp(22),dp(22),Gravity.CENTER);box.addView(glyph,p);
|
||||
box.setContentDescription(label);box.setClickable(true);box.setFocusable(true);box.setOnClickListener(v->click.run());return box;
|
||||
}
|
||||
View icon(String name,int color) { return new Icon(context,name,color); }
|
||||
Icon icon(String name,int color) { return new Icon(context,name,color); }
|
||||
void gap(LinearLayout parent,int height){parent.addView(new View(context),new LinearLayout.LayoutParams(1,dp(height)));}
|
||||
void divider(LinearLayout parent){View line=new View(context);line.setBackgroundColor(LINE);parent.addView(line,new LinearLayout.LayoutParams(-1,dp(.5f)));}
|
||||
LinearLayout.LayoutParams size(int width,int height){return new LinearLayout.LayoutParams(width<0?width:dp(width),height<0?height:dp(height));}
|
||||
@@ -93,8 +93,9 @@ final class MobileUi {
|
||||
}
|
||||
@android.annotation.SuppressLint("ViewConstructor") // Programmatic icon primitive, not inflated from XML.
|
||||
static final class Icon extends View {
|
||||
private final Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG); private final String name;
|
||||
private final Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG); private String name;
|
||||
Icon(Context context,String name,int color){super(context);this.name=name;paint.setColor(color);setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);}
|
||||
void setName(String value){if(name.equals(value))return;name=value;invalidate();}
|
||||
@Override protected void onDraw(Canvas c){
|
||||
c.save();c.scale(getWidth()/24f,getHeight()/24f);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(1.7f);paint.setStrokeCap(Paint.Cap.ROUND);paint.setStrokeJoin(Paint.Join.ROUND);
|
||||
switch(name){
|
||||
@@ -136,6 +137,14 @@ final class MobileUi {
|
||||
case "unlock":c.drawRoundRect(5,10,19,22,2,2,paint);c.drawArc(8,2,16,15,180,150,false,paint);c.drawPoint(12,16,paint);break;
|
||||
case "clipboard":c.drawRoundRect(4,4,20,22,2,2,paint);c.drawRoundRect(8,2,16,7,2,2,paint);break;
|
||||
case "eye":path(c,2,12,6,7,12,5,18,7,22,12,18,17,12,19,6,17,2,12);c.drawCircle(12,12,3,paint);break;
|
||||
case "eye_off":
|
||||
Path hiddenEye=new Path();
|
||||
hiddenEye.moveTo(10,5);hiddenEye.cubicTo(15,4,19,8,22,12);
|
||||
hiddenEye.quadTo(20.4f,14.7f,18,17);
|
||||
hiddenEye.moveTo(6,6);hiddenEye.quadTo(3.5f,8.5f,2,12);
|
||||
hiddenEye.cubicTo(7,20,13,21,18,17);
|
||||
hiddenEye.moveTo(10,10);hiddenEye.cubicTo(8,13,11,16,14,14);
|
||||
c.drawPath(hiddenEye,paint);path(c,3,3,21,21);break;
|
||||
default:c.drawCircle(12,12,9,paint);path(c,12,10,12,17);c.drawPoint(12,6,paint);
|
||||
}c.restore();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ final class SessionControls extends FrameLayout {
|
||||
private TextView videoFeedback;
|
||||
private RemotePrivacyScreen privacy=new RemotePrivacyScreen();
|
||||
private View privacyButton;
|
||||
private MobileUi.Icon privacyIcon;
|
||||
private TextView privacyFeedback,privacyCaption;
|
||||
private TextView transferLabel,saveFileButton;
|
||||
private String transferStatus="";
|
||||
@@ -116,7 +117,7 @@ final class SessionControls extends FrameLayout {
|
||||
if(transferLabel!=null){transferLabel.setText(transferStatus);transferLabel.setVisibility(transferStatus.isEmpty()?GONE:VISIBLE);}
|
||||
if(saveFileButton!=null)saveFileButton.setVisibility(hasReceivedFile?VISIBLE:GONE);
|
||||
}
|
||||
private void closeMenu(){if(menu!=null){removeView(menu);menu=null;menuScroll=null;}if(shield!=null){removeView(shield);shield=null;}videoFeedback=transferLabel=saveFileButton=null;privacyFeedback=privacyCaption=null;privacyButton=null;trafficCells=null;trafficRows=null;networkDetails=null;encryptionLock=encryptionOpen=null;settingRows.clear();orb.setContentDescription("展开远程控制菜单");positionMouse();}
|
||||
private void closeMenu(){if(menu!=null){removeView(menu);menu=null;menuScroll=null;}if(shield!=null){removeView(shield);shield=null;}videoFeedback=transferLabel=saveFileButton=null;privacyFeedback=privacyCaption=null;privacyButton=null;privacyIcon=null;trafficCells=null;trafficRows=null;networkDetails=null;encryptionLock=encryptionOpen=null;settingRows.clear();orb.setContentDescription("展开远程控制菜单");positionMouse();}
|
||||
private void openMenu(String page){
|
||||
cancelMouseInput();
|
||||
closeMenu();menuPage=page;shield=new View(getContext());shield.setOnClickListener(v->closeMenu());addView(shield,new LayoutParams(-1,-1));
|
||||
@@ -133,7 +134,7 @@ final class SessionControls extends FrameLayout {
|
||||
}
|
||||
if(page.equals("controls")){
|
||||
String[] labels={"键盘",mouseVisible?"收起鼠标":"虚拟鼠标",relative?"相对鼠标":"绝对鼠标","显示器","画面设置",muted?"静音":"声音","发送文件","网络状态","Ctrl+Alt+Del","剪贴板","隐私屏"};
|
||||
String[] icons={"keyboard","mouse","mouse","display","sliders","audio","folder","chart","lock","clipboard","lock"};
|
||||
String[] icons={"keyboard","mouse","mouse","display","sliders","audio","folder","chart","lock","clipboard","eye"};
|
||||
Runnable[] clicks={()->{closeMenu();toggleKeyboard();},this::toggleMouse,actions::mouse,actions::display,()->openMenu("video"),actions::mute,actions::sendFile,()->openMenu("network"),actions::secureAttention,actions::clipboard,actions::togglePrivacy};
|
||||
menuColumns=controlColumns();
|
||||
java.util.List<Integer> visibleControls=new java.util.ArrayList<>();
|
||||
@@ -142,8 +143,8 @@ final class SessionControls extends FrameLayout {
|
||||
visibleControls.add(index);
|
||||
}
|
||||
int controlCount=visibleControls.size();
|
||||
for(int row=0;row<(controlCount+menuColumns-1)/menuColumns;row++){LinearLayout line=ui.row();for(int col=0;col<menuColumns;col++){int position=row*menuColumns+col;if(position>=controlCount){View spacer=new View(getContext());LinearLayout.LayoutParams p=new LinearLayout.LayoutParams(0,ui.dp(52),1);if(col>0)p.leftMargin=ui.dp(7);line.addView(spacer,p);continue;}int index=visibleControls.get(position);LinearLayout control=ui.column();control.setGravity(Gravity.CENTER);control.setBackground(ui.background(0xFFF0F0F2,10));control.addView(ui.icon(icons[index],INK),ui.size(19,19));ui.gap(control,4);TextView caption=ui.text(labels[index],10,false);caption.setSingleLine();caption.setGravity(Gravity.CENTER);control.addView(caption);control.setContentDescription(labels[index]);control.setClickable(true);control.setFocusable(true);control.setOnClickListener(v->clicks[index].run());
|
||||
if(index==10){privacyButton=control;privacyCaption=caption;}
|
||||
for(int row=0;row<(controlCount+menuColumns-1)/menuColumns;row++){LinearLayout line=ui.row();for(int col=0;col<menuColumns;col++){int position=row*menuColumns+col;if(position>=controlCount){View spacer=new View(getContext());LinearLayout.LayoutParams p=new LinearLayout.LayoutParams(0,ui.dp(52),1);if(col>0)p.leftMargin=ui.dp(7);line.addView(spacer,p);continue;}int index=visibleControls.get(position);LinearLayout control=ui.column();control.setGravity(Gravity.CENTER);control.setBackground(ui.background(0xFFF0F0F2,10));MobileUi.Icon icon=ui.icon(icons[index],INK);control.addView(icon,ui.size(19,19));ui.gap(control,4);TextView caption=ui.text(labels[index],10,false);caption.setSingleLine();caption.setGravity(Gravity.CENTER);control.addView(caption);control.setContentDescription(labels[index]);control.setClickable(true);control.setFocusable(true);control.setOnClickListener(v->clicks[index].run());
|
||||
if(index==10){privacyButton=control;privacyIcon=icon;privacyCaption=caption;}
|
||||
LinearLayout.LayoutParams p=new LinearLayout.LayoutParams(0,ui.dp(52),1);if(col>0)p.leftMargin=ui.dp(7);line.addView(control,p);
|
||||
}body.addView(line);if((row+1)*menuColumns<controlCount)ui.gap(body,7);}
|
||||
privacyFeedback=ui.text("",11,false);privacyFeedback.setTextColor(SECONDARY);privacyFeedback.setPadding(0,ui.dp(7),0,0);privacyFeedback.setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);body.addView(privacyFeedback);renderPrivacy();
|
||||
@@ -168,6 +169,7 @@ final class SessionControls extends FrameLayout {
|
||||
if(privacyFeedback!=null){String feedback=privacy.feedback(now);privacyFeedback.setText(feedback);privacyFeedback.setVisibility(feedback.isEmpty()?GONE:VISIBLE);}
|
||||
if(privacyButton==null)return;
|
||||
boolean enabled=privacy.enabled(now);String action=privacy.active()?"关闭隐私屏":"开启隐私屏";
|
||||
privacyIcon.setName(enabled?"eye_off":"eye");
|
||||
privacyCaption.setText(privacy.buttonTitle(now));
|
||||
privacyButton.setSelected(enabled);
|
||||
privacyButton.setContentDescription(action+","+privacy.status(now));
|
||||
|
||||
@@ -142,7 +142,7 @@ export struct MobileRemoteView {
|
||||
return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].filter((index: number) =>
|
||||
(index !== 8 || this.state.platform === 'windows') && (index !== 10 || this.state.privacyVisible));
|
||||
}
|
||||
private icons(): string[] { return ['keyboard', 'mouse', 'mouse', 'display', 'sliders', this.state.muted ? 'muted' : 'audio', 'folder', 'chart', 'lock', 'clipboard', 'lock']; }
|
||||
private icons(): string[] { return ['keyboard', 'mouse', 'mouse', 'display', 'sliders', this.state.muted ? 'muted' : 'audio', 'folder', 'chart', 'lock', 'clipboard', this.state.privacyEnabled ? 'eye_off' : 'eye']; }
|
||||
private columns(): number { return this.viewHeight < 400 && this.viewWidth >= 400 ? 4 : 3; }
|
||||
private menuWidth(): number { return Math.max(1, Math.min(this.viewWidth - 16, this.columns() === 4 ? 380 : Math.max(280, Math.min(340, this.viewWidth - 160)))); }
|
||||
private menuX(): number { return clamp(this.orbX > this.viewWidth / 2 ? this.orbX - this.menuWidth() - 12 : this.orbX + 66, 8, this.viewWidth - this.menuWidth() - 8); }
|
||||
|
||||
@@ -1249,7 +1249,7 @@ private struct FloatingSessionMenu: View {
|
||||
if session.privacyScreen.desktopAvailable {
|
||||
FloatingControlButton(
|
||||
title: session.privacyScreen.buttonTitle(at: session.privacyClock),
|
||||
symbol: "eye.slash",
|
||||
symbol: session.privacyScreen.enabled(at: session.privacyClock) ? "eye.slash" : "eye",
|
||||
selected: session.privacyScreen.enabled(at: session.privacyClock),
|
||||
action: session.togglePrivacyScreen
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user