Applies search

This commit is contained in:
stom79 2017-11-23 19:18:40 +01:00
parent e74a273f97
commit 03c119e367
12 changed files with 236 additions and 50 deletions

View File

@ -24,10 +24,14 @@ import android.view.View;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import fr.gouv.etalab.mastodon.R;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveSearchAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveTootsAsyncTask;
import fr.gouv.etalab.mastodon.client.APIResponse;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.Entities.Error;
import fr.gouv.etalab.mastodon.client.Entities.Results;
@ -35,7 +39,7 @@ import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.drawers.SearchListAdapter;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchStatusInterface;
/**
@ -43,7 +47,7 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchInterface;
* Show search results within two tabs: Toots and accounts
*/
public class SearchResultActivity extends AppCompatActivity implements OnRetrieveSearchInterface {
public class SearchResultActivity extends AppCompatActivity implements OnRetrieveSearchInterface, OnRetrieveSearchStatusInterface {
private String search;
@ -68,8 +72,11 @@ public class SearchResultActivity extends AppCompatActivity implements OnRetriev
Bundle b = getIntent().getExtras();
if(b != null){
search = b.getString("search");
if( search != null)
boolean tootOnly = b.getBoolean("tootOnly", false);
if( !tootOnly && search != null)
new RetrieveSearchAsyncTask(getApplicationContext(), search.trim(), SearchResultActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else if(tootOnly)
new RetrieveTootsAsyncTask(getApplicationContext(), search.trim(), SearchResultActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
Toast.makeText(this,R.string.toast_error_search,Toast.LENGTH_LONG).show();
}else{
@ -124,5 +131,23 @@ public class SearchResultActivity extends AppCompatActivity implements OnRetriev
}
@Override
public void onRetrieveSearchStatus(APIResponse apiResponse, Error error) {
loader.setVisibility(View.GONE);
if( apiResponse.getError() != null){
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean show_error_messages = sharedpreferences.getBoolean(Helper.SET_SHOW_ERROR_MESSAGES, true);
if( show_error_messages)
Toast.makeText(getApplicationContext(), error.getError(),Toast.LENGTH_LONG).show();
return;
}
lv_search.setVisibility(View.VISIBLE);
List<String> tags = new ArrayList<>();
List<Account> accounts = new ArrayList<>();
List<Status> statuses = apiResponse.getStatuses();
SearchListAdapter searchListAdapter = new SearchListAdapter(SearchResultActivity.this, statuses, accounts, tags);
lv_search.setAdapter(searchListAdapter);
searchListAdapter.notifyDataSetChanged();
}
}

View File

@ -0,0 +1,59 @@
/* Copyright 2017 Thomas Schneider
*
* This file is a part of Mastalab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Mastalab; if not,
* see <http://www.gnu.org/licenses>. */
package fr.gouv.etalab.mastodon.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.APIResponse;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchStatusInterface;
/**
* Created by Thomas on 22/11/2017.
* Retrieves toots from search
*/
public class RetrieveTootsAsyncTask extends AsyncTask<Void, Void, Void> {
private String query;
private APIResponse apiResponse;
private OnRetrieveSearchStatusInterface listener;
private API api;
private WeakReference<Context> contextReference;
public RetrieveTootsAsyncTask(Context context, String query, OnRetrieveSearchStatusInterface onRetrieveSearchStatusInterface){
this.contextReference = new WeakReference<>(context);
this.query = query;
this.listener = onRetrieveSearchStatusInterface;
}
@Override
protected Void doInBackground(Void... params) {
api = new API(this.contextReference.get());
apiResponse = api.searchStatus(query, 40);
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrieveSearchStatus(apiResponse, api.getError());
}
}

View File

@ -1133,6 +1133,39 @@ public class API {
return apiResponse;
}
/**
* Retrieves Accounts when searching (ie: via @...) *synchronously*
*
* @param query String search
* @return APIResponse
*/
public APIResponse searchStatus(String query, int count) {
HashMap<String, String> params = new HashMap<>();
params.put("q", query);
if( count < 5)
count = 5;
if( count > 40 )
count = 40;
params.put("limit", String.valueOf(count));
try {
HttpsConnection httpsConnection = new HttpsConnection();
String response = httpsConnection.get(getAbsoluteUrl("/statuses/search"), 60, params, null);
statuses = parseStatuses(new JSONArray(response));
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
}catch (Exception e) {
setDefaultError();
e.printStackTrace();
}
apiResponse.setStatuses(statuses);
return apiResponse;
}
/**
* Parse json response an unique account
* @param resobj JSONObject

View File

@ -16,14 +16,22 @@ package fr.gouv.etalab.mastodon.drawers;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
import fr.gouv.etalab.mastodon.R;
import fr.gouv.etalab.mastodon.activities.SearchResultActivity;
import fr.gouv.etalab.mastodon.sqlite.SearchDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
/**
@ -34,10 +42,14 @@ public class SearchTootsListAdapter extends BaseAdapter {
private List<String> searches;
private LayoutInflater layoutInflater;
private Context context;
private SearchTootsListAdapter searchTootsListAdapter;
public SearchTootsListAdapter(Context context, List<String> searches){
this.searches = searches;
layoutInflater = LayoutInflater.from(context);
this.context = context;
this.searchTootsListAdapter = this;
}
@Override
@ -59,21 +71,52 @@ public class SearchTootsListAdapter extends BaseAdapter {
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final String tag = searches.get(position);
final String search = searches.get(position);
final ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.drawer_search, parent, false);
holder = new ViewHolder();
holder.search_title = convertView.findViewById(R.id.search_keyword);
holder.search_container = convertView.findViewById(R.id.search_container);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.search_title.setText(tag);
holder.search_title.setText(search);
holder.search_title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, SearchResultActivity.class);
intent.putExtra("search", search);
intent.putExtra("tootOnly", true);
context.startActivity(intent);
}
});
final SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
holder.search_container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.delete + ": " + search);
builder.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new SearchDAO(context, db).remove(search.trim());
searches.remove(search);
searchTootsListAdapter.notifyDataSetChanged();
dialog.dismiss();
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
}
});
return convertView;
@ -81,6 +124,7 @@ public class SearchTootsListAdapter extends BaseAdapter {
private class ViewHolder {
LinearLayout search_container;
TextView search_title;
}

View File

@ -23,16 +23,20 @@ import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.List;
import fr.gouv.etalab.mastodon.activities.MainActivity;
import fr.gouv.etalab.mastodon.drawers.SearchTootsListAdapter;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.sqlite.SearchDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import fr.gouv.etalab.mastodon.R;
@ -51,7 +55,7 @@ public class DisplaySearchFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_drafts, container, false);
View rootView = inflater.inflate(R.layout.fragment_search, container, false);
context = getContext();
final ListView lv_search_toots = rootView.findViewById(R.id.lv_search_toots);
@ -61,11 +65,13 @@ public class DisplaySearchFragment extends Fragment {
mainLoader.setVisibility(View.VISIBLE);
final SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<String> searches = new SearchDAO(context, db).getAllSearch();
if( searches != null && searches.size() > 0) {
searchTootsListAdapter = new SearchTootsListAdapter(context, searches);
lv_search_toots.setAdapter(searchTootsListAdapter);
searchTootsListAdapter.notifyDataSetChanged();
}else {
if( searches == null)
searches = new ArrayList<>();
Log.v(Helper.TAG,"searches: " + searches);
searchTootsListAdapter = new SearchTootsListAdapter(context, searches);
lv_search_toots.setAdapter(searchTootsListAdapter);
searchTootsListAdapter.notifyDataSetChanged();
if( searches.size() == 0) {
textviewNoAction.setVisibility(View.VISIBLE);
}
mainLoader.setVisibility(View.GONE);
@ -77,43 +83,32 @@ public class DisplaySearchFragment extends Fragment {
add_new.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.search);
builder.setIcon(android.R.drawable.ic_menu_search)
.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogConfirm, int which) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
LayoutInflater inflater = getLayoutInflater();
@SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.search_toot, null);
dialogBuilder.setView(dialogView);
final EditText editText = dialogView.findViewById(R.id.search_toot);
dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
String keyword = editText.getText().toString().trim();
//Already in db
List<String> searches = new SearchDAO(context, db).getSearchByKeyword(keyword);
if( searches.size() > 0){
return;
}
new SearchDAO(context, db).insertSearch(keyword);
searches.add(keyword);
searchTootsListAdapter.notifyDataSetChanged();
}
});
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogConfirm, int which) {
dialogConfirm.dismiss();
}
})
.show();
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
LayoutInflater inflater = getLayoutInflater();
@SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.search_toot, null);
dialogBuilder.setView(dialogView);
final EditText editText = dialogView.findViewById(R.id.search_toot);
dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
String keyword = editText.getText().toString().trim();
//Empty
if( keyword.length() == 0)
return;
//Already in db
List<String> searches = new SearchDAO(context, db).getSearchByKeyword(keyword);
if( searches == null)
searches = new ArrayList<>();
if( searches.size() > 0){
return;
}
new SearchDAO(context, db).insertSearch(keyword);
searches.add(keyword);
searchTootsListAdapter.notifyDataSetChanged();
}
});
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
}
});
return rootView;

View File

@ -0,0 +1,26 @@
/* Copyright 2017 Thomas Schneider
*
* This file is a part of Mastalab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Mastalab; if not,
* see <http://www.gnu.org/licenses>. */
package fr.gouv.etalab.mastodon.interfaces;
import fr.gouv.etalab.mastodon.client.APIResponse;
import fr.gouv.etalab.mastodon.client.Entities.Error;
/**
* Created by Thomas on 22/11/2017.
* Interface for search
*/
public interface OnRetrieveSearchStatusInterface {
void onRetrieveSearchStatus(APIResponse apiResponse, Error error);
}

View File

@ -18,13 +18,12 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/account_container"
android:id="@+id/search_container"
android:orientation="vertical">
<TextView
android:drawableRight="@drawable/ic_keyboard_arrow_right"
android:drawableEnd="@drawable/ic_keyboard_arrow_right"
android:id="@+id/search_keyword"
android:visibility="gone"
android:textSize="18sp"
android:background="?attr/colorAccent"
android:paddingBottom="10dp"

View File

@ -433,4 +433,5 @@
<string name="live_notif">Live notifications</string>
<string name="filter_regex">Mit regulären Ausdrücken filtern</string>
<string name="search">Suche</string>
<string name="delete">Löschen</string>
</resources>

View File

@ -441,4 +441,5 @@
<string name="filter_regex">Filtrer avec une expression rationnelle</string>
<string name="search">Rechercher</string>
<string name="delete">Supprimer</string>
</resources>

View File

@ -437,4 +437,5 @@
<string name="live_notif">Live notifications</string>
<string name="filter_regex">Wegfilteren met reguliere expressies</string>
<string name="search">Zoeken</string>
<string name="delete">Verwijderen</string>
</resources>

View File

@ -439,4 +439,5 @@
<string name="live_notif">Live notifications</string>
<string name="filter_regex">Filtrar com uma expressão regular</string>
<string name="search">Pesquisar</string>
<string name="delete">Eliminar</string>
</resources>

View File

@ -446,4 +446,5 @@
<string name="filter_regex">Filter out by regular expressions</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
</resources>