Add edge swipe dismiss for popup overlays

This commit is contained in:
7015725
2026-05-23 06:08:24 +08:00
parent 095f7ccb39
commit 0cc6439619
3 changed files with 108 additions and 5 deletions

View File

@@ -4624,8 +4624,111 @@ FloatBallAppWM.prototype.showPopupOverlay = function(opts) {
root.setBackgroundColor(self.withAlpha(isDark ? 0xFF000000 : 0xFFFFFFFF, isDark ? 0.58 : 0.42));
root.setClickable(true);
try { root.setFocusable(true); root.setFocusableInTouchMode(true); } catch(eRootFocus) {}
try {
root.setOnKeyListener(new android.view.View.OnKeyListener({
onKey: function(v, keyCode, event) {
try {
if (keyCode === android.view.KeyEvent.KEYCODE_BACK && event && event.getAction && event.getAction() === android.view.KeyEvent.ACTION_UP) {
closePopup();
return true;
}
} catch(eKey) {}
return false;
}
}));
} catch(eRootKey) {}
var card = new android.widget.LinearLayout(context);
var popupBackDownX = 0;
var popupBackDownY = 0;
var popupBackEdge = -1;
var popupBackEligible = false;
var popupBackActive = false;
var popupBackMoved = false;
var card = new JavaAdapter(android.widget.LinearLayout, {
onInterceptTouchEvent: function(ev) {
try {
if (!ev) return false;
var action = ev.getActionMasked();
if (action === android.view.MotionEvent.ACTION_DOWN) {
popupBackDownX = ev.getX();
popupBackDownY = ev.getY();
popupBackEdge = -1;
popupBackEligible = false;
popupBackActive = false;
popupBackMoved = false;
var edgeW = self.dp(56);
var cw = 0;
try { cw = this.getWidth(); } catch(eW) { cw = 0; }
if (popupBackDownX <= edgeW) { popupBackEdge = 0; popupBackEligible = true; }
else if (cw > 0 && popupBackDownX >= cw - edgeW) { popupBackEdge = 1; popupBackEligible = true; }
return false;
}
if (action === android.view.MotionEvent.ACTION_MOVE) {
if (!popupBackEligible) return false;
var dx = ev.getX() - popupBackDownX;
var dy = ev.getY() - popupBackDownY;
var adx = Math.abs(dx);
var ady = Math.abs(dy);
var validDir = (popupBackEdge === 0 && dx > 0) || (popupBackEdge === 1 && dx < 0);
var slop = Math.max(self.dp(8), self.dp(Number(self.config.CLICK_SLOP_DP || 6)));
if (validDir && adx > slop && adx > ady * 0.9) {
popupBackActive = true;
popupBackMoved = true;
try { this.animate().cancel(); } catch(eCancel) {}
try { this.setTranslationX(dx); } catch(eTx) {}
return true;
}
}
} catch(eIntercept) { try { safeLog(self.L, 'w', 'popup back intercept fail: ' + String(eIntercept)); } catch(eLog) {} }
return false;
},
onTouchEvent: function(ev) {
try {
if (!ev || !popupBackActive) return false;
var action = ev.getActionMasked();
if (action === android.view.MotionEvent.ACTION_MOVE) {
var mx = ev.getX() - popupBackDownX;
var my = ev.getY() - popupBackDownY;
var validDir2 = (popupBackEdge === 0 && mx > 0) || (popupBackEdge === 1 && mx < 0);
if (validDir2 && Math.abs(mx) > Math.abs(my) * 0.9) {
popupBackMoved = true;
var maxMove = Math.floor(panelWidth * 0.62);
var tx = mx;
if (tx > maxMove) tx = maxMove;
if (tx < -maxMove) tx = -maxMove;
this.setTranslationX(tx);
}
return true;
}
if (action === android.view.MotionEvent.ACTION_UP || action === android.view.MotionEvent.ACTION_CANCEL) {
var ux = ev.getX() - popupBackDownX;
var uy = ev.getY() - popupBackDownY;
var okDir = (popupBackEdge === 0 && ux > self.dp(72)) || (popupBackEdge === 1 && ux < -self.dp(72));
var ok = action === android.view.MotionEvent.ACTION_UP && popupBackMoved && okDir && Math.abs(ux) > Math.abs(uy) * 0.9;
var dir = popupBackEdge === 1 ? -1 : 1;
popupBackActive = false;
popupBackEligible = false;
popupBackMoved = false;
popupBackEdge = -1;
if (ok) {
this.animate().translationX(dir * panelWidth).alpha(0.96).setDuration(150).withEndAction(new java.lang.Runnable({ run: function() { closePopup(); } })).start();
} else {
this.animate().translationX(0).alpha(1).setDuration(160).start();
}
return true;
}
return true;
} catch(eTouch) {
popupBackActive = false;
popupBackEligible = false;
popupBackMoved = false;
popupBackEdge = -1;
try { this.setTranslationX(0); this.setAlpha(1); } catch(eReset) {}
try { safeLog(self.L, 'w', 'popup back touch fail: ' + String(eTouch)); } catch(eLog2) {}
}
return false;
}
}, context);
card.setOrientation(android.widget.LinearLayout.VERTICAL);
var cardLp = new android.widget.FrameLayout.LayoutParams(panelWidth, panelHeight);
cardLp.gravity = android.view.Gravity.CENTER;

View File

@@ -62,8 +62,8 @@
"size": 23906
},
"th_14_panels.js": {
"sha256": "fcbab7b835c4f020c258d8ddd81675e486572bc140dc6db4aa3bee3f9c2aa27d",
"size": 268044
"sha256": "9ecfbb5f367802cb3b9f3cbcfbb473e75656207cd03ad61cd25bb43d080c8c41",
"size": 272423
},
"th_14_schema_editor.js": {
"sha256": "5669d0b5a16f770bed24eedee24203df57f7cbc7910c840931e533adac1ef146",
@@ -80,5 +80,5 @@
},
"keyId": "toolhub-targets-2026-rsa3072",
"schema": 2,
"version": 20260522220033
"version": 20260522220817
}

