Repository: mitmproxy/mitmproxy

Issue:
Flowlist: Focus jumps to bottom of list when deleting flow
##### Steps to reproduce the problem:

1. Create a flow in mitmproxy, duplicate it ten times.
2. Delete flow number 5.
3. Cursor jumps to the last flow, instead to what previously was flow 6.

##### System information

Mitmproxy: 3.0.0dev0989 (62561ed)
Python:    3.5.2
OpenSSL:   OpenSSL 1.0.2g  1 Mar 2016
Platform:  Linux-4.4.0-43-Microsoft-x86_64-with-Ubuntu-16.04-xenial
Flowlist: Focus jumps to bottom of list when deleting flow
##### Steps to reproduce the problem:

1. Create a flow in mitmproxy, duplicate it ten times.
2. Delete flow number 5.
3. Cursor jumps to the last flow, instead to what previously was flow 6.

##### System information

Mitmproxy: 3.0.0dev0989 (62561ed)
Python:    3.5.2
OpenSSL:   OpenSSL 1.0.2g  1 Mar 2016
Platform:  Linux-4.4.0-43-Microsoft-x86_64-with-Ubuntu-16.04-xenial


Discussion:

Resolving patch:
diff --git a/mitmproxy/addons/view.py b/mitmproxy/addons/view.py
--- a/mitmproxy/addons/view.py
+++ b/mitmproxy/addons/view.py
@@ -406,8 +406,11 @@ def remove(self, flows: typing.Sequence[mitmproxy.flow.Flow]) -> None:
                 if f.killable:
                     f.kill()
                 if f in self._view:
+                    # We manually pass the index here because multiple flows may have the same
+                    # sorting key, and we cannot reconstruct the index from that.
+                    idx = self._view.index(f)
                     self._view.remove(f)
-                    self.sig_view_remove.send(self, flow=f)
+                    self.sig_view_remove.send(self, flow=f, index=idx)
                 del self._store[f.id]
                 self.sig_store_remove.send(self, flow=f)
         if len(flows) > 1:
@@ -507,11 +510,12 @@ def update(self, flows: typing.Sequence[mitmproxy.flow.Flow]) -> None:
                         self.sig_view_update.send(self, flow=f)
                 else:
                     try:
-                        self._view.remove(f)
-                        self.sig_view_remove.send(self, flow=f)
+                        idx = self._view.index(f)
                     except ValueError:
-                        # The value was not in the view
-                        pass
+                        pass  # The value was not in the view
+                    else:
+                        self._view.remove(f)
+                        self.sig_view_remove.send(self, flow=f, index=idx)
 
 
 class Focus:
@@ -554,11 +558,11 @@ def index(self, idx):
     def _nearest(self, f, v):
         return min(v._bisect(f), len(v) - 1)
 
-    def _sig_view_remove(self, view, flow):
+    def _sig_view_remove(self, view, flow, index):
         if len(view) == 0:
             self.flow = None
         elif flow is self.flow:
-            self.flow = view[self._nearest(self.flow, view)]
+            self.index = min(index, len(self.view) - 1)
 
     def _sig_view_refresh(self, view):
         if len(view) == 0:
diff --git a/mitmproxy/tools/web/master.py b/mitmproxy/tools/web/master.py
--- a/mitmproxy/tools/web/master.py
+++ b/mitmproxy/tools/web/master.py
@@ -60,7 +60,7 @@ def _sig_view_update(self, view, flow):
             data=app.flow_to_json(flow)
         )
 
-    def _sig_view_remove(self, view, flow):
+    def _sig_view_remove(self, view, flow, index):
         app.ClientConnection.broadcast(
             resource="flows",
             cmd="remove",


Test patch: