Compare commits

...

33 Commits

Author SHA1 Message Date
Denis Karmyshakov 8c88db932f
Merge pull request #9 from TouchInstinct/gradle_update
Gradle update
2018-08-13 19:59:27 +03:00
Denis Karmyshakov 4c8da7ac45 Gradle update 2018-08-13 19:58:00 +03:00
Gavriil Sitnikov e4d4689ff3
Merge pull request #8 from TouchInstinct/gradle_update
Removing build tools
2017-11-20 19:29:02 +03:00
Denis Karmyshakov ee07f6c69d Removing build tools 2017-11-20 19:27:12 +03:00
Антон 60d9fa3ad8 Merge pull request #7 from TouchInstinct/pptx
add pptx
2017-09-07 19:54:31 +03:00
Arseniy Borisov d7169ddd85 add pptx 2017-09-07 19:51:43 +03:00
Gavriil 02f6ecf4a8 Merge pull request #6 from TouchInstinct/chat_android_no_target_api
Chat android no target api
2017-08-04 16:05:11 +03:00
Elena Bobkova c771a2adeb .ppt extension allowed 2017-08-04 15:52:19 +03:00
Elena 97896e5387 removed target api 2017-07-01 22:15:37 +03:00
Gavriil 341272e5ef Merge pull request #5 from TouchInstinct/fix/ellipsize_start_fix
ellipsize start bug workaround
2017-05-04 18:25:50 +03:00
Elena Bobkova c66b3c8ea6 ellipsize start bug workaround 2017-05-04 18:20:00 +03:00
Gavriil df7e6cd34d Merge pull request #4 from TouchInstinct/fix/lib_update
build tools update
2017-05-04 14:47:44 +03:00
Elena Bobkova 2c5635e4d1 lib update 2017-05-03 22:41:05 +03:00
Gavriil ec53246057 Merge pull request #3 from TouchInstinct/feature/filter_for_file_extension
Feature/filter for file extension
2017-04-06 19:16:09 +03:00
Arhipov 4ab65e90fd static 2017-04-06 19:01:39 +03:00
Arhipov cc5d9fe06a merge branch 'feature/purge' 2017-04-06 18:56:41 +03:00
contrudar 867b71ba6d fix the bug SECRETCHAT-832 2016-10-21 13:31:11 +03:00
contrudar 7b4d77d252 Merge branch 'feature/filter_for_file_extension' of github.com:contrudar/NoNonsense-FilePicker into feature/filter_for_file_extension 2016-10-19 17:27:01 +03:00
contrudar 2364dfb58b fix the bug SECRETCHAT-828 2016-10-19 17:26:29 +03:00
Alex Urzhumtcev 770d1282b4 Merge pull request #2 from TouchInstinct/bug_fix
fix the bug SECRETCHAT-829
2016-10-19 13:47:51 +03:00
contrudar 62be967de8 fix the bug SECRETCHAT-829 2016-10-19 13:45:30 +03:00
contrudar 2cdfe13357 remove tests 2016-10-10 17:20:48 +03:00
Alex Urzhumtcev 6a42d88efb Merge pull request #1 from TouchInstinct/feature/fix_of_file_extensions
ignore case of extensions
2016-10-08 01:15:42 +03:00
Alex Urzhumtcev 7870a8fc7d ignore case of extensions 2016-10-08 01:09:00 +03:00
contrudar e17121c143 dismiss dialog fragment when we click on a file or Cancel button 2016-10-04 16:28:37 +03:00
contrudar bc7755aee1 make DialogFragment from Fragment File Picker 2016-10-04 16:17:04 +03:00
contrudar f187c04368 return activity as a listener instead of a target fragment 2016-10-04 14:24:53 +03:00
Alex Urzhumtcev 69f9050c3c work through target fragment 2016-10-04 02:36:51 +03:00
Alex Urzhumtcev a24496b132 try to fix style bug 2016-10-04 02:10:50 +03:00
contrudar 17bab40222 get rid of the activites 2016-10-03 19:53:43 +03:00
contrudar aba30dc710 handle onBackPressed() in Fragment 2016-09-30 19:08:08 +03:00
contrudar d488178c90 don't check a directory in depth 2016-09-27 23:12:29 +03:00
contrudar 5404a689ff filter files and folders by a file extension 2016-09-27 22:28:22 +03:00
8 changed files with 112 additions and 155 deletions

View File

