Merge pull request #2890 from TeamAmaze/bugfix/3.6.4

Bugfix/3.6.4 fix android tv overscan
This commit is contained in:
Vishal Nehra
2021-10-11 05:14:58 +05:30
committed by GitHub
14 changed files with 228 additions and 100 deletions
@@ -36,6 +36,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import android.widget.Toast
import androidx.annotation.IntDef
import androidx.appcompat.view.ContextThemeWrapper
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
@@ -45,6 +46,8 @@ import com.amaze.filemanager.R
import com.amaze.filemanager.adapters.data.AppDataParcelable
import com.amaze.filemanager.adapters.glide.AppsAdapterPreloadModel
import com.amaze.filemanager.adapters.holders.AppHolder
import com.amaze.filemanager.adapters.holders.EmptyViewHolder
import com.amaze.filemanager.adapters.holders.SpecialViewHolder
import com.amaze.filemanager.asynchronous.asynctasks.DeleteTask
import com.amaze.filemanager.asynchronous.management.ServiceWatcherUtil
import com.amaze.filemanager.asynchronous.services.CopyService
@@ -66,6 +69,8 @@ import com.amaze.filemanager.utils.Utils
import com.amaze.filemanager.utils.safeLet
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.roundToInt
class AppsRecyclerAdapter(
private val fragment: Fragment,
@@ -74,59 +79,128 @@ class AppsRecyclerAdapter(
private val adjustListViewCallback: AdjustListViewForTv<AppHolder>,
private val appDataParcelableList: MutableList<AppDataParcelable>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val myChecked = SparseBooleanArray()
private var appDataListItem: MutableList<ListItem> = mutableListOf()
set(value) {
value.clear()
val headerFlags = BooleanArray(2)
appDataParcelableList.forEach {
if (!isBottomSheet && it.isSystemApp && !headerFlags[0]) {
value.add(ListItem(TYPE_HEADER_SYSTEM))
modelProvider.addItem("")
headerFlags[0] = true
} else if (!isBottomSheet && !it.isSystemApp && !headerFlags[1]) {
value.add(ListItem(TYPE_HEADER_THIRD_PARTY))
modelProvider.addItem("")
headerFlags[1] = true
}
modelProvider.addItem(it.path)
value.add(ListItem(it))
}
if (!isBottomSheet) {
modelProvider.addItem("")
value.add(ListItem(EMPTY_LAST_ITEM))
}
field = value
}
init {
appDataListItem = mutableListOf()
}
private val mInflater: LayoutInflater get() = fragment.requireActivity()
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE) as LayoutInflater
companion object {
const val TYPE_ITEM = 0
const val TYPE_HEADER_SYSTEM = 1
const val TYPE_HEADER_THIRD_PARTY = 2
const val EMPTY_LAST_ITEM = 3
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = mInflater.inflate(R.layout.rowlayout, parent, false)
return AppHolder(view)
var view = View(fragment.requireContext())
when (viewType) {
TYPE_ITEM -> {
view = mInflater.inflate(R.layout.rowlayout, parent, false)
return AppHolder(view)
}
TYPE_HEADER_SYSTEM, TYPE_HEADER_THIRD_PARTY -> {
view = mInflater.inflate(R.layout.list_header, parent, false)
return SpecialViewHolder(
fragment.requireContext(), view,
(fragment.requireActivity() as MainActivity).utilsProvider,
if (viewType == TYPE_HEADER_SYSTEM)
SpecialViewHolder.HEADER_SYSTEM_APP
else
SpecialViewHolder.HEADER_THIRD_PARTY_APP
)
}
EMPTY_LAST_ITEM -> {
view.minimumHeight =
(
fragment.requireActivity().resources.getDimension(R.dimen.fab_height) +
fragment.requireContext().resources
.getDimension(R.dimen.fab_margin)
).roundToInt()
return EmptyViewHolder(view)
}
else -> {
throw IllegalStateException("Illegal $viewType in apps adapter")
}
}
}
override fun getItemViewType(position: Int): Int {
return appDataListItem[position].listItemType
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is AppHolder) {
val rowItem: AppDataParcelable = appDataParcelableList[position]
if (isBottomSheet) {
holder.about.visibility = View.GONE
holder.txtDesc.text = rowItem.openFileParcelable?.className
holder.txtDesc.isSingleLine = true
holder.txtDesc.ellipsize = TextUtils.TruncateAt.MIDDLE
modelProvider.loadApkImage(rowItem.packageName, holder.apkIcon)
} else {
modelProvider.loadApkImage(rowItem.path, holder.apkIcon)
}
if (holder.about != null && !isBottomSheet) {
if ((fragment.requireActivity() as MainActivity).appTheme == AppTheme.LIGHT) {
holder.about.setColorFilter(
Color.parseColor("#ff666666")
appDataListItem[position].appDataParcelable?.let { rowItem ->
if (isBottomSheet) {
holder.about.visibility = View.GONE
holder.txtDesc.text = rowItem.openFileParcelable?.className
holder.txtDesc.isSingleLine = true
holder.txtDesc.ellipsize = TextUtils.TruncateAt.MIDDLE
modelProvider.loadApkImage(rowItem.packageName, holder.apkIcon)
} else {
modelProvider.loadApkImage(rowItem.path, holder.apkIcon)
}
if (holder.about != null && !isBottomSheet) {
if ((fragment.requireActivity() as MainActivity).appTheme == AppTheme.LIGHT) {
holder.about.setColorFilter(
Color.parseColor("#ff666666")
)
}
showPopup(holder.about, rowItem)
}
holder.rl.setOnFocusChangeListener { _, _ ->
adjustListViewCallback.adjustListViewForTv(
holder,
fragment.requireActivity() as MainActivity
)
}
showPopup(holder.about, rowItem)
}
holder.rl.setOnFocusChangeListener { _, _ ->
adjustListViewCallback.adjustListViewForTv(
holder,
fragment.requireActivity() as MainActivity
)
}
holder.txtTitle.text = rowItem.label
val enableMarqueeFilename =
(fragment.requireActivity() as MainActivity)
.getBoolean(PreferencesConstants.PREFERENCE_ENABLE_MARQUEE_FILENAME)
if (enableMarqueeFilename) {
holder.txtTitle.ellipsize = if (enableMarqueeFilename)
TextUtils.TruncateAt.MARQUEE else TextUtils.TruncateAt.MIDDLE
marqueeAfterDelay(2000, holder.txtTitle)
}
holder.txtTitle.text = rowItem.label
val enableMarqueeFilename =
(fragment.requireActivity() as MainActivity)
.getBoolean(PreferencesConstants.PREFERENCE_ENABLE_MARQUEE_FILENAME)
if (enableMarqueeFilename) {
holder.txtTitle.ellipsize = if (enableMarqueeFilename)
TextUtils.TruncateAt.MARQUEE else TextUtils.TruncateAt.MIDDLE
marqueeAfterDelay(2000, holder.txtTitle)
}
// File f = new File(rowItem.getDesc());
if (!isBottomSheet) {
holder.txtDesc.text = rowItem.fileSize
}
holder.rl.isClickable = true
holder.rl.nextFocusRightId = holder.about.id
holder.rl.setOnClickListener {
startActivityForRowItem(rowItem)
// File f = new File(rowItem.getDesc());
if (!isBottomSheet) {
holder.txtDesc.text = rowItem.fileSize
}
holder.rl.isClickable = true
holder.rl.nextFocusRightId = holder.about.id
holder.rl.setOnClickListener {
startActivityForRowItem(rowItem)
}
}
if (myChecked[position]) {
holder.rl.setBackgroundColor(
@@ -143,7 +217,7 @@ class AppsRecyclerAdapter(
}
override fun getItemCount(): Int {
return appDataParcelableList.size
return appDataListItem.size
}
/**
@@ -155,7 +229,7 @@ class AppsRecyclerAdapter(
clear()
val list = if (!showSystemApps) data.filter { !it.isSystemApp } else data
addAll(list)
modelProvider.setItemList(list.map { it.path })
appDataListItem = mutableListOf()
notifyDataSetChanged()
}
}
@@ -424,4 +498,20 @@ class AppsRecyclerAdapter(
.build()
.show()
}
@Target(AnnotationTarget.TYPE)
@IntDef(
TYPE_ITEM,
TYPE_HEADER_SYSTEM,
TYPE_HEADER_THIRD_PARTY,
EMPTY_LAST_ITEM,
)
annotation class ListItemType
data class ListItem(
var appDataParcelable: AppDataParcelable?,
var listItemType: @ListItemType Int = TYPE_ITEM
) {
constructor(listItemType: @ListItemType Int) : this(null, listItemType)
}
}
@@ -34,6 +34,10 @@ class AppDataSorter(var sort: Int, isAscending: Boolean) :
override fun compare(file1: AppDataParcelable?, file2: AppDataParcelable?): Int {
safeLet(file1, file2) {
f1, f2 ->
if (f1.isSystemApp != f2.isSystemApp) {
return if (f1.isSystemApp) -1 else 1
}
when (sort) {
SORT_NAME -> {
// sort by name
@@ -20,6 +20,7 @@
package com.amaze.filemanager.adapters.glide;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -58,6 +59,13 @@ public class AppsAdapterPreloadModel implements ListPreloader.PreloadModelProvid
this.items = items;
}
public void addItem(String item) {
if (items == null) {
items = new ArrayList<>();
}
items.add(item);
}
@NonNull
@Override
public List<String> getPreloadItems(int position) {
@@ -44,12 +44,16 @@ class SpecialViewHolder(
companion object {
const val HEADER_FILES = 0
const val HEADER_FOLDERS = 1
const val HEADER_SYSTEM_APP = 2
const val HEADER_THIRD_PARTY_APP = 3
}
init {
when (type) {
HEADER_FILES -> txtTitle.setText(R.string.files)
HEADER_FOLDERS -> txtTitle.setText(R.string.folders)
HEADER_SYSTEM_APP -> txtTitle.setText(R.string.system_apps)
HEADER_THIRD_PARTY_APP -> txtTitle.setText(R.string.third_party_apps)
else -> throw IllegalStateException(": $type")
}
@@ -36,7 +36,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.format.Formatter;
import androidx.core.util.Pair;
import androidx.loader.content.AsyncTaskLoader;
/**
@@ -44,11 +43,11 @@ import androidx.loader.content.AsyncTaskLoader;
*
* <p>Class loads all the packages installed
*/
public class AppListLoader extends AsyncTaskLoader<AppListLoader.AppsDataPair> {
public class AppListLoader extends AsyncTaskLoader<List<AppDataParcelable>> {
private PackageManager packageManager;
private PackageReceiver packageReceiver;
private AppsDataPair mApps;
private List<AppDataParcelable> mApps;
private final int sortBy;
private final boolean isAscending;
@@ -66,15 +65,14 @@ public class AppListLoader extends AsyncTaskLoader<AppListLoader.AppsDataPair> {
}
@Override
public AppsDataPair loadInBackground() {
public List<AppDataParcelable> loadInBackground() {
List<ApplicationInfo> apps =
packageManager.getInstalledApplications(
PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS);
if (apps == null) return new AppsDataPair(Collections.emptyList(), Collections.emptyList());
mApps = new AppsDataPair(new ArrayList<>(apps.size()), new ArrayList<>(apps.size()));
if (apps == null) return Collections.emptyList();
mApps = new ArrayList<>(apps.size());
PackageInfo androidInfo = null;
try {
androidInfo = packageManager.getPackageInfo("android", PackageManager.GET_SIGNATURES);
@@ -110,27 +108,22 @@ public class AppListLoader extends AsyncTaskLoader<AppListLoader.AppsDataPair> {
isSystemApp,
null);
mApps.first.add(elem);
}
Collections.sort(mApps.first, new AppDataSorter(sortBy, isAscending));
for (AppDataParcelable p : mApps.first) {
mApps.second.add(p.getPath());
mApps.add(elem);
}
Collections.sort(mApps, new AppDataSorter(sortBy, isAscending));
return mApps;
}
@Override
public void deliverResult(AppsDataPair data) {
public void deliverResult(List<AppDataParcelable> data) {
if (isReset()) {
if (data != null) onReleaseResources(data); // TODO onReleaseResources() is empty
}
// preserving old data for it to be closed
AppsDataPair oldData = mApps;
List<AppDataParcelable> oldData = mApps;
mApps = data;
if (isStarted()) {
// loader has been started, if we have data, return immediately
@@ -168,7 +161,7 @@ public class AppListLoader extends AsyncTaskLoader<AppListLoader.AppsDataPair> {
}
@Override
public void onCanceled(AppsDataPair data) {
public void onCanceled(List<AppDataParcelable> data) {
super.onCanceled(data);
onReleaseResources(data); // TODO onReleaseResources() is empty
@@ -197,7 +190,7 @@ public class AppListLoader extends AsyncTaskLoader<AppListLoader.AppsDataPair> {
/** We would want to release resources here List is nothing we would want to close */
// TODO do something
private void onReleaseResources(AppsDataPair layoutElementList) {}
private void onReleaseResources(List<AppDataParcelable> layoutElementList) {}
/**
* Check if an App is under /system or has been installed as an update to a built-in system
@@ -216,18 +209,4 @@ public class AppListLoader extends AsyncTaskLoader<AppListLoader.AppsDataPair> {
&& piApp.signatures != null
&& piSys.signatures[0].equals(piApp.signatures[0]));
}
/** typedef Pair<List<AppDataParcelable>, List<String>> AppsDataPair */
public static class AppsDataPair extends Pair<List<AppDataParcelable>, List<String>> {
/**
* Constructor for a Pair.
*
* @param first the first object in the Pair
* @param second the second object in the pair
*/
public AppsDataPair(List<AppDataParcelable> first, List<String> second) {
super(first, second);
}
}
}
@@ -177,6 +177,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.arch.core.util.Function;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.loader.app.LoaderManager;
@@ -1443,6 +1444,24 @@ public class MainActivity extends PermissionsActivity
return floatingActionButton;
}
public void showFab() {
getFAB().setVisibility(View.VISIBLE);
getFAB().show();
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) getFAB().getLayoutParams();
params.setBehavior(new SpeedDialView.ScrollingViewSnackbarBehavior());
getFAB().requestLayout();
}
public void hideFab() {
getFAB().setVisibility(View.GONE);
getFAB().hide();
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) getFAB().getLayoutParams();
params.setBehavior(new SpeedDialView.NoBehavior());
getFAB().requestLayout();
}
public AppBar getAppbar() {
return appbar;
}
@@ -310,11 +310,6 @@ class OpenFileDialogFragment : BaseBottomSheetFragment(), AdjustListViewForTv<Ap
modelProvider,
true, this, appDataParcelableList
)
modelProvider.setItemList(
appDataParcelableList.map { appDataParcelable ->
appDataParcelable.packageName
}
)
loadViews(lastAppData)
viewBinding.appsRecyclerView.addOnScrollListener(preloader)
@@ -40,6 +40,7 @@ import com.amaze.filemanager.asynchronous.loaders.AppListLoader;
import com.amaze.filemanager.ui.activities.MainActivity;
import com.amaze.filemanager.ui.provider.UtilitiesProvider;
import com.amaze.filemanager.ui.theme.AppTheme;
import com.amaze.filemanager.ui.views.FastScroller;
import com.amaze.filemanager.utils.GlideConstants;
import com.amaze.filemanager.utils.Utils;
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader;
@@ -68,7 +69,7 @@ import androidx.recyclerview.widget.RecyclerView;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
public class AppsListFragment extends Fragment
implements LoaderManager.LoaderCallbacks<AppListLoader.AppsDataPair>,
implements LoaderManager.LoaderCallbacks<List<AppDataParcelable>>,
AdjustListViewForTv<AppHolder> {
public static final int ID_LOADER_APP_LIST = 0;
@@ -82,6 +83,8 @@ public class AppsListFragment extends Fragment
private LinearLayoutManager linearLayoutManager;
private RecyclerViewPreloader<String> preloader;
private List<AppDataParcelable> appDataParcelableList;
private FastScroller fastScroller;
private boolean showSystemApps = true;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -101,6 +104,7 @@ public class AppsListFragment extends Fragment
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final MainActivity mainActivity = (MainActivity) getActivity();
Objects.requireNonNull(mainActivity);
@@ -119,9 +123,17 @@ public class AppsListFragment extends Fragment
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
isAscending = sharedPreferences.getBoolean(PREFERENCE_APPLIST_ISASCENDING, true);
sortby = sharedPreferences.getInt(PREFERENCE_APPLIST_SORTBY, 0);
fastScroller = rootView.findViewById(R.id.fastscroll);
fastScroller.setPressedHandleColor(mainActivity.getAccent());
fastScroller.setRecyclerView(getRecyclerView(), 1);
mainActivity
.getAppbar()
.getAppbarLayout()
.addOnOffsetChangedListener(
(appBarLayout, verticalOffset) -> {
fastScroller.updateHandlePosition(verticalOffset, 112);
});
LoaderManager.getInstance(this).initLoader(ID_LOADER_APP_LIST, null, this);
super.onViewCreated(view, savedInstanceState);
}
@Override
@@ -141,8 +153,9 @@ public class AppsListFragment extends Fragment
requireActivity().finish();
return true;
case R.id.checkbox_system_apps:
adapter.setData(appDataParcelableList, !item.isChecked());
item.setChecked(!item.isChecked());
adapter.setData(appDataParcelableList, item.isChecked());
showSystemApps = item.isChecked();
return true;
default:
return super.onOptionsItemSelected(item);
@@ -151,7 +164,7 @@ public class AppsListFragment extends Fragment
private void updateViews(MainActivity mainActivity, UtilitiesProvider utilsProvider) {
mainActivity.getAppbar().setTitle(R.string.apps);
mainActivity.getFAB().hide();
mainActivity.hideFab();
mainActivity.getAppbar().getBottomBar().setVisibility(View.GONE);
mainActivity.supportInvalidateOptionsMenu();
@@ -233,28 +246,34 @@ public class AppsListFragment extends Fragment
@NonNull
@Override
public Loader<AppListLoader.AppsDataPair> onCreateLoader(int id, Bundle args) {
public Loader<List<AppDataParcelable>> onCreateLoader(int id, Bundle args) {
return new AppListLoader(getContext(), sortby, isAscending);
}
@Override
public void onLoadFinished(
@NonNull Loader<AppListLoader.AppsDataPair> loader, AppListLoader.AppsDataPair data) {
@NonNull Loader<List<AppDataParcelable>> loader, List<AppDataParcelable> data) {
getSpinner().setVisibility(View.GONE);
if (data.first.isEmpty()) {
if (data.isEmpty()) {
getRecyclerView().setVisibility(View.GONE);
rootView.findViewById(R.id.empty_text_view).setVisibility(View.VISIBLE);
} else {
modelProvider.setItemList(data.second);
appDataParcelableList = new ArrayList<>(data.first);
adapter = new AppsRecyclerAdapter(this, modelProvider, false, this, data.first);
appDataParcelableList = new ArrayList<>(data);
List<AppDataParcelable> adapterList = new ArrayList<>();
for (AppDataParcelable appDataParcelable : data) {
if (!showSystemApps && appDataParcelable.isSystemApp()) {
continue;
}
adapterList.add(appDataParcelable);
}
adapter = new AppsRecyclerAdapter(this, modelProvider, false, this, adapterList);
getRecyclerView().setVisibility(View.VISIBLE);
getRecyclerView().setAdapter(adapter);
}
}
@Override
public void onLoaderReset(@NonNull Loader<AppListLoader.AppsDataPair> loader) {
public void onLoaderReset(@NonNull Loader<List<AppDataParcelable>> loader) {
adapter.setData(Collections.emptyList(), true);
}
@@ -480,7 +480,7 @@ class CompressedExplorerFragment : Fragment(), BottomBarButtonPath {
override fun onResume() {
super.onResume()
requireMainActivity().fab.hide()
requireMainActivity().hideFab()
val intent = Intent(activity, ExtractService::class.java)
requireActivity().bindService(intent, mServiceConnection, 0)
}
@@ -634,7 +634,7 @@ class FtpServerFragment : Fragment(R.layout.fragment_ftp) {
private fun updateViews(mainActivity: MainActivity, binding: FragmentFtpBinding) {
mainActivity.appbar.setTitle(R.string.ftp)
mainActivity.fab.hide()
mainActivity.hideFab()
mainActivity.appbar.bottomBar.setVisibility(View.GONE)
mainActivity.invalidateOptionsMenu()
@@ -417,7 +417,7 @@ public class MainFragment extends Fragment
mode.setCustomView(actionModeView);
getMainActivity().setPagingEnabled(false);
getMainActivity().getFAB().hide();
getMainActivity().hideFab();
// translates the drawable content down
// if (getMainActivity().isDrawerLocked) getMainActivity().translateDrawerList(true);
@@ -711,7 +711,7 @@ public class MainFragment extends Fragment
// translates the drawer content up
// if (getMainActivity().isDrawerLocked) getMainActivity().translateDrawerList(false);
getMainActivity().getFAB().show();
getMainActivity().showFab();
if (!mainFragmentViewModel.getResults())
adapter.toggleChecked(false, mainFragmentViewModel.getCurrentPath());
else adapter.toggleChecked(false);
@@ -991,8 +991,6 @@ public class MainFragment extends Fragment
== DataUtils.GRID;
setListElements(
data.second, back, providedPath, data.first, false, isPathLayoutGrid);
setListElements(
data.second, back, providedPath, data.first, false, isPathLayoutGrid);
} else {
Log.w(getClass().getSimpleName(), "Load list operation cancelled");
}
@@ -1196,7 +1194,7 @@ public class MainFragment extends Fragment
}
getMainActivity().updatePaths(mainFragmentViewModel.getNo());
getMainActivity().getFAB().show();
getMainActivity().showFab();
getMainActivity().getAppbar().getAppbarLayout().setExpanded(true);
listView.stopScroll();
fastScroller.setRecyclerView(
@@ -148,7 +148,7 @@ public class ProcessViewerFragment extends Fragment {
setRetainInstance(true);
mainActivity.getAppbar().setTitle(R.string.process_viewer);
mainActivity.getFAB().hide();
mainActivity.hideFab();
mainActivity.getAppbar().getBottomBar().setVisibility(View.GONE);
mainActivity.supportInvalidateOptionsMenu();
@@ -4,6 +4,7 @@
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:descendantFocusability="afterDescendants">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_view"
android:layout_width="@dimen/zero_dp"
@@ -15,6 +16,15 @@
android:descendantFocusability="afterDescendants"
android:visibility="gone"
/>
<com.amaze.filemanager.ui.views.FastScroller
android:id="@+id/fastscroll"
android:orientation="vertical"
android:layout_width="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_height="match_parent"/>
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/loading_spinner"
android:layout_width="@dimen/material_generic_large"
+2
View File
@@ -722,5 +722,7 @@ You only need to do this once, until the next time you select a new location for
<string name="cloud_drive_tooltip">Create a Google Drive™ connection for managing files from within Amaze File Manager.</string>
<string name="signin_with_google_title">Authenticate to use Google Drive™</string>
<string name="show_system_apps">Show system apps</string>
<string name="system_apps">System apps</string>
<string name="third_party_apps">Third party apps</string>
</resources>