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"> + + + + +