From 7a1517fc3d5296d7954daa857ef62fcf794ab7ce Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Mon, 11 Jan 2021 02:22:24 +0200 Subject: [PATCH 1/3] Fix #10068 --- OsmAnd/res/values/strings.xml | 3 + .../AddNewTrackFolderBottomSheet.java | 158 ++++++++++++++++++ .../plus/myplaces/AvailableGPXFragment.java | 153 +++-------------- .../plus/myplaces/MoveGpxFileBottomSheet.java | 151 +++++++++++++++++ .../ElevationDateBottomSheet.java | 3 +- 5 files changed, 336 insertions(+), 132 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java create mode 100644 OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 47645eb555..765b81de75 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,9 @@ --> + Select folder or add new one + Select folder + Folders Online routing engines Online routing engine Copy address diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java b/OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java new file mode 100644 index 0000000000..584ba75339 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java @@ -0,0 +1,158 @@ +package net.osmand.plus.myplaces; + +import android.content.res.ColorStateList; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import com.google.android.material.textfield.TextInputEditText; +import com.google.android.material.textfield.TextInputLayout; + +import net.osmand.AndroidUtils; +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + +import java.io.File; + +import static net.osmand.FileUtils.ILLEGAL_PATH_NAME_CHARACTERS; + +public class AddNewTrackFolderBottomSheet extends MenuBottomSheetDialogFragment { + + public static final String TAG = AddNewTrackFolderBottomSheet.class.getName(); + private static final Log LOG = PlatformUtil.getLog(AddNewTrackFolderBottomSheet.class); + private static final String FOLDER_NAME_KEY = "folder_name_key"; + + private OsmandApplication app; + + private TextInputEditText editText; + private TextInputLayout nameTextBox; + + private String folderName; + private boolean rightButtonEnabled = true; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + app = requiredMyApplication(); + if (savedInstanceState != null) { + folderName = savedInstanceState.getString(FOLDER_NAME_KEY); + } else if (Algorithms.isEmpty(folderName)) { + folderName = app.getAppPath(IndexConstants.GPX_INDEX_DIR).getName(); + } + items.add(new TitleItem(getString(R.string.add_new_folder))); + + View view = UiUtilities.getInflater(app, nightMode).inflate(R.layout.track_name_edit_text, null); + nameTextBox = view.findViewById(R.id.name_text_box); + nameTextBox.setBoxBackgroundColorResource(nightMode ? R.color.list_background_color_dark : R.color.activity_background_color_light); + nameTextBox.setHint(AndroidUtils.addColon(app, R.string.shared_string_name)); + ColorStateList colorStateList = ColorStateList.valueOf(ContextCompat + .getColor(app, nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light)); + nameTextBox.setDefaultHintTextColor(colorStateList); + TextInputEditText nameText = view.findViewById(R.id.name_edit_text); + nameText.setText(folderName); + nameText.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) { + updateFileNameFromEditText(s.toString()); + } + }); + BaseBottomSheetItem editFolderName = new BaseBottomSheetItem.Builder() + .setCustomView(view) + .create(); + items.add(editFolderName); + } + + @Override + protected boolean isRightBottomButtonEnabled() { + return rightButtonEnabled; + } + + private void updateFileNameFromEditText(String name) { + rightButtonEnabled = false; + if (ILLEGAL_PATH_NAME_CHARACTERS.matcher(name).find()) { + nameTextBox.setError(getString(R.string.file_name_containes_illegal_char)); + } else if (Algorithms.isEmpty(name.trim())) { + nameTextBox.setError(getString(R.string.empty_filename)); + } else { + File destFolder = new File(app.getAppPath(IndexConstants.GPX_INDEX_DIR), name); + if (destFolder.exists()) { + nameTextBox.setError(getString(R.string.file_with_name_already_exist)); + } else { + nameTextBox.setError(null); + folderName = name; + rightButtonEnabled = true; + } + } + updateBottomButtons(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putString(FOLDER_NAME_KEY, folderName); + super.onSaveInstanceState(outState); + } + + @Override + protected void onRightBottomButtonClick() { + AndroidUtils.hideSoftKeyboard(requireActivity(), editText); + Fragment fragment = getTargetFragment(); + if (fragment instanceof OnTrackFolderAddListener) { + OnTrackFolderAddListener listener = (OnTrackFolderAddListener) fragment; + listener.onTrackFolderAdd(folderName); + } + dismiss(); + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_cancel; + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_add; + } + + public interface OnTrackFolderAddListener { + + void onTrackFolderAdd(String folderName); + } + + public static void showInstance(@NonNull FragmentManager fragmentManager, @Nullable Fragment target, + @NonNull String folderName, boolean usedOnMap) { + try { + if (!fragmentManager.isStateSaved() && fragmentManager.findFragmentByTag(AddNewTrackFolderBottomSheet.TAG) == null) { + AddNewTrackFolderBottomSheet fragment = new AddNewTrackFolderBottomSheet(); + fragment.folderName = folderName; + fragment.setUsedOnMap(usedOnMap); + fragment.setTargetFragment(target, 0); + fragment.show(fragmentManager, AddNewTrackFolderBottomSheet.TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java index 9e4ac656a4..4fc2e309fc 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java @@ -13,8 +13,6 @@ import android.os.AsyncTask; import android.os.Build; 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.MenuInflater; @@ -27,7 +25,6 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.EditText; import android.widget.ExpandableListView; import android.widget.Filter; import android.widget.Filterable; @@ -42,6 +39,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.view.ActionMode; import androidx.appcompat.widget.SearchView; import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentActivity; import net.osmand.AndroidUtils; import net.osmand.Collator; @@ -81,11 +79,12 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.enums.TracksSortByMode; import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; +import net.osmand.plus.myplaces.MoveGpxFileBottomSheet.OnTrackFileMoveListener; import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.widgets.popup.PopUpMenuItem; import net.osmand.plus.widgets.popup.PopUpMenuHelper; +import net.osmand.plus.widgets.popup.PopUpMenuItem; import java.io.File; import java.text.DateFormat; @@ -101,21 +100,18 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Pattern; import static net.osmand.plus.GpxSelectionHelper.CURRENT_TRACK; import static net.osmand.plus.myplaces.FavoritesActivity.GPX_TAB; import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID; import static net.osmand.util.Algorithms.capitalizeFirstLetter; -import static net.osmand.util.Algorithms.collectDirs; import static net.osmand.util.Algorithms.formatDuration; import static net.osmand.util.Algorithms.objectEquals; import static net.osmand.util.Algorithms.removeAllFiles; public class AvailableGPXFragment extends OsmandExpandableListFragment implements - FavoritesFragmentStateHolder, OsmAuthorizationListener { + FavoritesFragmentStateHolder, OsmAuthorizationListener, OnTrackFileMoveListener { - public static final Pattern ILLEGAL_PATH_NAME_CHARACTERS = Pattern.compile("[?:\"*|<>]"); public static final int SEARCH_ID = -1; // public static final int ACTION_ID = 0; // protected static final int DELETE_ACTION_ID = 1; @@ -790,129 +786,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement } private void moveGpx(final GpxInfo info) { - - final ContextMenuAdapter menuAdapter = new ContextMenuAdapter(app); - ContextMenuItem.ItemBuilder itemBuilder = new ContextMenuItem.ItemBuilder(); - - final List dirs = new ArrayList<>(); - collectDirs(app.getAppPath(IndexConstants.GPX_INDEX_DIR), dirs, info.file.getParentFile()); - if (!info.file.getParentFile().equals(app.getAppPath(IndexConstants.GPX_INDEX_DIR))) { - dirs.add(0, app.getAppPath(IndexConstants.GPX_INDEX_DIR)); + FragmentActivity activity = getActivity(); + if (activity != null) { + MoveGpxFileBottomSheet.showInstance(activity.getSupportFragmentManager(), this, info.file.getAbsolutePath(), false); } - String gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR).getPath(); - int i = 0; - for (File dir : dirs) { - String dirName = dir.getPath(); - if (dirName.startsWith(gpxDir)) { - if (dirName.length() == gpxDir.length()) { - dirName = dir.getName(); - } else { - dirName = dirName.substring(gpxDir.length() + 1); - } - } - menuAdapter.addItem(itemBuilder.setTitle(capitalizeFirstLetter(dirName)) - .setIcon(R.drawable.ic_action_folder_stroke).setTag(i).createItem()); - i++; - } - menuAdapter.addItem(itemBuilder.setTitleId(R.string.add_new_folder, app) - .setIcon(R.drawable.ic_zoom_in).setTag(-1).createItem()); - final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - final ArrayAdapter listAdapter = - menuAdapter.createListAdapter(getActivity(), app.getSettings().isLightContent()); - builder.setTitle(R.string.select_gpx_folder); - builder.setAdapter(listAdapter, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - ContextMenuItem item = menuAdapter.getItem(which); - int index = item.getTag(); - if (index == -1) { - Activity a = getActivity(); - AlertDialog.Builder b = new AlertDialog.Builder(a); - b.setTitle(R.string.add_new_folder); - final EditText editText = new EditText(a); - editText.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) { - Editable text = editText.getText(); - if (text.length() >= 1) { - if (ILLEGAL_PATH_NAME_CHARACTERS.matcher(text).find()) { - editText.setError(app.getString(R.string.file_name_containes_illegal_char)); - } - } - } - }); - int leftPadding = AndroidUtils.dpToPx(a, 24f); - int topPadding = AndroidUtils.dpToPx(a, 4f); - b.setView(editText, leftPadding, topPadding, leftPadding, topPadding); - // Behaviour will be overwritten later; - b.setPositiveButton(R.string.shared_string_ok, null); - b.setNegativeButton(R.string.shared_string_cancel, null); - final AlertDialog alertDialog = b.create(); - alertDialog.setOnShowListener(new DialogInterface.OnShowListener() { - @Override - public void onShow(DialogInterface dialog) { - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - String newName = editText.getText().toString(); - if (ILLEGAL_PATH_NAME_CHARACTERS.matcher(newName).find()) { - Toast.makeText(app, R.string.file_name_containes_illegal_char, - Toast.LENGTH_LONG).show(); - return; - } - File destFolder = new File(app.getAppPath(IndexConstants.GPX_INDEX_DIR), newName); - if (destFolder.exists()) { - Toast.makeText(app, R.string.file_with_name_already_exists, - Toast.LENGTH_LONG).show(); - return; - } else if (destFolder.mkdirs()) { - File dest = new File(destFolder, info.fileName); - if (info.file.renameTo(dest)) { - app.getGpxDbHelper().rename(info.file, dest); - asyncLoader = new LoadGpxTask(); - asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); - } else { - Toast.makeText(app, R.string.file_can_not_be_moved, Toast.LENGTH_LONG).show(); - } - - } else { - Toast.makeText(app, R.string.file_can_not_be_moved, Toast.LENGTH_LONG).show(); - } - alertDialog.dismiss(); - } - }); - } - }); - alertDialog.show(); - } else { - File dir = dirs.get(index); - File dest = new File(dir, info.file.getName()); - if (dest.exists()) { - Toast.makeText(app, R.string.file_with_name_already_exists, Toast.LENGTH_LONG).show(); - } else { - if (info.file.renameTo(dest)) { - app.getGpxDbHelper().rename(info.file, dest); - asyncLoader = new LoadGpxTask(); - asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); - } else { - Toast.makeText(app, R.string.file_can_not_be_moved, Toast.LENGTH_LONG).show(); - } - } - } - } - }); - builder.setNegativeButton(R.string.shared_string_cancel, null); - builder.create().show(); } @Override @@ -938,6 +815,22 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement app.startActivity(intent); } + @Override + public void onFileMove(@NonNull File src, @NonNull File dest) { + File destFolder = dest.getParentFile(); + if (destFolder != null && !destFolder.exists() && !destFolder.mkdirs()) { + app.showToastMessage(R.string.file_can_not_be_moved); + } else if (dest.exists()) { + app.showToastMessage(R.string.file_with_name_already_exists); + } else if (src.renameTo(dest)) { + app.getGpxDbHelper().rename(src, dest); + asyncLoader = new LoadGpxTask(); + asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); + } else { + app.showToastMessage(R.string.file_can_not_be_moved); + } + } + public class LoadGpxTask extends AsyncTask> { private List result; diff --git a/OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java new file mode 100644 index 0000000000..50450ad19c --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java @@ -0,0 +1,151 @@ +package net.osmand.plus.myplaces; + +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitleItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.myplaces.AddNewTrackFolderBottomSheet.OnTrackFolderAddListener; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import static net.osmand.util.Algorithms.capitalizeFirstLetter; +import static net.osmand.util.Algorithms.collectDirs; + +public class MoveGpxFileBottomSheet extends MenuBottomSheetDialogFragment implements OnTrackFolderAddListener { + + public static final String TAG = MoveGpxFileBottomSheet.class.getSimpleName(); + private static final Log LOG = PlatformUtil.getLog(MoveGpxFileBottomSheet.class); + private static final String FILE_PATH_KEY = "file_path_key"; + + private OsmandApplication app; + private String filePath; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + app = requiredMyApplication(); + if (savedInstanceState != null) { + filePath = savedInstanceState.getString(FILE_PATH_KEY); + } + if (filePath == null) { + return; + } + final File file = new File(filePath); + final File fileDir = file.getParentFile(); + + items.add(new TitleItem(getString(R.string.shared_string_folders))); + items.add(new SubtitleItem(getString(R.string.select_folder_descr))); + + BaseBottomSheetItem addNewFolderItem = new SimpleBottomSheetItem.Builder() + .setTitle(getString(R.string.add_new_folder)) + .setIcon(getActiveIcon(R.drawable.ic_action_folder_add)) + .setLayoutId(R.layout.bottom_sheet_item_simple) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity activity = getActivity(); + if (activity != null) { + AddNewTrackFolderBottomSheet.showInstance(activity.getSupportFragmentManager(), + MoveGpxFileBottomSheet.this, fileDir.getName(), usedOnMap); + } + } + }) + .create(); + items.add(addNewFolderItem); + items.add(new DividerItem(app)); + + final List dirs = new ArrayList<>(); + collectDirs(app.getAppPath(IndexConstants.GPX_INDEX_DIR), dirs, fileDir); + if (!Algorithms.objectEquals(fileDir, app.getAppPath(IndexConstants.GPX_INDEX_DIR))) { + dirs.add(0, app.getAppPath(IndexConstants.GPX_INDEX_DIR)); + } + String gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR).getPath(); + for (final File dir : dirs) { + String dirName = dir.getPath(); + if (dirName.startsWith(gpxDir)) { + if (dirName.length() == gpxDir.length()) { + dirName = dir.getName(); + } else { + dirName = dirName.substring(gpxDir.length() + 1); + } + } + + final BaseBottomSheetItem[] folderItem = new BaseBottomSheetItem[1]; + folderItem[0] = new SimpleBottomSheetItem.Builder() + .setTitle(capitalizeFirstLetter(dirName)) + .setIcon(getActiveIcon(R.drawable.ic_action_folder)) + .setLayoutId(R.layout.bottom_sheet_item_simple) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Fragment fragment = getTargetFragment(); + if (fragment instanceof OnTrackFileMoveListener) { + OnTrackFileMoveListener listener = (OnTrackFileMoveListener) fragment; + listener.onFileMove(file, new File(dir, file.getName())); + } + dismiss(); + } + }) + .setTag(dir) + .create(); + items.add(folderItem[0]); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(FILE_PATH_KEY, filePath); + } + + @Override + public void onTrackFolderAdd(String folderName) { + Fragment fragment = getTargetFragment(); + if (fragment instanceof OnTrackFileMoveListener) { + File file = new File(filePath); + File destFolder = new File(app.getAppPath(IndexConstants.GPX_INDEX_DIR), folderName); + OnTrackFileMoveListener listener = (OnTrackFileMoveListener) fragment; + listener.onFileMove(file, new File(destFolder, file.getName())); + } + dismiss(); + } + + public static void showInstance(@NonNull FragmentManager fragmentManager, @Nullable Fragment target, + @NonNull String filePath, boolean usedOnMap) { + try { + if (!fragmentManager.isStateSaved() && fragmentManager.findFragmentByTag(MoveGpxFileBottomSheet.TAG) == null) { + MoveGpxFileBottomSheet fragment = new MoveGpxFileBottomSheet(); + fragment.filePath = filePath; + fragment.setUsedOnMap(usedOnMap); + fragment.setTargetFragment(target, 0); + fragment.show(fragmentManager, MoveGpxFileBottomSheet.TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } + + public interface OnTrackFileMoveListener { + void onFileMove(@NonNull File src, @NonNull File dest); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java index 0d5d990eaf..427bda7521 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java @@ -2,7 +2,6 @@ package net.osmand.plus.settings.bottomsheets; import android.content.Context; import android.os.Bundle; -import android.os.Handler; import android.view.View; import android.widget.TextView; @@ -255,7 +254,7 @@ public class ElevationDateBottomSheet extends MenuBottomSheetDialogFragment { fragment.appMode = appMode; fragment.setUsedOnMap(usedOnMap); fragment.setTargetFragment(target, 0); - fragment.show(fm, ScreenTimeoutBottomSheet.TAG); + fragment.show(fm, ElevationDateBottomSheet.TAG); } } catch (RuntimeException e) { LOG.error("showInstance", e); From f2f2d57a61bc5fe4e904194faa04442ecd374a52 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Mon, 11 Jan 2021 04:16:22 +0200 Subject: [PATCH 2/3] Move gpx UI polishing --- ...ttom_sheet_item_title_with_description.xml | 44 ++++++++++ OsmAnd/res/layout/select_folder_row.xml | 44 ++++++++++ OsmAnd/res/values/strings.xml | 1 + ...veAsNewTrackBottomSheetDialogFragment.java | 84 ++++++++++++++++--- .../adapter/FolderListAdapter.java | 24 ++---- .../plus/myplaces/MoveGpxFileBottomSheet.java | 50 +++++++++-- 6 files changed, 210 insertions(+), 37 deletions(-) create mode 100644 OsmAnd/res/layout/bottom_sheet_item_title_with_description.xml create mode 100644 OsmAnd/res/layout/select_folder_row.xml diff --git a/OsmAnd/res/layout/bottom_sheet_item_title_with_description.xml b/OsmAnd/res/layout/bottom_sheet_item_title_with_description.xml new file mode 100644 index 0000000000..9ffaa2e9dd --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_title_with_description.xml @@ -0,0 +1,44 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/select_folder_row.xml b/OsmAnd/res/layout/select_folder_row.xml new file mode 100644 index 0000000000..d9340cc5f2 --- /dev/null +++ b/OsmAnd/res/layout/select_folder_row.xml @@ -0,0 +1,44 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 765b81de75..c499d54b5c 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,7 @@ --> + Empty Select folder or add new one Select folder Folders diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java index 5b4058f339..90cbd1446e 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java @@ -8,6 +8,7 @@ import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.View; +import android.view.View.OnClickListener; import android.widget.EditText; import android.widget.Toast; @@ -16,13 +17,16 @@ import androidx.annotation.Nullable; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; +import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.GPXFile; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; @@ -35,12 +39,17 @@ import net.osmand.plus.base.bottomsheetmenu.HorizontalRecyclerBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.measurementtool.adapter.FolderListAdapter; +import net.osmand.plus.myplaces.MoveGpxFileBottomSheet; +import net.osmand.plus.myplaces.MoveGpxFileBottomSheet.OnTrackFileMoveListener; +import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.io.File; +import java.util.ArrayList; +import java.util.List; -public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { +public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFragment implements OnTrackFileMoveListener { public static final String TAG = SaveAsNewTrackBottomSheetDialogFragment.class.getSimpleName(); private static final Log LOG = PlatformUtil.getLog(SaveAsNewTrackBottomSheetDialogFragment.class); @@ -52,19 +61,24 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial public static final String SOURCE_FOLDER_NAME_KEY = "source_folder_name_key"; public static final String SHOW_SIMPLIFIED_BUTTON_KEY = "show_simplified_button_key"; - private boolean showOnMap; - private boolean simplifiedTrack; + private OsmandApplication app; + + private FolderListAdapter adapter; + private TextInputLayout nameTextBox; + private RecyclerView recyclerView; + private String fileName; private String sourceFileName; private String sourceFolderName; private String folderName; + private boolean showOnMap; + private boolean simplifiedTrack; private boolean rightButtonEnabled = true; private boolean showSimplifiedButton = true; - private TextInputLayout nameTextBox; @Override public void createMenuItems(Bundle savedInstanceState) { - OsmandApplication app = getMyApplication(); + app = getMyApplication(); if (app == null) { return; } @@ -118,12 +132,30 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial items.add(new DividerSpaceItem(app, contentPaddingSmall)); - FolderListAdapter adapter = new FolderListAdapter(app, nightMode, folderName); + View selectFolderView = View.inflate(UiUtilities.getThemedContext(app, nightMode), R.layout.select_folder_row, null); + selectFolderView.findViewById(R.id.select_folder_button).setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity activity = getActivity(); + if (activity != null) { + File dest = getFile(app, folderName, fileName); + MoveGpxFileBottomSheet.showInstance(activity.getSupportFragmentManager(), + SaveAsNewTrackBottomSheetDialogFragment.this, dest.getAbsolutePath(), usedOnMap); + } + } + }); + BaseBottomSheetItem selectFolderItem = new BaseBottomSheetItem.Builder() + .setCustomView(selectFolderView) + .create(); + items.add(selectFolderItem); + + adapter = new FolderListAdapter(app, nightMode, folderName); + adapter.setFolders(getFolders()); if (adapter.getItemCount() > 0) { adapter.setListener(createFolderSelectListener()); View view = View.inflate(UiUtilities.getThemedContext(app, nightMode), R.layout.bottom_sheet_item_recyclerview, null); - View recyclerView = view.findViewById(R.id.recycler_view); + recyclerView = view.findViewById(R.id.recycler_view); recyclerView.setPadding(contentPaddingHalf, 0, contentPaddingHalf, 0); BaseBottomSheetItem scrollItem = new HorizontalRecyclerBottomSheetItem.Builder() .setAdapter(adapter) @@ -191,7 +223,7 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial GradientDrawable background = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline); if (background != null) { - int highlightColor = ContextCompat.getColor(app,nightMode ? + int highlightColor = ContextCompat.getColor(app, nightMode ? R.color.list_background_color_dark : R.color.activity_background_color_light); int strokedColor = AndroidUtils.getColorFromAttr(UiUtilities.getThemedContext(app, nightMode), R.attr.stroked_buttons_and_links_outline); @@ -234,7 +266,7 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial } public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, String folderName, - String fileName, boolean showSimplifiedButton, boolean showOnMap) { + String fileName, boolean showSimplifiedButton, boolean showOnMap) { try { if (!fm.isStateSaved()) { SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment(); @@ -284,7 +316,7 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial } } } - GPXUtilities.GPXFile gpxFile = GPXUtilities.loadGPXFile(dest); + GPXFile gpxFile = GPXUtilities.loadGPXFile(dest); if (gpxFile.error != null) { return; } @@ -331,6 +363,38 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial return false; } + private List getFolders() { + List dirs = new ArrayList<>(); + File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR); + dirs.add(gpxDir); + Algorithms.collectDirs(gpxDir, dirs); + List dirItems = new ArrayList<>(); + for (File dir : dirs) { + dirItems.add(dir.getName()); + } + return dirItems; + } + + @Override + public void onFileMove(@NonNull File src, @NonNull File dest) { + File destFolder = dest.getParentFile(); + if (destFolder != null) { + folderName = destFolder.getName(); + boolean newFolder = destFolder.mkdirs(); + List folders = getFolders(); + if (newFolder) { + adapter.setFolders(folders); + } + adapter.setSelectedFolderName(folderName); + adapter.notifyDataSetChanged(); + + int position = folders.indexOf(folderName); + if (position != -1) { + recyclerView.scrollToPosition(position); + } + } + } + @Override protected int getBgColorId() { return nightMode ? R.color.activity_background_color_dark : R.color.list_background_color_light; diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/adapter/FolderListAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/FolderListAdapter.java index b383a4bef6..30b85910ad 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/adapter/FolderListAdapter.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/FolderListAdapter.java @@ -15,14 +15,11 @@ import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import net.osmand.AndroidUtils; -import net.osmand.IndexConstants; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.util.Algorithms; -import java.io.File; import java.util.ArrayList; -import java.util.Collection; import java.util.List; public class FolderListAdapter extends RecyclerView.Adapter { @@ -38,24 +35,15 @@ public class FolderListAdapter extends RecyclerView.Adapter folders) { items.clear(); - items.addAll(getFolders()); - } - - private Collection getFolders() { - List dirs = new ArrayList<>(); - File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR); - dirs.add(gpxDir); - Algorithms.collectDirs(gpxDir, dirs); - List dirItems = new ArrayList<>(); - for (File dir : dirs) { - dirItems.add(dir.getName()); - } - return dirItems; + items.addAll(folders); } @NonNull diff --git a/OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java index 50450ad19c..c00e360d7d 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/MoveGpxFileBottomSheet.java @@ -14,12 +14,13 @@ import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; -import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitleItem; -import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.myplaces.AddNewTrackFolderBottomSheet.OnTrackFolderAddListener; import net.osmand.util.Algorithms; @@ -53,13 +54,20 @@ public class MoveGpxFileBottomSheet extends MenuBottomSheetDialogFragment implem final File file = new File(filePath); final File fileDir = file.getParentFile(); - items.add(new TitleItem(getString(R.string.shared_string_folders))); - items.add(new SubtitleItem(getString(R.string.select_folder_descr))); + BaseBottomSheetItem titleItem = new BottomSheetItemWithDescription.Builder() + .setDescription(getString(R.string.select_folder_descr)) + .setTitle(getString(R.string.shared_string_folders)) + .setLayoutId(R.layout.bottom_sheet_item_title_with_description) + .create(); + items.add(titleItem); + View addNewFolderView = UiUtilities.getInflater(app, nightMode).inflate(R.layout.bottom_sheet_item_with_descr_64dp, null); + addNewFolderView.setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.bottom_sheet_list_item_height)); + AndroidUiHelper.updateVisibility(addNewFolderView.findViewById(R.id.description), false); BaseBottomSheetItem addNewFolderItem = new SimpleBottomSheetItem.Builder() .setTitle(getString(R.string.add_new_folder)) .setIcon(getActiveIcon(R.drawable.ic_action_folder_add)) - .setLayoutId(R.layout.bottom_sheet_item_simple) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_64dp) .setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -70,9 +78,13 @@ public class MoveGpxFileBottomSheet extends MenuBottomSheetDialogFragment implem } } }) + .setCustomView(addNewFolderView) .create(); items.add(addNewFolderItem); - items.add(new DividerItem(app)); + + DividerItem dividerItem = new DividerItem(app); + dividerItem.setMargins(0, 0, 0, 0); + items.add(dividerItem); final List dirs = new ArrayList<>(); collectDirs(app.getAppPath(IndexConstants.GPX_INDEX_DIR), dirs, fileDir); @@ -89,12 +101,19 @@ public class MoveGpxFileBottomSheet extends MenuBottomSheetDialogFragment implem dirName = dirName.substring(gpxDir.length() + 1); } } - + String description; + List files = collectFiles(dir); + if (Algorithms.isEmpty(files)) { + description = getString(R.string.shared_string_empty); + } else { + description = String.valueOf(files.size()); + } final BaseBottomSheetItem[] folderItem = new BaseBottomSheetItem[1]; - folderItem[0] = new SimpleBottomSheetItem.Builder() + folderItem[0] = new BottomSheetItemWithDescription.Builder() + .setDescription(description) .setTitle(capitalizeFirstLetter(dirName)) .setIcon(getActiveIcon(R.drawable.ic_action_folder)) - .setLayoutId(R.layout.bottom_sheet_item_simple) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_64dp) .setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -130,6 +149,19 @@ public class MoveGpxFileBottomSheet extends MenuBottomSheetDialogFragment implem dismiss(); } + public List collectFiles(File parentDir) { + List files = new ArrayList<>(); + File[] listFiles = parentDir.listFiles(); + if (listFiles != null) { + for (File file : listFiles) { + if (!file.isDirectory()) { + files.add(file); + } + } + } + return files; + } + public static void showInstance(@NonNull FragmentManager fragmentManager, @Nullable Fragment target, @NonNull String filePath, boolean usedOnMap) { try { From 0942b612aba1db5a53ea6ef969a52272dacf5759 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Mon, 11 Jan 2021 07:22:40 +0200 Subject: [PATCH 3/3] Fix typo --- .../osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java b/OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java index 584ba75339..2a80de5b43 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/AddNewTrackFolderBottomSheet.java @@ -63,9 +63,9 @@ public class AddNewTrackFolderBottomSheet extends MenuBottomSheetDialogFragment ColorStateList colorStateList = ColorStateList.valueOf(ContextCompat .getColor(app, nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light)); nameTextBox.setDefaultHintTextColor(colorStateList); - TextInputEditText nameText = view.findViewById(R.id.name_edit_text); - nameText.setText(folderName); - nameText.addTextChangedListener(new TextWatcher() { + editText = view.findViewById(R.id.name_edit_text); + editText.setText(folderName); + editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }