android icon indicating copy to clipboard operation
android copied to clipboard

Search feature for the Android App

Open supportreq opened this issue 10 years ago • 44 comments

Adding a search above the file listing


Edited by @davigonz from here on


We are going to face this in different stages:

1. Local search [DONE]

Here you have a gif showing how the local search looks like

2. Search using API: https://github.com/owncloud/core/issues/25373#issuecomment-400967608

https://github.com/owncloud/core/pull/31873

CC @michaelstingl @jesmrec

supportreq avatar Oct 30 '14 09:10 supportreq

Do you mean a filter function for one folder: Current folder contains 500 files, you type "abc" in filter and it shows only 2 files? (this should be easy, though the right UX should be discussed a bit more).

Or do you want a real search: Searching for "abc" on the server across all folders? Then the results have to be shown with the folder where the file lies... (much more complex)

tobiasKaminsky avatar Oct 30 '14 10:10 tobiasKaminsky

we can start with the first filter.. something which apps like dropbox offers

supportreq avatar Oct 30 '14 10:10 supportreq

I have splitted "filter function" to #696, so this issue is all about real search.

tobiasKaminsky avatar Oct 30 '14 11:10 tobiasKaminsky

e0f31070-643d-11e4-8a07-d28b3a47ae44

@davivel @jancborchardt

Searching is usually done from a "magnifying glass" button in the action bar; the input field is then put in the action bar, replacing the title.

Your proposal is the same like dropbox does it? But I think it would be good to have the folder structure shown. For example on the screenshot no one can distinguish the "test" folder or say where they are located.

tobiasKaminsky avatar Nov 04 '14 16:11 tobiasKaminsky

@tobiasKaminsky then in case of two exactly same folder names in the results we can show the path in parentheses behind it. If the names are all unique, no need to show the path. (This is similar how Sublime Text does it for open files.)

jancborchardt avatar Nov 06 '14 13:11 jancborchardt

@jancborchardt Hmm. My intension to display the path is that the user can navigate next time to the desired file without searching again. Or how would he know, that file "test.jpg" is in /images/wedding/ ? The navigation bar on the top of the display is only displayed when you browse in a folder. But if you would open an image directly you will never know where this file is located in owncloud.

tobiasKaminsky avatar Nov 06 '14 15:11 tobiasKaminsky

@jancborchardt Parentheses? May be "heavy". What about path in smaller text under the name?

@tobiasKaminsky , we can reconsider the preview layout to show the current path in some place.

davivel avatar Nov 06 '14 16:11 davivel

@davivel good call, path in smaller text under the name. Then we can also show it always @tobiasKaminsky

jancborchardt avatar Nov 06 '14 17:11 jancborchardt

Hey guys, any update for this?

supportreq avatar Dec 12 '14 12:12 supportreq

hi, any update for local or remote search feature ?

mahermeg17 avatar Feb 16 '15 15:02 mahermeg17

Hi, Following the sort feature, I added a filter to the FileListListAdapter.java like this :

public void filterByName(String keyName) {
mFilteredFiles=new Vector<OCFile>();
for(OCFile f :mFiles){
if(f.getFileName().contains(keyName)){
mFilteredFiles.add(f);
}
}
mFiles=mFilteredFiles;
Log.d("FileListListAdapter", ">>>notifyDataSetChanged");
notifyDataSetChanged();
Log.d("FileListListAdapter", ">>>notifyDataSetChanged.. OK");
}

and into the FileDisplayActivity.java :

@Override
public boolean onOptionsItemSelected(MenuItem item) {
.....
case R.id.action_search: {
SharedPreferences appPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Read sorting order, default to sort by name ascending
Integer sortOrder = appPreferences.getInt("sortOrder", FileListListAdapter.SORT_NAME);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title");
builder.setMessage("Message");
// Set an EditText view to get user input 
final EditText input = new EditText(this);
builder.setView(input);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String value = input.getText().toString().trim();
filterByName(value);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
builder.show();
break;
}
....
}   

this works and return the filtred list. But at the first sync thread launched after the search, the listview is refreched as it is in the server (not filtred). Shoud I use a new listview result and show in the AlertDialog ? or are there an other easier way ?