View File

@@ -1 +1 @@
C96vTXwZOxNzf6dPnp6DLtQzgY1xdVSe+JAObGu78cZqXO4BNCooFVfLGN4/WaTICx6e6mJ/dtmRVnPtJVc39+EDSaDWUg1ELtD4pPW4u5a5r8qU0J7mCxpUvLcTowG0txvheU4Cu5FQqPdHuBgNiyS1J5pNu0WAHapVBhyR7PXgOA8gnzzSaYZyawO/tf6uG20nVS3cFnlcw+ImvmY0tdLUTnfoaRJZBZMDAy5P36oLZCb3NSoqKPSrNj2cWr6i0x+h5D1jdDxRDjBGpK/fRsJAh4CdZTch8pEQsHVlGakb5hLmGARF0WR3RMHOCVeJNj2LXza1ktx2apjfUPJj84neHBgTCj0BcfwrZ0VY52cwE7n5aJn9xdXMaOiPzlioF7fcN9gmMS6ib0+N9qpW2sqfSSXmiWVEuUvNS0f11w39WfzPI5UNE+rt5bwplIWCuiLPWu65wAewm5Fz+y49ysqYuhPJwUEfJ8HLn+wRJnFcaOdWGod2U3DSVLliwi5Y
YhHLAiZPsJLqf7OEX6ttGyJW25rDDxh+lv066wwRbJMIVsvbpX5m0NKmXTwTJhHYrwc2G3Fsile9hvTe6UXXEQU8FurBxA55g3U9WQadSsXVBi2I3E41IiES5IiFxpp1BHDXr4X3mOv1tvNmAfiPdVZ9NU/YD8+gGHdcGUK/OT5DWpfFduTOAdkC9garVWdfHPCxHlxwCS7TYoeKxkGdi8gQdR/pWHfRp6F9pZ103HyuRyTWCZVeU+1Nh/VGOb5a+HGPGQmHOcEb/Gqh4+w9AuGH++VhpH50fMJJdh5CZVObuTlfsEnili+F0QmHhMeKhzpnPnP2gj15ahAm0ThK6rOgDxdyeJ1DzptbkhjYAckoTMLcDEKulJ24fiugkPIvL1vx/OR6mqM8/JJKIA/4aFe+Km1SRLNj7c9m6VOYGQypA6PD2qwDdreMm2AZzyhcIEQdUIbH0k8lFUPFrVVRBAYgJf7R/SkTeLvHgeczPGsjX1nadPavl+4RsrLpLeVi