diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/MainActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/MainActivity.java
index 5b5d039b..ee346edd 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/activities/MainActivity.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/activities/MainActivity.java
@@ -511,6 +511,26 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
new TabLayoutMediator(findViewById(R.id.tablayout), mPager, (tab, position) ->
tab.setText(getString(stateAdapter.getPageTitle(position)))
).attach();
+
+ View switchButton = findViewById(R.id.tab_switch_button);
+ if (switchButton != null) {
+ switchButton.setOnClickListener(v -> {
+ if (mPager.getCurrentItem() != POS_CONNECTIONS) {
+ // Switch to Connections tab first, then toggle after fragment is created
+ mPager.setCurrentItem(POS_CONNECTIONS);
+ mPager.post(this::toggleDataView);
+ } else {
+ toggleDataView();
+ }
+ });
+ }
+ }
+
+ private void toggleDataView() {
+ Fragment container = getFragmentAtPos(POS_CONNECTIONS);
+ if (container instanceof DataViewContainerFragment) {
+ ((DataViewContainerFragment) container).toggleView();
+ }
}
@Override
@@ -625,6 +645,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public void appStateReady() {
mState = AppState.ready;
notifyAppState();
+ updateTabSwitchButton();
if(mPcapLoadDialog != null)
checkLoadedPcap();
@@ -638,6 +659,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public void appStateRunning() {
mState = AppState.running;
notifyAppState();
+ updateTabSwitchButton();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
checkVpnLockdownNotice();
@@ -658,6 +680,14 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
notifyAppState();
}
+ private void updateTabSwitchButton() {
+ View switchButton = findViewById(R.id.tab_switch_button);
+ if (switchButton != null) {
+ boolean httpLogAvailable = (CaptureService.getHttpLog() != null);
+ switchButton.setVisibility(httpLogAvailable ? android.view.View.VISIBLE : android.view.View.GONE);
+ }
+ }
+
private void checkDecryptionRulesNotice() {
if(!mDecEmptyRulesNoticeShown && PCAPdroid.getInstance().getDecryptionList().isEmpty()) {
new AlertDialog.Builder(this)
diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/DataViewContainerFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/DataViewContainerFragment.java
index d57cad9b..0a403b34 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/fragments/DataViewContainerFragment.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/DataViewContainerFragment.java
@@ -143,38 +143,24 @@ public class DataViewContainerFragment extends Fragment implements MenuProvider
if (mConnectionsFragment instanceof ConnectionsFragment) {
((ConnectionsFragment) mConnectionsFragment).onCreateMenu(menu, menuInflater);
}
-
- if (CaptureService.getHttpLog() != null)
- menu.add(Menu.NONE, R.id.switch_to_http_log, 25, R.string.switch_to_http)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
} else if ((mCurrentView == VIEW_HTTP_LOG) && (mHttpLogFragment != null)) {
if (mHttpLogFragment instanceof HttpLogFragment) {
((HttpLogFragment) mHttpLogFragment).onCreateMenu(menu, menuInflater);
}
- menu.add(Menu.NONE, R.id.switch_to_connections, 25, R.string.switch_to_connections)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
}
+
+ updateTabTitle();
}
@Override
public boolean onMenuItemSelected(@NonNull MenuItem item) {
- int id = item.getItemId();
-
- if (id == R.id.switch_to_http_log) {
- switchToView(VIEW_HTTP_LOG);
- return true;
- } else if (id == R.id.switch_to_connections) {
- switchToView(VIEW_CONNECTIONS);
- return true;
- }
-
- if (mCurrentView == VIEW_CONNECTIONS && mConnectionsFragment != null) {
+ if ((mCurrentView == VIEW_CONNECTIONS) && (mConnectionsFragment != null)) {
if (mConnectionsFragment instanceof ConnectionsFragment) {
if (((ConnectionsFragment) mConnectionsFragment).onMenuItemSelected(item)) {
return true;
}
}
- } else if (mCurrentView == VIEW_HTTP_LOG && mHttpLogFragment != null) {
+ } else if ((mCurrentView == VIEW_HTTP_LOG) && (mHttpLogFragment != null)) {
if (mHttpLogFragment instanceof HttpLogFragment) {
if (((HttpLogFragment) mHttpLogFragment).onMenuItemSelected(item)) {
return true;
@@ -185,6 +171,12 @@ public class DataViewContainerFragment extends Fragment implements MenuProvider
return false;
}
+ public void toggleView() {
+ int targetView = (mCurrentView == VIEW_CONNECTIONS) ?
+ VIEW_HTTP_LOG : VIEW_CONNECTIONS;
+ switchToView(targetView);
+ }
+
private void switchToView(int targetView) {
if (mCurrentView == targetView) {
return;
@@ -221,6 +213,13 @@ public class DataViewContainerFragment extends Fragment implements MenuProvider
tab.setText(getString(titleRes));
}
}
+
+ View switchButton = activity.findViewById(R.id.tab_switch_button);
+ if (switchButton != null) {
+ int contentDescRes = (mCurrentView == VIEW_CONNECTIONS) ?
+ R.string.switch_to_http : R.string.switch_to_connections;
+ switchButton.setContentDescription(getString(contentDescRes));
+ }
}
public boolean onBackPressed() {
diff --git a/app/src/main/res/drawable/ic_swap_horiz.xml b/app/src/main/res/drawable/ic_swap_horiz.xml
new file mode 100644
index 00000000..a976771b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_swap_horiz.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/tab_switch_button_background.xml b/app/src/main/res/drawable/tab_switch_button_background.xml
new file mode 100644
index 00000000..f95ff869
--- /dev/null
+++ b/app/src/main/res/drawable/tab_switch_button_background.xml
@@ -0,0 +1,9 @@
+
+
+ -
+
+
+
+
+
diff --git a/app/src/main/res/layout/tabs_activity.xml b/app/src/main/res/layout/tabs_activity.xml
index 51d67c54..22a51d83 100644
--- a/app/src/main/res/layout/tabs_activity.xml
+++ b/app/src/main/res/layout/tabs_activity.xml
@@ -25,15 +25,35 @@
android:layout_height="match_parent"
android:orientation="vertical">
-
+ android:orientation="horizontal">
+
+
+
+
+