mahermeg17 avatar Feb 24 '15 15:02 mahermeg17

Ok, some news.. I added the result of search into a new listview in the same alertbuilder. I use cloned adpater from the FileListListAdapter and delete unused methodes. still now to open selected file/folder into the main app activity ; FileDisplayActivity or FileActivity !! I am confused on this point, any help plz!

mahermeg17 avatar Feb 26 '15 14:02 mahermeg17

OK. it's done. It was more simpler than expected:

resultList.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
                // TODO Auto-generated method stub
                OCFile f= (OCFile) ((FileListFilterAdapter) resultList.getAdapter()).getItem(position);

                Intent showDetailsIntent = new Intent(FileDisplayActivity.this, FileDisplayActivity.class);
                showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, f);
                showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount);
                showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(showDetailsIntent);
            }
        });

please clean up the code and ad it to the next release. And here the search method using a recursive algo :

@SuppressLint("DefaultLocale")
public void filterByName(String keyName) {
    mFilteredFiles = new Vector<OCFile>();
    keyName = keyName.toLowerCase().trim();
    deepFilter(keyName, mFiles);
}

@SuppressLint("DefaultLocale")
public void deepFilter(String keyName, Vector<OCFile> level) {
    for (OCFile f : level) {
        if (f.getFileName().toLowerCase().contains(keyName)) {
            mFilteredFiles.add(f);
            Log.i("deepFilter", ">>find >>> " + f.getFileName());
        } else if (f!=null && f.isFolder()) {
            level = mStorageManager.getFolderContent(f);
            if (!level.isEmpty() && level != null) {
                Log.d("FileListListAdapter", ">>>level=" + level.get(0).getFileId());
                deepFilter(keyName, level);
            }
        }
    }
}

mahermeg17 avatar Feb 26 '15 15:02 mahermeg17

Hi again, I have a little bug when acceding to the file details from my listview containing the results : it's not auto downloaded and opened like the usual main functionality.

mahermeg17 avatar Feb 27 '15 08:02 mahermeg17

Hi, Now I know it's about this code in my FileListFilterAdapter: FileDownloaderBinder downloaderBinder = mTransferServiceGetter.getFileDownloaderBinder(); FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder(); if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) { localStateView.setImageResource(R.drawable.downloading_file_indicator); localStateView.setVisibility(View.VISIBLE); } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) { localStateView.setImageResource(R.drawable.uploading_file_indicator); localStateView.setVisibility(View.VISIBLE); } else if (file.isDown()) { localStateView.setImageResource(R.drawable.local_file_indicator); localStateView.setVisibility(View.VISIBLE); } else { localStateView.setVisibility(View.INVISIBLE); }

so I change the initialisation of the adapter int the OCFileListFragment mFilterAdapter = new FileListFilterAdapter( getSherlockActivity(), mContainerActivity );