@ -6,18 +6,15 @@ apply plugin: 'com.android.library'
*/
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
compileSdkVersion compileSdk
defaultConfig {
minSdkVersion 9
targetSdkVersion 25
minSdkVersion 16
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:support-v4:25.3.1'
compile 'com.android.support:recyclerview-v7:25.3.1'
implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
implementation "com.android.support:support-v4:$supportLibraryVersion"
implementation "com.android.support:recyclerview-v7:$supportLibraryVersion"
}

View File

@ -14,9 +14,10 @@ import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.util.SortedList;
@ -116,54 +117,11 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
return new FileItemAdapter<>(this);
}
/**
* Set before making the fragment visible. This method will re-use the existing
* arguments bundle in the fragment if it exists so extra arguments will not
* be overwritten. This allows you to set any extra arguments in the fragment
* constructor if you wish.
* <p/>
* The key/value-pairs listed below will be overwritten however.
*
* @param startPath path to directory the picker will show upon start
* @param mode what is allowed to be selected (dirs, files, both)
* @param allowMultiple selecting a single item or several?
* @param allowDirCreate can new directories be created?
* @param allowExistingFile if selecting a "new" file, can existing files be chosen
* @param singleClick selecting an item does not require a press on OK
*/
public void setArgs(@Nullable final String startPath, final int mode,
final boolean allowMultiple, final boolean allowDirCreate,
final boolean allowExistingFile, final boolean singleClick) {
// Validate some assumptions so users don't get surprised (or get surprised early)
if (mode == MODE_NEW_FILE && allowMultiple) {
throw new IllegalArgumentException(
"MODE_NEW_FILE does not support 'allowMultiple'");
}
// Single click only makes sense if we are not selecting multiple items
if (singleClick && allowMultiple) {
throw new IllegalArgumentException("'singleClick' can not be used with 'allowMultiple'");
}
// There might have been arguments set elsewhere, if so do not overwrite them.
Bundle b = getArguments();
if (b == null) {
b = new Bundle();
}
if (startPath != null) {
b.putString(KEY_START_PATH, startPath);
}
b.putBoolean(KEY_ALLOW_DIR_CREATE, allowDirCreate);
b.putBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
b.putBoolean(KEY_ALLOW_EXISTING_FILE, allowExistingFile);
b.putBoolean(KEY_SINGLE_CLICK, singleClick);
b.putInt(KEY_MODE, mode);
setArguments(b);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflateRootView(inflater, container);
getContext().getTheme().applyStyle(getStyleId(), true);
final View view = inflater.inflate(R.layout.nnf_fragment_filepicker, container, false);
Toolbar toolbar = (Toolbar) view.findViewById(R.id.nnf_picker_toolbar);
if (toolbar != null) {
@ -192,11 +150,11 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
});
view.findViewById(R.id.nnf_button_ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
onClickOk(v);
}
});
@Override
public void onClick(final View v) {
onClickOk(v);
}
});
view.findViewById(R.id.nnf_button_ok_newfile).setOnClickListener(
new View.OnClickListener() {
@Override
@ -236,10 +194,6 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
return view;
}
protected View inflateRootView(LayoutInflater inflater, ViewGroup container) {
return inflater.inflate( R.layout.nnf_fragment_filepicker, container, false);
}
/**
* Checks if a divider drawable has been defined in the current theme. If it has, will apply
* an item decoration with the divider. If no divider has been specified, then does nothing.
@ -264,6 +218,7 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
public void onClickCancel(@NonNull View view) {
if (mListener != null) {
mListener.onCancelled();
dismiss();
}
}
@ -321,10 +276,10 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
mListener.onFilePicked(toUri(getFirstCheckedItem()));
}
}
dismiss();
}
/**
*
* @return filename as entered/picked by the user for the new file
*/
@NonNull
@ -386,10 +341,15 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@ -409,6 +369,7 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Only if we have no state
if (mCurrentPath == null) {
if (savedInstanceState != null) {
@ -451,25 +412,27 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
}
}
setModeView();
setModeView(getView());
// If still null
if (mCurrentPath == null) {
mCurrentPath = getRoot();
}
refresh(mCurrentPath);
}
/**
* Hides/Shows appropriate views depending on mode
*/
protected void setModeView() {
protected void setModeView(@NonNull View view) {
boolean nf = mode == MODE_NEW_FILE;
mNewFileButtonContainer.setVisibility(nf ? View.VISIBLE : View.GONE);
mRegularButtonContainer.setVisibility(nf ? View.GONE : View.VISIBLE);
if (!nf && singleClick) {
getActivity().findViewById(R.id.nnf_button_ok).setVisibility(View.GONE);
view.findViewById(R.id.nnf_button_ok).setVisibility(View.GONE);
}
}
@ -507,12 +470,6 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
b.putInt(KEY_MODE, mode);
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* Refreshes the list. Call this when current path changes. This method also checks
* if permissions are granted and requests them if necessary. See hasPermission()
@ -628,6 +585,7 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v;
getContext().getTheme().applyStyle(getStyleId(), true);
switch (viewType) {
case LogicHandler.VIEWTYPE_HEADER:
v = LayoutInflater.from(getActivity()).inflate(R.layout.nnf_filepicker_listitem_dir,
@ -645,6 +603,9 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
}
}
@StyleRes
protected abstract int getStyleId();
/**
* @param vh to bind data from either a file or directory
* @param position 0 - n, where the header has been subtracted
@ -866,6 +827,7 @@ public abstract class AbstractFilePickerFragment<T> extends DialogFragment
v.setOnLongClickListener(this);
icon = v.findViewById(R.id.item_icon);
text = (TextView) v.findViewById(android.R.id.text1);
text.setTextColor(ContextCompat.getColor(getActivity(), android.R.color.white));
}
/**

View File

@ -1,33 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.nononsenseapps.filepicker;
import android.annotation.SuppressLint;
import android.os.Environment;
import android.support.annotation.Nullable;
import java.io.File;
@SuppressLint("Registered")
public class FilePickerActivity extends AbstractFilePickerActivity<File> {
public FilePickerActivity() {
super();
}
@Override
protected AbstractFilePickerFragment<File> getFragment(
@Nullable final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir, final boolean allowExistingFile,
final boolean singleClick) {
AbstractFilePickerFragment<File> fragment = new FilePickerFragment();
// startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
fragment.setArgs(startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
mode, allowMultiple, allowCreateDir, allowExistingFile, singleClick);
return fragment;
}
}

View File

@ -19,26 +19,27 @@ import android.support.v7.widget.util.SortedListAdapterCallback;
import android.widget.Toast;
import java.io.File;
import java.util.Locale;
/**
* An implementation of the picker which allows you to select a file from the internal/external
* storage (SD-card) on a device.
*/
public class FilePickerFragment extends AbstractFilePickerFragment<File> {
public abstract class FilePickerFragment extends AbstractFilePickerFragment<File> {
private static final String[] extensions = new String[]{".doc", ".docx", ".xlsx", ".xls", ".png", ".jpg",
".tif", ".tiff", ".pdf", ".jpeg", ".ppt", ".pptx"};
protected static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
protected boolean showHiddenItems = false;
private File mRequestedPath = null;
public FilePickerFragment() {
}
/**
* This method is used to dictate whether hidden files and folders should be shown or not
*
* @param showHiddenItems whether hidden items should be shown or not
*/
public void showHiddenItems(boolean showHiddenItems){
public void showHiddenItems(boolean showHiddenItems) {
this.showHiddenItems = showHiddenItems;
}
@ -48,7 +49,7 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
* @return true if hidden items are shown, otherwise false
*/
public boolean areHiddenItemsShown(){
public boolean areHiddenItemsShown() {
return showHiddenItems;
}
@ -95,6 +96,7 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
// Treat this as a cancel press
if (mListener != null) {
mListener.onCancelled();
dismiss();
}
} else { // if (requestCode == PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE) {
if (PackageManager.PERMISSION_GRANTED == grantResults[0]) {
@ -108,6 +110,7 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
// Treat this as a cancel press
if (mListener != null) {
mListener.onCancelled();
dismiss();
}
}
}
@ -236,7 +239,7 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
files.beginBatchedUpdates();
if (listFiles != null) {
for (java.io.File f : listFiles) {
if (isItemVisible(f)) {
if (isItemVisible(f) && directoryHasNeededFiles(f)) {
files.add(f);
}
}
@ -292,6 +295,23 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
};
}
private boolean directoryHasNeededFiles(@NonNull final File file) {
final File[] fileList = file.listFiles();
if (fileList == null) {
return isNeededExtension(file.toString());
}
return true;
}
private boolean isNeededExtension(@NonNull final String fileName) {
for (final String extension : extensions) {
if (fileName.endsWith(extension) || fileName.endsWith(extension.toUpperCase(Locale.getDefault()))) {
return true;
}
}
return false;
}
/**
* Name is validated to be non-null, non-empty and not containing any
* slashes.
@ -348,4 +368,5 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
return lhs.getName().compareToIgnoreCase(rhs.getName());
}
}
}

View File

@ -6,22 +6,23 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/edit_text"
style="?android:textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="48dp"
android:fontFamily="light"
android:padding="4dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:hint="@string/nnf_name"
android:fontFamily="light"
android:maxLines="1"
android:gravity="center_vertical"
android:hint="@string/nnf_name"
android:imeOptions="actionDone"
style="?android:textAppearanceMedium"
android:inputType="textAutoComplete|textAutoCorrect"
tools:ignore="UnusedAttribute" />
android:padding="4dp"
tools:ignore="UnusedAttribute"/>
</FrameLayout>

View File

@ -5,17 +5,17 @@
~ License, v. 2.0. If a copy of the MPL was not distributed with this
~ file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nnf_item_container"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeight"
android:background="?selectableItemBackground"
android:focusable="true"
android:minHeight="?android:listPreferredItemHeight"
android:nextFocusLeft="@+id/nnf_button_cancel"
android:nextFocusRight="@id/checkbox"
android:orientation="horizontal">
<LinearLayout android:id="@+id/nnf_item_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeight"
android:background="?selectableItemBackground"
android:focusable="true"
android:minHeight="?android:listPreferredItemHeight"
android:nextFocusLeft="@+id/nnf_button_cancel"
android:nextFocusRight="@id/checkbox"
android:orientation="horizontal">
<!--suppress AndroidDomInspection -->
@ -38,6 +38,7 @@
android:layout_weight="1"
android:ellipsize="end"
android:gravity="center_vertical"
android:textColor="@android:color/black"
android:maxLines="1"
android:padding="8dp"
android:text="@string/nnf_name" />
@ -50,6 +51,6 @@
android:nextFocusRight="@+id/nnf_button_ok"
android:paddingEnd="8dp"
android:paddingRight="8dp"
tools:ignore="RtlSymmetry" />
tools:ignore="RtlSymmetry"/>
</LinearLayout>

View File

@ -5,17 +5,17 @@
~ License, v. 2.0. If a copy of the MPL was not distributed with this
~ file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nnf_item_container"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeight"
android:background="?selectableItemBackground"
android:focusable="true"
android:minHeight="?android:listPreferredItemHeight"
android:nextFocusLeft="@+id/nnf_button_cancel"
android:nextFocusRight="@+id/nnf_button_ok"
android:orientation="horizontal">
<LinearLayout android:id="@+id/nnf_item_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeight"
android:background="?selectableItemBackground"
android:focusable="true"
android:minHeight="?android:listPreferredItemHeight"
android:nextFocusLeft="@+id/nnf_button_cancel"
android:nextFocusRight="@+id/nnf_button_ok"
android:orientation="horizontal">
<!--suppress AndroidDomInspection -->
<ImageView
@ -27,7 +27,7 @@
android:src="@drawable/nnf_ic_folder_black_48dp"
android:tint="?attr/nnf_dir_icon_color"
android:visibility="visible"
tools:ignore="ContentDescription,VectorDrawableCompat" />
tools:ignore="ContentDescription,VectorDrawableCompat"/>
<TextView
android:id="@android:id/text1"
@ -37,7 +37,8 @@
android:layout_weight="1"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:padding="8dp"
android:text="@string/nnf_name" />
android:text="@string/nnf_name"
android:textColor="@android:color/white"/>
</LinearLayout>

View File

@ -7,10 +7,9 @@
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FilePickerActivity">
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/nnf_picker_toolbar"
@ -26,8 +25,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="start"
android:maxLines="1"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:maxLines="1"/>
tools:ignore="Deprecated"/>
<!--
suppressing deprecation of singleLine to fix crash related to ellipsize="start", see bug:
https://issuetracker.google.com/issues/36950033
-->
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
@ -58,7 +63,8 @@
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@android:string/cancel"/>
android:text="@android:string/cancel"
android:textColor="@android:color/white"/>
<Button
android:id="@+id/nnf_button_ok"
@ -66,7 +72,8 @@
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@android:string/ok"/>
android:text="@android:string/ok"
android:textColor="@android:color/white"/>
</LinearLayout>