package com.sunilpaulmathew.debloater.fragments; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.Menu; import android.view.SubMenu; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import androidx.activity.OnBackPressedCallback; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatEditText; import androidx.appcompat.widget.AppCompatImageButton; import androidx.appcompat.widget.AppCompatTextView; import androidx.appcompat.widget.PopupMenu; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.card.MaterialCardView; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.tabs.TabLayout; import com.google.android.material.textview.MaterialTextView; import com.sunilpaulmathew.debloater.R; import com.sunilpaulmathew.debloater.activities.TomatotActivity; import com.sunilpaulmathew.debloater.activities.UADActivity; import com.sunilpaulmathew.debloater.adapters.ActivePackagesAdapter; import com.sunilpaulmathew.debloater.utils.PackageTasks; import com.sunilpaulmathew.debloater.utils.UpdateCheck; import com.sunilpaulmathew.debloater.utils.Utils; import java.util.Objects; import in.sunilpaulmathew.sCommon.CommonUtils.sCommonUtils; import in.sunilpaulmathew.sCommon.CommonUtils.sExecutor; /* * Created by sunilpaulmathew on October 28, 2020 */ public class ActivePackagesFragment extends Fragment { private AppCompatEditText mSearchWord; private AppCompatImageButton mMenu; private boolean mExit = false; private final Handler mHandler = new Handler(); private LinearLayout mProgressLayout; private MaterialCardView mReverse; private RecyclerView mRecyclerView; private ActivePackagesAdapter mRecycleViewAdapter; private String mSearchText = null; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View mRootView = inflater.inflate(R.layout.fragment_packages, container, false); mSearchWord = mRootView.findViewById(R.id.search_word); AppCompatImageButton mSearchButton = mRootView.findViewById(R.id.search_button); AppCompatTextView mSummary = mRootView.findViewById(R.id.about_summary); MaterialTextView mPageTitle = mRootView.findViewById(R.id.page_title); mReverse = mRootView.findViewById(R.id.reverse_button); mMenu = mRootView.findViewById(R.id.menu_button); mProgressLayout = mRootView.findViewById(R.id.progress_layout); mRecyclerView = mRootView.findViewById(R.id.recycler_view); TabLayout mTabLayout = mRootView.findViewById(R.id.tab_layout); mRecyclerView.setLayoutManager(new LinearLayoutManager(requireActivity())); mPageTitle.setText(getString(R.string.apps, getString(R.string.active))); mSummary.setText(getString(R.string.active_app_summary)); mReverse.setElevation(10); mReverse.setOnClickListener(v -> { sCommonUtils.saveBoolean("reverse_order", !sCommonUtils.getBoolean("reverse_order", false, requireActivity()), requireActivity()); loadUI(requireActivity(), mSearchText); }); mSearchButton.setOnClickListener(v -> { if (mSearchWord.getVisibility() == View.VISIBLE) { if (mSearchText != null && !mSearchText.isEmpty()) { mSearchText = null; mSearchWord.setText(null); } mSummary.setVisibility(View.VISIBLE); mSearchWord.setVisibility(View.GONE); PackageTasks.toggleKeyboard(mSearchWord, 0, requireActivity()); } else { mSummary.setVisibility(View.GONE); mSearchWord.setVisibility(View.VISIBLE); PackageTasks.toggleKeyboard(mSearchWord, 1, requireActivity()); } }); mTabLayout.addTab(mTabLayout.newTab().setText(getString(R.string.apps_all))); mTabLayout.addTab(mTabLayout.newTab().setText(getString(R.string.apps_system))); mTabLayout.addTab(mTabLayout.newTab().setText(getString(R.string.apps_product))); mTabLayout.addTab(mTabLayout.newTab().setText(getString(R.string.apps_vendor))); mTabLayout.setVisibility(View.VISIBLE); Objects.requireNonNull(mTabLayout.getTabAt(getTabPosition(requireActivity()))).select(); mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { String mStatus = sCommonUtils.getString("appTypes", "all", requireActivity()); switch (tab.getPosition()) { case 0: if (!mStatus.equals("all")) { sCommonUtils.saveString("appTypes", "all", requireActivity()); loadUI(requireActivity(), mSearchText); } break; case 1: if (!mStatus.equals("system")) { sCommonUtils.saveString("appTypes", "system", requireActivity()); loadUI(requireActivity(), mSearchText); } break; case 2: if (!mStatus.equals("product")) { sCommonUtils.saveString("appTypes", "product", requireActivity()); loadUI(requireActivity(), mSearchText); } break; case 3: if (!mStatus.equals("vendor")) { sCommonUtils.saveString("appTypes", "vendor", requireActivity()); loadUI(requireActivity(), mSearchText); } break; } } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); mSearchWord.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { loadUI(requireActivity(), s.toString().toLowerCase()); } }); mMenu.setOnClickListener(v -> menuOptions(requireActivity())); loadUI(requireActivity(), mSearchText); if (UpdateCheck.isSignatureMatched(requireActivity()) && sCommonUtils.getInt("update_enabled", 2, requireActivity()) == 2) { new MaterialAlertDialogBuilder(requireActivity()) .setIcon(R.mipmap.ic_launcher_round) .setTitle("Please Note") .setMessage(""" De-Bloater includes a built-in auto-update system that is active only when the app is installed via the GitHub release page or through IzzyOnDroid. Updates are fetched directly from the latest official release on GitHub. You can choose to enable or disable this feature. This prompt will keep appearing until you make a decision.""") .setCancelable(false) .setNeutralButton("No, Thanks", (dialogInterface, i) -> sCommonUtils.saveInt("update_enabled", 1, requireActivity())) .setPositiveButton("Yes, Enable", (dialogInterface, i) -> sCommonUtils.saveInt("update_enabled", 0, requireActivity())) .show(); } requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { if (mSearchWord.getVisibility() == View.VISIBLE) { if (mSearchText != null) { mSearchText = null; mSearchWord.setText(null); } mSearchWord.setVisibility(View.GONE); return; } if (mExit) { mExit = false; requireActivity().finish(); } else { sCommonUtils.toast(getString(R.string.press_back_exit), requireActivity()).show(); mExit = true; mHandler.postDelayed(() -> mExit = false, 2000); } } }); return mRootView; } private int getTabPosition(Activity activity) { String mStatus = sCommonUtils.getString("appTypes", "all", activity); return switch (mStatus) { case "vendor" -> 3; case "product" -> 2; case "system" -> 1; default -> 0; }; } private void menuOptions(Activity activity) { PopupMenu popupMenu = new PopupMenu(activity, mMenu); Menu menu = popupMenu.getMenu(); if (PackageTasks.isModuleInitialized()) { menu.add(Menu.NONE, 1, Menu.NONE, R.string.module_status_reset); } SubMenu sort = menu.addSubMenu(Menu.NONE, 0, Menu.NONE, getString(R.string.sort_by)); sort.add(0, 2, Menu.NONE, getString(R.string.name)).setCheckable(true) .setChecked(sCommonUtils.getInt("sort_apps", 1, activity) == 0); sort.add(0, 3, Menu.NONE, getString(R.string.package_id)).setCheckable(true) .setChecked(sCommonUtils.getInt("sort_apps", 1, activity) == 1); sort.setGroupCheckable(0, true, true); SubMenu customScripts = menu.addSubMenu(Menu.NONE, 0, Menu.NONE, getString(R.string.custom_scripts)); customScripts.add(Menu.NONE, 4, Menu.NONE, R.string.custom_scripts_tomatot); customScripts.add(Menu.NONE, 5, Menu.NONE, R.string.custom_scripts_uad); menu.add(Menu.NONE, 6, Menu.NONE, R.string.reboot); popupMenu.setOnMenuItemClickListener(item -> { switch (item.getItemId()) { case 0: break; case 1: PackageTasks.removeModule(activity); break; case 2: if (sCommonUtils.getInt("sort_apps", 1, activity) != 0) { sCommonUtils.saveInt("sort_apps", 0, activity); loadUI(activity, mSearchText); } break; case 3: if (sCommonUtils.getInt("sort_apps", 1, activity) != 1) { sCommonUtils.saveInt("sort_apps", 1, activity); loadUI(activity, mSearchText); } break; case 4: Intent tomatotScript = new Intent(activity, TomatotActivity.class); startActivity(tomatotScript); break; case 5: Intent uadScript = new Intent(activity, UADActivity.class); startActivity(uadScript); break; case 6: Utils.runCommand("svc power reboot"); break; } return false; }); popupMenu.show(); } private void loadUI(Activity activity, String searchText) { new sExecutor() { @Override public void onPreExecute() { mProgressLayout.setVisibility(View.VISIBLE); mReverse.setVisibility(View.GONE); mRecyclerView.setVisibility(View.GONE); mRecyclerView.removeAllViews(); } @Override public void doInBackground() { mRecycleViewAdapter = new ActivePackagesAdapter(PackageTasks.getActivePackageData(activity, searchText), searchText); if (searchText != null) { mSearchText = searchText; } } @Override public void onPostExecute() { mRecyclerView.setAdapter(mRecycleViewAdapter); mProgressLayout.setVisibility(View.GONE); mRecyclerView.setVisibility(View.VISIBLE); mReverse.setVisibility(View.VISIBLE); } }.execute(); } @Override public void onStart() { super.onStart(); if (mSearchText != null) { mSearchText = null; mSearchWord.setText(null); } } @Override public void onDestroy() { super.onDestroy(); if (mSearchText != null) { mSearchText = null; mSearchWord.setText(null); } } }