and in the FileDisplayActivity case R.id.action_search: { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Recherche"); final Account mAccount = getAccount(); final FileDataStorageManager mStorageManager = new FileDataStorageManager(mAccount, getContentResolver()); LayoutInflater inflater = this.getLayoutInflater(); View dialogView = inflater.inflate(R.layout.list_search_result, null); builder.setView(dialogView); final EditText input = (EditText) dialogView.findViewById(R.id.search_key); final ListView resultList = (ListView) dialogView.findViewById(R.id.search_result_list); final Button search = (Button) dialogView.findViewById(R.id.search_button); resultList.setAdapter(getmFilterAdapter()); resultList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) { // TODO Auto-generated method stub OCFile f= (OCFile) ((FileListFilterAdapter) resultList.getAdapter()).getItem(position); Intent showDetailsIntent = null; if (PreviewImageFragment.canBePreviewed(f)) { showDetailsIntent = new Intent(FileDisplayActivity.this, PreviewImageActivity.class); } else { showDetailsIntent = new Intent(FileDisplayActivity.this, FileDisplayActivity.class); } showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, f); showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); showDetailsIntent.setAction(null); startActivity(showDetailsIntent); } }); search.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { String value = input.getText().toString().trim(); if (!value.isEmpty()) { try { Vector<OCFile> files = getSpacemFiles(); ((FileListFilterAdapter) resultList.getAdapter()).setmAccount(mAccount); ((FileListFilterAdapter) resultList.getAdapter()).setmStorageManager(mStorageManager); ((FileListFilterAdapter) resultList.getAdapter()).setmFiles(files); ((FileListFilterAdapter) resultList.getAdapter()).filterByName(value); ((FileListFilterAdapter) resultList.getAdapter()).notifyDataSetChanged(); } catch (Exception e) { e.printStackTrace(); } } } }); builder.setNegativeButton("Retour", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // Canceled. } }); builder.show(); break; }

but finaly the file is not auto downloaded and shown ...!!?

mahermeg17 avatar Feb 27 '15 09:02 mahermeg17

@DeepDiver1975 Is there a search api in /core? (Sorry, if you are not the right contact person in /core, but you are roughly the only one I know)

tobiasKaminsky avatar Oct 18 '15 09:10 tobiasKaminsky

@DeepDiver1975 Is there a search api in /core? (Sorry, if you are not the right contact person in /core, but you are roughly the only one I know)

Nothing which is usable by the clients (in terms of public api or ready to be used)

DeepDiver1975 avatar Oct 19 '15 08:10 DeepDiver1975

@DeepDiver1975 Thank you for your reply. Is there a related issue in /core, which I can subscribe to? Or should I open one? Then I could also link it to this one.

tobiasKaminsky avatar Oct 19 '15 17:10 tobiasKaminsky

Is there a related issue in /core, which I can subscribe to? Or should I open one?

I'm not aware of one right away - maybe searching github can reveal something. At least there should be an issue about webdav search by @butonic

DeepDiver1975 avatar Oct 19 '15 22:10 DeepDiver1975

There is a research issue where I had a look at hew we could expose our search via webdaf, since there is RFC5323 for it: https://github.com/owncloud/core/pull/12884. See also comment in https://github.com/owncloud/core/issues/12543#issuecomment-67628949

The bottom line is that we should implement a query language that can express RFC5323 DAV:basicsearch parts:

  • DAV:select provides the result record definition.
  • DAV:from defines the scope.
  • DAV:where defines the criteria.
  • DAV:orderby defines the sort order of the result set.
  • DAV:limit provides constraints on the query as a whole.

That at least is my personal opinion.

butonic avatar Oct 20 '15 07:10 butonic

Thank you both for your feedback. Then we will wait until the server part is finished.

tobiasKaminsky avatar Oct 20 '15 18:10 tobiasKaminsky

When will this search feature be released in the latest Android version, will this be included into the iOS version too?

whisere avatar Oct 29 '15 03:10 whisere

As the previous devs said, there is no functionality in the server that will allow searching for now. So this will have to wait. The same is true for the iOS app.

tobiasKaminsky avatar Oct 29 '15 18:10 tobiasKaminsky

Thank you.

whisere avatar Oct 30 '15 03:10 whisere

As /core needs some time to get the search api, I would like to add the search in the current folder. This could look like https://github.com/owncloud/android/issues/695#issuecomment-61665708. @jancborchardt @davivel is this ok?

tobiasKaminsky avatar Feb 08 '16 08:02 tobiasKaminsky

Yeah, we can have a filter of the current folder first, and then search of the rest later. Kind of like in the web interface where the current folder is filtered and other results show below.

jancborchardt avatar Feb 08 '16 15:02 jancborchardt

@tobiasKaminsky is this in beta?

supportreq avatar Apr 11 '16 11:04 supportreq

No... There is no pull request so far. But when there is one, I will include it into beta.

tobiasKaminsky avatar Apr 14 '16 19:04 tobiasKaminsky

Some core efforts are needed before:

owncloud/core#13915

davigonz avatar Jan 22 '18 14:01 davigonz

@davigonz i think we should add the feature to search locally for documents of a certain type example pdf, images, videos and files. Also, is the feature of local search being implemented?

harshitbansal05 avatar Feb 06 '18 19:02 harshitbansal05