From 5ab3288350d671c5e2fc2d3c4c6767b26d2b2c8d Mon Sep 17 00:00:00 2001 From: Pau Date: Tue, 13 May 2025 21:10:23 +0200 Subject: [PATCH] Refactored main, added comments and bottom nav animations --- .../java/com/example/acloc/MainActivity.java | 313 +++++++++++++----- app/src/main/res/anim/slide_in_left.xml | 11 + app/src/main/res/anim/slide_in_right.xml | 11 + app/src/main/res/anim/slide_out_left.xml | 11 + app/src/main/res/anim/slide_out_right.xml | 11 + 5 files changed, 269 insertions(+), 88 deletions(-) create mode 100644 app/src/main/res/anim/slide_in_left.xml create mode 100644 app/src/main/res/anim/slide_in_right.xml create mode 100644 app/src/main/res/anim/slide_out_left.xml create mode 100644 app/src/main/res/anim/slide_out_right.xml diff --git a/app/src/main/java/com/example/acloc/MainActivity.java b/app/src/main/java/com/example/acloc/MainActivity.java index d7edf67..fcf65b2 100644 --- a/app/src/main/java/com/example/acloc/MainActivity.java +++ b/app/src/main/java/com/example/acloc/MainActivity.java @@ -19,7 +19,7 @@ import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; -import com.example.acloc.activities.ManageRolesActivity; +import com.example.acloc.activity.ManageRolesActivity; import com.example.acloc.api.ApiClient; import com.example.acloc.dialog.AlertChangePasswordDialog; import com.example.acloc.dialog.AlertViewOrUpdateProfileDialog; @@ -34,6 +34,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.ieslamar.acloc.R; import java.util.Locale; @@ -43,43 +44,74 @@ import retrofit2.Response; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); + + // UI Components private RelativeLayout rlMainActivity; private BottomNavigationView bottomNavigationView; private Toolbar toolbar; + + // Variables private Dialog dialog; private Context context; + private Fragment currentFragment; + + // Animation constants + private static final int ANIM_ENTER_RIGHT = R.anim.slide_in_right; + private static final int ANIM_EXIT_LEFT = R.anim.slide_out_left; + private static final int ANIM_ENTER_LEFT = R.anim.slide_in_left; + private static final int ANIM_EXIT_RIGHT = R.anim.slide_out_right; + private static final int ANIM_FADE_IN = android.R.anim.fade_in; + private static final int ANIM_FADE_OUT = android.R.anim.fade_out; @Override protected void onCreate(Bundle savedInstanceState) { - // Get saved language from SharedPreferences - String savedLanguage = SharedPref.getLanguage(this); - - // Check if current language matches saved - if (!Locale.getDefault().getLanguage().equals(savedLanguage)) { - setLocale(savedLanguage); // Apply only if needed - } - + applyLanguageSettings(); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + initToolbar(); initUI(); initObj(); initListeners(); + // Load default fragment loadDefaultFragment(savedInstanceState); - getRoleUuids(); + fetchRoleUuids(); } + /** + * Apply language settings from SharedPreferences + */ + private void applyLanguageSettings() { + String savedLanguage = SharedPref.getLanguage(this); + if (!Locale.getDefault().getLanguage().equals(savedLanguage)) { + setLocale(savedLanguage); + } + } + + /** + * Initialize toolbar + */ private void initToolbar() { toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); } + /** + * Initialize UI components + */ private void initUI() { rlMainActivity = findViewById(R.id.rlMainActivity); bottomNavigationView = findViewById(R.id.bottomNavView); } + /** + * Initialize objects + */ + private void initObj() { + context = this; + } + @SuppressLint("RestrictedApi") @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -89,11 +121,10 @@ public class MainActivity extends AppCompatActivity { m.setOptionalIconsVisible(true); } - // show/hide the "Manage Roles" menu item - MenuItem manageNotesItem = menu.findItem(R.id.menu_manageRoles); - if (!"admin".equalsIgnoreCase(SharedPref.getRole(context))) { - manageNotesItem.setVisible(false); // hide for non-admins - } + // Show/hide the "Manage Roles" menu item based on user role + MenuItem manageRolesItem = menu.findItem(R.id.menu_manageRoles); + boolean isAdmin = "admin".equalsIgnoreCase(SharedPref.getRole(context)); + manageRolesItem.setVisible(isAdmin); return true; } @@ -103,24 +134,29 @@ public class MainActivity extends AppCompatActivity { int id = item.getItemId(); if (id == R.id.menu_profile) { - dialog = new AlertViewOrUpdateProfileDialog(context) - .openProfileDialog(); + dialog = new AlertViewOrUpdateProfileDialog(context).openProfileDialog(); return true; } else if (id == R.id.menu_changePassword) { - dialog = new AlertChangePasswordDialog(context) - .openChangePasswordDialog(); + dialog = new AlertChangePasswordDialog(context).openChangePasswordDialog(); + return true; } else if (id == R.id.menu_changeLanguage) { - changeLanguage(); + showLanguageChangeDialog(); + return true; } else if (id == R.id.menu_manageRoles) { Helper.goTo(MainActivity.this, ManageRolesActivity.class); + return true; } else if (id == R.id.menu_logout) { - AlertDialog dialog = DialogUtils.logoutDialog(context); - dialog.show(); + DialogUtils.logoutDialog(context).show(); + return true; } + return super.onOptionsItemSelected(item); } - private void changeLanguage() { + /** + * Show dialog to confirm language change + */ + private void showLanguageChangeDialog() { String currentLanguage = Locale.getDefault().getLanguage(); String newLanguage = currentLanguage.equals("es") ? "en" : "es"; @@ -128,20 +164,28 @@ public class MainActivity extends AppCompatActivity { this, getString(R.string.change_language_confirmation), (dialogInterface, i) -> { - SharedPref.setLanguage(this, newLanguage); // Save to SharedPref - setLocale(newLanguage); // Apply language - - // Restart app to apply change - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - finish(); + SharedPref.setLanguage(this, newLanguage); + setLocale(newLanguage); + restartApp(); } ); dialog.show(); } - // Method to update the language dynamically + /** + * Restart app to apply language changes + */ + private void restartApp() { + Intent intent = new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); + } + + /** + * Set app locale + * @param lang Language code (e.g., "en", "es") + */ private void setLocale(String lang) { Locale locale = new Locale(lang); Locale.setDefault(locale); @@ -149,51 +193,127 @@ public class MainActivity extends AppCompatActivity { Configuration config = new Configuration(); config.setLocale(locale); - getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); - } - - private void initObj() { - context = this; + getBaseContext().getResources().updateConfiguration( + config, + getBaseContext().getResources().getDisplayMetrics() + ); } + /** + * Initialize listeners for UI components + */ private void initListeners() { - // Set item selected listener for bottom navigation - bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { - @Override - public boolean onNavigationItemSelected(@NonNull MenuItem item) { - Fragment selectedFragment = null; - String title = ""; + bottomNavigationView.setOnNavigationItemSelectedListener(item -> { + Fragment selectedFragment = null; + String title = ""; + int id = item.getItemId(); - int id = item.getItemId(); - if (id == R.id.menu_myReports) { - selectedFragment = new MyReportsFragment(); - title = getString(R.string.My_Report); - } else if (id == R.id.menu_map) { - selectedFragment = new MapFragment(); - title = getString(R.string.Map); - } else if (id == R.id.menu_favorite) { - selectedFragment = new FavoriteFragment(); - title = getString(R.string.Favorite); - } - - if (selectedFragment != null) { - loadFragment(selectedFragment, title); - } - return true; + if (id == R.id.menu_myReports) { + selectedFragment = new MyReportsFragment(); + title = getString(R.string.My_Report); + } else if (id == R.id.menu_map) { + selectedFragment = new MapFragment(); + title = getString(R.string.Map); + } else if (id == R.id.menu_favorite) { + selectedFragment = new FavoriteFragment(); + title = getString(R.string.Favorite); } + + if (selectedFragment != null) { + loadFragmentWithAnimation(selectedFragment, title, getAnimationDirection(selectedFragment)); + } + return true; }); } + /** + * Determine animation direction based on fragment navigation + * @param newFragment The fragment being navigated to + * @return Array of animation resource IDs [enter, exit] + */ + private int[] getAnimationDirection(Fragment newFragment) { + if (currentFragment == null) { + return new int[]{ANIM_FADE_IN, ANIM_FADE_OUT}; + } + + // Determine navigation direction based on fragment types + boolean goingRight = isNavigatingRight(currentFragment, newFragment); + + if (goingRight) { + return new int[]{ANIM_ENTER_RIGHT, ANIM_EXIT_LEFT}; + } else { + return new int[]{ANIM_ENTER_LEFT, ANIM_EXIT_RIGHT}; + } + } + + /** + * Determine if navigation is going right in the bottom nav + * @param current Current fragment + * @param next Fragment being navigated to + * @return true if navigating right, false if navigating left + */ + private boolean isNavigatingRight(Fragment current, Fragment next) { + // Get position in navigation order + int currentPos = getFragmentPosition(current); + int nextPos = getFragmentPosition(next); + + return nextPos > currentPos; + } + + /** + * Get fragment position in navigation order + * @param fragment Fragment to check + * @return Position index (0 for MyReports, 1 for Map, 2 for Favorites) + */ + private int getFragmentPosition(Fragment fragment) { + if (fragment instanceof MyReportsFragment) return 0; + if (fragment instanceof MapFragment) return 1; + if (fragment instanceof FavoriteFragment) return 2; + return 1; // Default to middle position + } + + /** + * Load fragment with animation + * @param fragment Fragment to load + * @param title Title to display in toolbar + * @param animations Array of animation resource IDs [enter, exit] + */ + private void loadFragmentWithAnimation(Fragment fragment, String title, int[] animations) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.setCustomAnimations( + animations[0], animations[1] + ); + transaction.replace(R.id.flMainContainer, fragment); + transaction.commit(); + + if (getSupportActionBar() != null) { + getSupportActionBar().setTitle(title); + } + + currentFragment = fragment; + } + + /** + * Load fragment without animation + * @param fragment Fragment to load + * @param title Title to display in toolbar + */ private void loadFragment(Fragment fragment, String title) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.flMainContainer, fragment); transaction.commit(); if (getSupportActionBar() != null) { - getSupportActionBar().setTitle(title); // Correct way to set title with support action bar + getSupportActionBar().setTitle(title); } + + currentFragment = fragment; } + /** + * Load default fragment if no saved instance state + * @param savedInstanceState Saved instance state + */ private void loadDefaultFragment(Bundle savedInstanceState) { if (savedInstanceState == null) { Fragment defaultFragment = new MapFragment(); @@ -201,18 +321,26 @@ public class MainActivity extends AppCompatActivity { loadFragment(defaultFragment, defaultTitle); bottomNavigationView.setSelectedItemId(R.id.menu_map); + currentFragment = defaultFragment; } } - // to change the fragment + /** + * Open fragment from child component + * @param fragment Fragment to open + * @param title Title to display + * @param navItemId Navigation item ID to select + */ public void openFragmentFromChild(Fragment fragment, String title, int navItemId) { - Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.flMainContainer); - if (currentFragment != null && currentFragment.getClass().equals(fragment.getClass())) { + Fragment currentFrag = getSupportFragmentManager().findFragmentById(R.id.flMainContainer); + if (currentFrag != null && currentFrag.getClass().equals(fragment.getClass())) { return; } + int[] animations = getAnimationDirection(fragment); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); + transaction.setCustomAnimations(animations[0], animations[1]); transaction.replace(R.id.flMainContainer, fragment); transaction.commit(); @@ -221,9 +349,13 @@ public class MainActivity extends AppCompatActivity { } bottomNavigationView.setSelectedItemId(navItemId); + currentFragment = fragment; } - private void getRoleUuids() { + /** + * Fetch role UUIDs from API + */ + private void fetchRoleUuids() { DialogUtils.showLoadingDialog(context, ""); String token = "Bearer " + SharedPref.getAccessToken(context); @@ -235,28 +367,7 @@ public class MainActivity extends AppCompatActivity { public void onResponse(Call call, Response response) { DialogUtils.dismissDialog(); if (response.isSuccessful() && response.body() != null) { - JsonObject responseBody = response.body(); - JsonObject data = responseBody.getAsJsonObject("_data"); - - if (data != null && data.has("role")) { - JsonArray rolesArray = data.getAsJsonArray("role"); - - for (JsonElement element : rolesArray) { - JsonObject roleObj = element.getAsJsonObject(); - String roleName = roleObj.get("name").getAsString(); - String roleUuid = roleObj.get("uuid").getAsString(); - - if ("admin".equalsIgnoreCase(roleName)) { - SharedPref.setAdminRoleUuid(context, roleUuid); - } else if ("viewer".equalsIgnoreCase(roleName)) { - SharedPref.setViewerRoleUuid(context, roleUuid); - } - } - Log.d(TAG, "Admin UUID: " + SharedPref.getAdminRoleUuid(context)); - Log.d(TAG, "Viewer UUID: " + SharedPref.getViewerRoleUuid(context)); - } else { - Log.d(TAG, "No roles found."); - } + processRolesResponse(response.body()); } else { Log.d(TAG, "Failed to load roles. Try again."); } @@ -266,10 +377,36 @@ public class MainActivity extends AppCompatActivity { public void onFailure(Call call, Throwable t) { DialogUtils.dismissDialog(); Log.e(TAG, "Get Roles Failure: ", t); -// Helper.makeSnackBar(rlMainActivity, context.getString(R.string.Network_error_Try_again)); + // Helper.makeSnackBar(rlMainActivity, context.getString(R.string.Network_error_Try_again)); } }); } + /** + * Process roles response from API + * @param responseBody JSON response body + */ + private void processRolesResponse(JsonObject responseBody) { + JsonObject data = responseBody.getAsJsonObject("_data"); + if (data != null && data.has("role")) { + JsonArray rolesArray = data.getAsJsonArray("role"); + + for (JsonElement element : rolesArray) { + JsonObject roleObj = element.getAsJsonObject(); + String roleName = roleObj.get("name").getAsString(); + String roleUuid = roleObj.get("uuid").getAsString(); + + if ("admin".equalsIgnoreCase(roleName)) { + SharedPref.setAdminRoleUuid(context, roleUuid); + } else if ("viewer".equalsIgnoreCase(roleName)) { + SharedPref.setViewerRoleUuid(context, roleUuid); + } + } + Log.d(TAG, "Admin UUID: " + SharedPref.getAdminRoleUuid(context)); + Log.d(TAG, "Viewer UUID: " + SharedPref.getViewerRoleUuid(context)); + } else { + Log.d(TAG, "No roles found."); + } + } } \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_left.xml b/app/src/main/res/anim/slide_in_left.xml new file mode 100644 index 0000000..07d168b --- /dev/null +++ b/app/src/main/res/anim/slide_in_left.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml new file mode 100644 index 0000000..bf44111 --- /dev/null +++ b/app/src/main/res/anim/slide_in_right.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml new file mode 100644 index 0000000..c8baf6f --- /dev/null +++ b/app/src/main/res/anim/slide_out_left.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_right.xml b/app/src/main/res/anim/slide_out_right.xml new file mode 100644 index 0000000..9448105 --- /dev/null +++ b/app/src/main/res/anim/slide_out_right.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file