android
android copied to clipboard
Search feature for the Android App
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
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)
we can start with the first filter.. something which apps like dropbox offers
I have splitted "filter function" to #696, so this issue is all about real search.
@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 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 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.
@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 good call, path in smaller text under the name. Then we can also show it always @tobiasKaminsky
Hey guys, any update for this?
hi, any update for local or remote search feature ?
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 ?
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!
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);
}
}
}
}
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.
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 ...!!?
@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)
@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 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.
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
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.
Thank you both for your feedback. Then we will wait until the server part is finished.
When will this search feature be released in the latest Android version, will this be included into the iOS version too?
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.
Thank you.
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?
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.
@tobiasKaminsky is this in beta?
No... There is no pull request so far. But when there is one, I will include it into beta.
Some core efforts are needed before:
owncloud/core#13915
@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?