diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 92bf7f97b..82329f24b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -65,7 +65,7 @@ android:label="@string/app_name" android:launchMode="singleTop" android:taskAffinity=".activity.MainActivity" - android:windowSoftInputMode="stateUnchanged|adjustResize"> + android:windowSoftInputMode="stateAlwaysHidden|adjustResize"> diff --git a/app/src/main/java/net/gsantner/markor/activity/DocumentShareIntoFragment.java b/app/src/main/java/net/gsantner/markor/activity/DocumentShareIntoFragment.java index a8822e712..f3a3268d7 100644 --- a/app/src/main/java/net/gsantner/markor/activity/DocumentShareIntoFragment.java +++ b/app/src/main/java/net/gsantner/markor/activity/DocumentShareIntoFragment.java @@ -268,6 +268,7 @@ private void showAppendDialog(int keyId) { @Override public void onFsViewerConfig(GsFileBrowserOptions.Options dopt) { dopt.rootFolder = startFolder; + dopt.newDirButtonEnable = false; } @Override diff --git a/app/src/main/java/net/gsantner/markor/frontend/filebrowser/MarkorFileBrowserFactory.java b/app/src/main/java/net/gsantner/markor/frontend/filebrowser/MarkorFileBrowserFactory.java index f18d5229c..8e3ee7a65 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/filebrowser/MarkorFileBrowserFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/filebrowser/MarkorFileBrowserFactory.java @@ -40,10 +40,11 @@ public static GsFileBrowserOptions.Options prepareFsViewerOpts(Context context, opts.doSelectFolder = doSelectFolder; opts.doSelectFile = !doSelectFolder; - opts.searchHint = R.string.search_documents; opts.searchButtonImage = R.drawable.ic_search_black_24dp; + opts.newDirButtonImage = R.drawable.baseline_create_new_folder_24; opts.homeButtonImage = R.drawable.ic_home_black_24dp; opts.selectedItemImage = R.drawable.ic_check_black_24dp; + opts.newDirButtonText = R.string.create_folder; opts.upButtonEnable = true; opts.homeButtonEnable = true; opts.mustStartWithRootFolder = false; diff --git a/app/src/main/java/net/gsantner/markor/frontend/textview/TextViewUtils.java b/app/src/main/java/net/gsantner/markor/frontend/textview/TextViewUtils.java index f9c2227ae..0f0724eda 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/textview/TextViewUtils.java +++ b/app/src/main/java/net/gsantner/markor/frontend/textview/TextViewUtils.java @@ -715,13 +715,6 @@ public static boolean checkRange(final int length, final int... indices) { return indices != null && indices.length >= 2 && inRange(0, length, indices) && indices[1] > indices[0]; } - public static void blinkView(final View view) { - if (view != null) { - final float init = view.getAlpha(); - ObjectAnimator.ofFloat(view, View.ALPHA, init, 0.1f, 1.0f, 0.1f, 1.0f, init).setDuration(1000).start(); - } - } - public static boolean isViewVisible(final View view) { if (view == null || !view.isShown()) { return false; diff --git a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java index 38b259843..4f3754efe 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java @@ -115,7 +115,7 @@ public static class DialogOptions { @StringRes public int searchHintText = android.R.string.search_go; @DrawableRes - public int clearInputIcon = android.R.drawable.ic_input_delete; + public int clearInputIcon = android.R.drawable.ic_menu_close_clear_cancel; } public static class Adapter extends BaseAdapter { diff --git a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserDialog.java index 63d35b32e..d5bb4a393 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserDialog.java @@ -17,17 +17,17 @@ */ package net.gsantner.opoc.frontend.filebrowser; +import android.app.Activity; +import android.app.Dialog; import android.content.Context; +import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; import android.widget.EditText; -import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.ColorRes; @@ -38,7 +38,11 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; + import net.gsantner.markor.R; +import net.gsantner.opoc.frontend.GsSearchOrCustomTextDialog; +import net.gsantner.opoc.util.GsContextUtils; import net.gsantner.opoc.wrapper.GsTextWatcherAdapter; import java.io.File; @@ -64,10 +68,9 @@ public static GsFileBrowserDialog newInstance(GsFileBrowserOptions.Options optio public TextView _dialogTitle; private TextView _buttonCancel; private TextView _buttonOk; - private LinearLayout _utilBar; - private LinearLayout _buttonBar; - private ImageView _homeButton; - private ImageView _buttonSearch; + private FloatingActionButton _homeButton; + private FloatingActionButton _buttonSearch; + private FloatingActionButton _buttonNewDir; private EditText _searchEdit; private GsFileBrowserListAdapter _filesystemViewerAdapter; @@ -80,8 +83,11 @@ public static GsFileBrowserDialog newInstance(GsFileBrowserOptions.Options optio @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.opoc_filesystem_dialog, container, false); - if (getDialog() != null && getDialog().getWindow() != null) { - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + final Dialog dialog = getDialog(); + final Window window = dialog != null ? dialog.getWindow() : null; + if (window != null) { + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + setStyle(STYLE_NORMAL, R.style.AppTheme_Unified); } return root; } @@ -90,22 +96,21 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa public void onViewCreated(View root, @Nullable Bundle savedInstanceState) { super.onViewCreated(root, savedInstanceState); Context context = getContext(); + _recyclerList = root.findViewById(R.id.ui__filesystem_dialog__list); - _dialogTitle = root.findViewById(R.id.ui__filesystem_dialog__title); + _dialogTitle = root.findViewById(R.id.ui__filesystem_dialog__title_text); _buttonCancel = root.findViewById(R.id.ui__filesystem_dialog__button_cancel); _buttonOk = root.findViewById(R.id.ui__filesystem_dialog__button_ok); - _utilBar = root.findViewById(R.id.ui__filesystem_dialog__utilbar); - _buttonBar = root.findViewById(R.id.ui__filesystem_dialog__buttons); _homeButton = root.findViewById(R.id.ui__filesystem_dialog__home); + _buttonNewDir = root.findViewById(R.id.ui__filesystem_dialog__new_dir); _buttonSearch = root.findViewById(R.id.ui__filesystem_dialog__search_button); _searchEdit = root.findViewById(R.id.ui__filesystem_dialog__search_edit); _searchEdit.addTextChangedListener(GsTextWatcherAdapter.on(this::changeAdapterFilter)); - for (final View v : new View[]{_homeButton, _buttonSearch, _buttonCancel, _buttonOk}) { + for (final View v : new View[]{_homeButton, _buttonSearch, _buttonNewDir, _buttonCancel, _buttonOk}) { v.setOnClickListener(this::onClicked); } - if (_dopt == null || _buttonCancel == null) { dismiss(); return; @@ -132,13 +137,20 @@ public void onViewCreated(View root, @Nullable Bundle savedInstanceState) { _buttonSearch.setVisibility(_dopt.searchEnable ? View.VISIBLE : View.GONE); _buttonSearch.setColorFilter(rcolor(_dopt.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_ATOP); + _buttonNewDir.setImageResource(_dopt.newDirButtonImage); + _buttonNewDir.setVisibility(_dopt.newDirButtonEnable ? View.VISIBLE : View.GONE); + _buttonNewDir.setColorFilter(rcolor(_dopt.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_ATOP); + _searchEdit.setHint(_dopt.searchHint); _searchEdit.setTextColor(rcolor(_dopt.primaryTextColor)); _searchEdit.setHintTextColor(rcolor(_dopt.secondaryTextColor)); + _searchEdit.setOnFocusChangeListener((v, isFocussed) -> { + GsContextUtils.instance.showSoftKeyboard(getActivity(), isFocussed, _searchEdit); + }); root.setBackgroundColor(rcolor(_dopt.backgroundColor)); - LinearLayoutManager lam = (LinearLayoutManager) _recyclerList.getLayoutManager(); + final LinearLayoutManager lam = (LinearLayoutManager) _recyclerList.getLayoutManager(); DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(getActivity(), lam.getOrientation()); _recyclerList.addItemDecoration(dividerItemDecoration); @@ -173,19 +185,54 @@ public void onClicked(View view) { break; } case R.id.ui__filesystem_dialog__search_button: { - _buttonSearch.setVisibility(View.GONE); - _searchEdit.setVisibility(View.VISIBLE); - _searchEdit.requestFocus(); - InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(_searchEdit, InputMethodManager.SHOW_IMPLICIT); + if (_searchEdit.getVisibility() == View.GONE) { + _searchEdit.setText(""); + _searchEdit.setVisibility(View.VISIBLE); + _searchEdit.requestFocus(); + } else { + _searchEdit.setText(""); + _searchEdit.setVisibility(View.GONE); + _searchEdit.clearFocus(); + } break; } case R.id.ui__filesystem_dialog__button_cancel: { onFsViewerNothingSelected(_dopt.requestId); break; } + case R.id.ui__filesystem_dialog__new_dir: { + showNewDirDialog(); + break; + } + } + } + @Override + public void onDismiss(final DialogInterface dialog) { + super.onDismiss(dialog); + GsContextUtils.instance.showSoftKeyboard(getActivity(), false, _searchEdit); + } + + private void showNewDirDialog() { + final Activity activity = getActivity(); + + if (activity == null) { + return; } + + final GsSearchOrCustomTextDialog.DialogOptions dopt = new GsSearchOrCustomTextDialog.DialogOptions(); + dopt.isDarkDialog = GsContextUtils.instance.isDarkModeEnabled(activity); + dopt.titleText = _dopt.newDirButtonText; + dopt.textColor = rcolor(_dopt.primaryTextColor); + dopt.searchHintText = android.R.string.untitled; + dopt.callback = (name) -> { + final File file = _filesystemViewerAdapter.createDirectoryHere(name); + if (file != null) { + _recyclerList.postDelayed(() -> _filesystemViewerAdapter.showAndBlink(file, _recyclerList), 100); + } + }; + + GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt); } private void checkOptions() { diff --git a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserFragment.java b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserFragment.java index 610fc9240..33e6d029f 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserFragment.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserFragment.java @@ -18,8 +18,10 @@ package net.gsantner.opoc.frontend.filebrowser; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import android.graphics.Color; +import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.util.Pair; @@ -29,6 +31,7 @@ import android.view.View; import android.widget.TextView; import android.widget.Toast; +import android.widget.Toolbar; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -315,6 +318,13 @@ public void onResume() { onFsViewerDoUiUpdate(_filesystemViewerAdapter); firstResume = false; + + final File folder = getCurrentFolder(); + final Activity activity = getActivity(); + if (isVisible() && folder != null && activity != null) { + activity.setTitle(folder.getName()); + reloadCurrentFolder(); + } } @@ -478,7 +488,7 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.action_info_selected_item: { if (_filesystemViewerAdapter.areItemsSelected()) { File file = new ArrayList<>(_filesystemViewerAdapter.getCurrentSelection()).get(0); - FileInfoDialog.show(file, getFragmentManager()); + FileInfoDialog.show(file, getChildFragmentManager()); } return true; } @@ -487,7 +497,7 @@ public boolean onOptionsItemSelected(MenuItem item) { if (_filesystemViewerAdapter.areItemsSelected()) { File file = new ArrayList<>(_filesystemViewerAdapter.getCurrentSelection()).get(0); WrRenameDialog renameDialog = WrRenameDialog.newInstance(file, renamedFile -> reloadCurrentFolder()); - renameDialog.show(getFragmentManager(), WrRenameDialog.FRAGMENT_TAG); + renameDialog.show(getChildFragmentManager(), WrRenameDialog.FRAGMENT_TAG); } return true; } @@ -545,7 +555,7 @@ public void askForDeletingFilesRecursive(WrConfirmDialog.ConfirmDialogCallback c } WrConfirmDialog confirmDialog = WrConfirmDialog.newInstance(getString(R.string.confirm_delete), message.toString(), itemsToDelete, confirmCallback); - confirmDialog.show(getParentFragmentManager(), WrConfirmDialog.FRAGMENT_TAG); + confirmDialog.show(getChildFragmentManager(), WrConfirmDialog.FRAGMENT_TAG); } private void askForMoveOrCopy(final boolean isMove) { @@ -585,7 +595,7 @@ public void onFsViewerDoUiUpdate(GsFileBrowserListAdapter adapter) { } } } - }, getActivity().getSupportFragmentManager(), getActivity()); + }, getChildFragmentManager(), getActivity()); } private void showImportDialog() { @@ -611,7 +621,7 @@ public void onFsViewerConfig(GsFileBrowserOptions.Options dopt) { dopt.doSelectFile = true; dopt.doSelectFolder = true; } - }, getFragmentManager(), getActivity(), null); + }, getChildFragmentManager(), getActivity(), null); } private void importFile(final File file) { @@ -624,9 +634,7 @@ private void importFile(final File file) { importFileToCurrentDirectory(getActivity(), file); } }); - if (getFragmentManager() != null) { - d.show(getFragmentManager(), WrConfirmDialog.FRAGMENT_TAG); - } + d.show(getChildFragmentManager(), WrConfirmDialog.FRAGMENT_TAG); } else { // Import importFileToCurrentDirectory(getActivity(), file); @@ -641,24 +649,7 @@ private void importFileToCurrentDirectory(Context context, File sourceFile) { @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); - if (isVisibleToUser && getCurrentFolder() != null && !TextUtils.isEmpty(getCurrentFolder().getName()) && getToolbar() != null) { - getToolbar().setTitle(getCurrentFolder().getName()); - reloadCurrentFolder(); - } - } - private void showAndBlink(final File file) { - final int pos = getAdapter().getFilePosition(file); - final LinearLayoutManager manager = (LinearLayoutManager) _recyclerList.getLayoutManager(); - if (manager != null && pos >= 0) { - manager.scrollToPositionWithOffset(pos, 1); - _recyclerList.postDelayed(() -> { - final RecyclerView.ViewHolder holder = _recyclerList.findViewHolderForLayoutPosition(pos); - if (holder != null) { - TextViewUtils.blinkView(holder.itemView); - } - }, 250); - } } // Switch to folder and show the file @@ -683,14 +674,14 @@ public void showFile(final File file) { public void onChanged() { super.onChanged(); if ((System.currentTimeMillis() - init) < 2000) { - _recyclerList.postDelayed(() -> showAndBlink(file), 250); + _recyclerList.postDelayed(() -> adapter.showAndBlink(file, _recyclerList), 250); } adapter.unregisterAdapterDataObserver(this); } }); adapter.setCurrentFolder(dir); } else { - showAndBlink(file); + adapter.showAndBlink(file, _recyclerList); } } diff --git a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserListAdapter.java b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserListAdapter.java index 9f5999309..c4d2dd3e3 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserListAdapter.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserListAdapter.java @@ -31,6 +31,7 @@ import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import net.gsantner.markor.R; @@ -96,6 +97,9 @@ public GsFileBrowserListAdapter(GsFileBrowserOptions.Options options, Context co _recyclerView = recyclerView; _prefApp = _context.getSharedPreferences("app", Context.MODE_PRIVATE); + // Prevents view flicker - https://stackoverflow.com/a/32488059 + setHasStableIds(true); + GsContextUtils cu = GsContextUtils.instance; if (_dopt.primaryColor == 0) { _dopt.primaryColor = cu.getResId(context, GsContextUtils.ResType.COLOR, "primary"); @@ -167,7 +171,6 @@ public void onBindViewHolder(@NonNull FilesystemViewerViewHolder holder, int pos } } - //String tmp = descriptionFile.getAbsolutePath().startsWith("/storage/emulated/0/") && getCurrentFolder().getAbsolutePath().startsWith("/storage/emulated/0/") ? "/storage/emulated/0/" : ""; holder.description.setTextColor(ContextCompat.getColor(_context, _dopt.secondaryTextColor)); holder.image.postDelayed(() -> { @@ -284,6 +287,13 @@ public TagContainer(File file_, int position_) { } } + + // Prevents view flicker - https://stackoverflow.com/a/32488059 + @Override + public long getItemId(final int position) { + return _adapterDataFiltered.get(position).hashCode(); + } + public File getCurrentFolder() { return _currentFolder; } @@ -389,8 +399,8 @@ public boolean isFilesOnlySelected() { public boolean toggleSelection(TagContainer data) { boolean clickHandled = false; - if (data != null && data.file != null && getCurrentFolder() != null) { - if (data.file.isDirectory() && getCurrentFolder().getParentFile() != null && getCurrentFolder().getParentFile().equals(data.file)) { + if (data != null && data.file != null && _currentFolder != null) { + if (data.file.isDirectory() && _currentFolder.getParentFile() != null && _currentFolder.getParentFile().equals(data.file)) { // goUp clickHandled = true; } else if (_currentSelection.contains(data.file)) { @@ -451,6 +461,49 @@ public boolean onLongClick(View view) { return false; } + public File createDirectoryHere(final CharSequence name) { + if (name == null || _currentFolder == null || !_currentFolder.canWrite()) { + return null; + } + + final String trimmed = name.toString().trim(); + + if (trimmed.length() == 0) { + return null; + } + + try { + final File file = new File(_currentFolder, trimmed); + if (file.exists() || file.mkdir()) { + reloadCurrentFolder(); + return file; + } + } catch (SecurityException ignored) { + } + + Toast.makeText(_context, R.string.file_does_not_exist_and_cant_be_created, Toast.LENGTH_LONG).show(); + return null; + } + + /** + * Show a file in the current folder and blink it + * @param file File to blink + * @param recycler RecyclerView which holds the file items + */ + public void showAndBlink(final File file, final RecyclerView recycler) { + final int pos = getFilePosition(file); + final LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager(); + if (manager != null && pos >= 0) { + manager.scrollToPositionWithOffset(pos, 1); + recycler.postDelayed(() -> { + final RecyclerView.ViewHolder holder = recycler.findViewHolderForLayoutPosition(pos); + if (holder != null) { + GsContextUtils.blinkView(holder.itemView); + } + }, 250); + } + } + // Get the position of a file in the current view // -1 if file is not a child of the current directory public int getFilePosition(final File file) { diff --git a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserOptions.java b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserOptions.java index cd68caed8..f814f8031 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserOptions.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/filebrowser/GsFileBrowserOptions.java @@ -71,7 +71,8 @@ public static class Options { upButtonEnable = true, homeButtonEnable = true, cancelButtonEnable = true, - okButtonEnable = true; + okButtonEnable = true, + newDirButtonEnable = true; public GsCallback.b2 fileOverallFilter = (context, file) -> true; @@ -89,11 +90,15 @@ public static class Options { public int contentDescriptionSelected = 0; @StringRes public int contentDescriptionFile = 0; + @StringRes + public int newDirButtonText = 0; @DrawableRes public int homeButtonImage = android.R.drawable.star_big_on; @DrawableRes public int searchButtonImage = android.R.drawable.ic_menu_search; @DrawableRes + public int newDirButtonImage = android.R.drawable.ic_menu_add; + @DrawableRes public int folderImage = android.R.drawable.ic_menu_view; @DrawableRes public int selectedItemImage = android.R.drawable.checkbox_on_background; diff --git a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java index e13aac99b..0575788b6 100644 --- a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java @@ -12,6 +12,7 @@ import static android.graphics.Bitmap.CompressFormat; import android.Manifest; +import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityManager; @@ -55,6 +56,7 @@ import android.net.Uri; import android.os.Build; import android.os.Environment; +import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.SystemClock; import android.os.VibrationEffect; @@ -2511,11 +2513,12 @@ public T showSoftKeyboard(final Activity activity, fi if (activity != null) { final InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); final View focus = (view != null && view.length > 0) ? view[0] : activity.getCurrentFocus(); - if (imm != null && focus != null && focus.getWindowToken() != null) { + final IBinder token = focus != null ? focus.getWindowToken() : null; + if (imm != null && focus != null) { if (show) { - imm.showSoftInput(focus, 0); - } else if (focus.getWindowToken() != null) { - imm.hideSoftInputFromWindow(focus.getWindowToken(), 0); + imm.showSoftInput(focus, InputMethodManager.SHOW_IMPLICIT); + } else if (token != null) { + imm.hideSoftInputFromWindow(token, InputMethodManager.HIDE_IMPLICIT_ONLY); } } } @@ -2821,4 +2824,11 @@ public boolean isDarkModeEnabled(final Context context) { } return false; } + + public static void blinkView(final View view) { + if (view != null) { + final float init = view.getAlpha(); + ObjectAnimator.ofFloat(view, View.ALPHA, init, 0.1f, 1.0f, 0.1f, 1.0f, init).setDuration(1000).start(); + } + } } diff --git a/app/src/main/res/drawable/baseline_create_new_folder_24.xml b/app/src/main/res/drawable/baseline_create_new_folder_24.xml new file mode 100644 index 000000000..df53c39b8 --- /dev/null +++ b/app/src/main/res/drawable/baseline_create_new_folder_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/opoc_filesystem_dialog.xml b/app/src/main/res/layout/opoc_filesystem_dialog.xml index 0891489b8..9b006859c 100644 --- a/app/src/main/res/layout/opoc_filesystem_dialog.xml +++ b/app/src/main/res/layout/opoc_filesystem_dialog.xml @@ -9,97 +9,101 @@ * #########################################################*/ --> - + android:layout_marginTop="4dp" + android:animateLayoutChanges="true"> - - - + android:layout_height="?attr/actionBarSize" + android:background="?attr/colorPrimary" + android:theme="@style/ThemeOverlay.AppCompat.ActionBar"> - - - - - + android:text="" + android:textColor="@android:color/primary_text_dark" + android:textSize="18sp" + android:layout_gravity="center_vertical|start" /> - + + + + + + + + + - + android:padding="4dp"> + tools:text="Select" /> - +