Cross bookmark

This commit is contained in:
stom79 2018-09-28 19:35:13 +02:00
parent 35c46a0187
commit 0159764a35
6 changed files with 180 additions and 3 deletions

View File

@ -43,7 +43,6 @@ import android.text.Spannable;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MenuItem;
@ -640,6 +639,13 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
}
}
});
holder.status_bookmark.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
CrossActions.doCrossBookmark(context, status, statusListAdapter);
return false;
}
});
holder.status_content_translated.setMovementMethod(LinkMovementMethod.getInstance());
//-------- END -> Manages translations
@ -1201,6 +1207,16 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
popup.getMenu().findItem(R.id.action_timed_mute).setVisible(false);
}
}
MenuItem itemBookmark = popup.getMenu().findItem(R.id.action_bookmark);
if( itemBookmark.getActionView() != null)
itemBookmark.getActionView().setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
CrossActions.doCrossBookmark(context, status, statusListAdapter);
return true;
}
});
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
AlertDialog.Builder builderInner;
@ -1951,7 +1967,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
}
}
private void notifyStatusChanged(Status status){
public void notifyStatusChanged(Status status){
for (int i = 0; i < statusListAdapter.getItemCount(); i++) {
//noinspection ConstantConditions
if (statusListAdapter.getItemAt(i) != null && statusListAdapter.getItemAt(i).getId().equals(status.getId())) {

View File

@ -44,10 +44,12 @@ import fr.gouv.etalab.mastodon.client.Entities.Mention;
import fr.gouv.etalab.mastodon.client.Entities.Results;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.drawers.AccountsSearchAdapter;
import fr.gouv.etalab.mastodon.drawers.StatusListAdapter;
import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import fr.gouv.etalab.mastodon.R;
import fr.gouv.etalab.mastodon.sqlite.StatusCacheDAO;
/**
* Will handle cross actions between accounts boost/favourites/pin and replies
@ -275,6 +277,89 @@ public class CrossActions {
}
public static void doCrossBookmark(final Context context, final Status status, StatusListAdapter statusListAdapter ){
List<Account> accounts = connectedAccounts(context, status, false);
if( accounts.size() == 1) {
status.setBookmarked(!status.isBookmarked());
try {
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
if (status.isBookmarked()) {
new StatusCacheDAO(context, db).insertStatus(StatusCacheDAO.BOOKMARK_CACHE, status);
Toast.makeText(context, R.string.status_bookmarked, Toast.LENGTH_LONG).show();
} else {
new StatusCacheDAO(context, db).remove(StatusCacheDAO.BOOKMARK_CACHE, status);
Toast.makeText(context, R.string.status_unbookmarked, Toast.LENGTH_LONG).show();
}
statusListAdapter.notifyStatusChanged(status);
}catch (Exception e){
e.printStackTrace();
Toast.makeText(context, R.string.toast_error, Toast.LENGTH_LONG).show();
}
}else {
AlertDialog.Builder builderSingle = new AlertDialog.Builder(context);
builderSingle.setTitle(context.getString(R.string.choose_accounts));
final AccountsSearchAdapter accountsSearchAdapter = new AccountsSearchAdapter(context, accounts, true);
final Account[] accountArray = new Account[accounts.size()];
int i = 0;
for(Account account: accounts){
accountArray[i] = account;
i++;
}
builderSingle.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builderSingle.setAdapter(accountsSearchAdapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, int which) {
final Account account = accountArray[which];
new AsyncTask<Void, Void, Void>() {
private WeakReference<Context> contextReference = new WeakReference<>(context);
Results response;
@Override
protected void onPreExecute() {
Toast.makeText(contextReference.get(), R.string.retrieve_remote_status, Toast.LENGTH_SHORT).show();
}
@Override
protected Void doInBackground(Void... voids) {
API api = new API(contextReference.get(), account.getInstance(), account.getToken());
response = api.search(status.getUrl());
return null;
}
@Override
protected void onPostExecute(Void result) {
if( response == null){
Toast.makeText(contextReference.get(),R.string.toast_error,Toast.LENGTH_LONG).show();
return;
}
List<fr.gouv.etalab.mastodon.client.Entities.Status> statuses = response.getStatuses();
if( statuses != null && statuses.size() > 0) {
final SQLiteDatabase db = Sqlite.getInstance(contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
fr.gouv.etalab.mastodon.client.Entities.Status statusBookmarked = new StatusCacheDAO(contextReference.get(), db).getStatus(StatusCacheDAO.BOOKMARK_CACHE, statuses.get(0).getId(), account.getId(), account.getInstance());
if (statusBookmarked == null) {
new StatusCacheDAO(contextReference.get(), db).insertStatus(StatusCacheDAO.BOOKMARK_CACHE, statuses.get(0), account.getId(), account.getInstance());
Toast.makeText(contextReference.get(), R.string.status_bookmarked, Toast.LENGTH_LONG).show();
} else {
new StatusCacheDAO(contextReference.get(), db).remove(StatusCacheDAO.BOOKMARK_CACHE, statuses.get(0), account.getId(), account.getInstance());
Toast.makeText(contextReference.get(), R.string.status_unbookmarked, Toast.LENGTH_LONG).show();
}
statusListAdapter.notifyStatusChanged(statuses.get(0));
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR );
}
});
builderSingle.show();
}
}
public static void doCrossReply(final Context context, final Status status, final RetrieveFeedsAsyncTask.Type type, boolean limitedToOwner){
List<Account> accounts = connectedAccounts(context, status, limitedToOwner);
@ -282,7 +367,7 @@ public class CrossActions {
if( accounts.size() == 1 && type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE) {
Intent intent = new Intent(context, TootActivity.class);
Bundle b = new Bundle();
if( status.getReblog() != null )
if( status != null && status.getReblog() != null )
b.putParcelable("tootReply", status.getReblog());
else
b.putParcelable("tootReply", status);

View File

@ -50,6 +50,53 @@ public class StatusCacheDAO {
//------- INSERTIONS -------
/**
* Insert a status in database
* @param cacheType int cache type
* @param status Status
* @param userId String
* @return boolean
*/
public long insertStatus(int cacheType, Status status, String userId, String instance) {
ContentValues values = new ContentValues();
values.put(Sqlite.COL_USER_ID, userId);
values.put(Sqlite.COL_CACHED_ACTION, cacheType);
values.put(Sqlite.COL_INSTANCE, instance);
values.put(Sqlite.COL_STATUS_ID, status.getId());
values.put(Sqlite.COL_URI, status.getUri());
values.put(Sqlite.COL_URL, status.getUrl());
values.put(Sqlite.COL_ACCOUNT, Helper.accountToStringStorage(status.getAccount()));
values.put(Sqlite.COL_IN_REPLY_TO_ID, status.getIn_reply_to_id());
values.put(Sqlite.COL_IN_REPLY_TO_ACCOUNT_ID, status.getIn_reply_to_account_id());
values.put(Sqlite.COL_REBLOG, status.getReblog()!=null?Helper.statusToStringStorage(status.getReblog()):null);
values.put(Sqlite.COL_CONTENT, status.getContent());
values.put(Sqlite.COL_EMOJIS, status.getEmojis()!=null?Helper.emojisToStringStorage(status.getEmojis()):null);
values.put(Sqlite.COL_REBLOGS_COUNT, status.getReblogs_count());
values.put(Sqlite.COL_FAVOURITES_COUNT, status.getFavourites_count());
values.put(Sqlite.COL_REBLOGGED, status.isReblogged());
values.put(Sqlite.COL_FAVOURITED, status.isFavourited());
values.put(Sqlite.COL_MUTED, status.isMuted());
values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(status.getCreated_at()));
values.put(Sqlite.COL_DATE_BACKUP, Helper.dateToString(new Date()));
values.put(Sqlite.COL_SENSITIVE, status.isSensitive());
values.put(Sqlite.COL_SPOILER_TEXT, status.getSpoiler_text());
values.put(Sqlite.COL_VISIBILITY, status.getVisibility());
values.put(Sqlite.COL_MEDIA_ATTACHMENTS, status.getMedia_attachments()!=null?Helper.attachmentToStringStorage(status.getMedia_attachments()):null);
values.put(Sqlite.COL_MENTIONS, status.getMentions()!=null?Helper.mentionToStringStorage(status.getMentions()):null);
values.put(Sqlite.COL_TAGS, status.getTags()!=null?Helper.tagToStringStorage(status.getTags()):null);
values.put(Sqlite.COL_APPLICATION, status.getApplication()!=null?Helper.applicationToStringStorage(status.getApplication()):null);
values.put(Sqlite.COL_LANGUAGE, status.getLanguage());
values.put(Sqlite.COL_PINNED, status.isPinned());
//Inserts cached status
long last_id;
try{
last_id = db.insert(Sqlite.TABLE_STATUSES_CACHE, null, values);
}catch (Exception e) {
last_id = -1;
}
return last_id;
}
/**
* Insert a status in database
@ -136,6 +183,14 @@ public class StatusCacheDAO {
return db.delete(Sqlite.TABLE_STATUSES_CACHE, Sqlite.COL_CACHED_ACTION + " = \""+ cacheType +"\" AND " + Sqlite.COL_STATUS_ID + " = \"" + status.getId() + "\" AND " + Sqlite.COL_INSTANCE + " = \"" + instance + "\" AND " + Sqlite.COL_USER_ID + " = '" + userId+ "'", null);
}
/***
* Remove stored status
* @return int
*/
public int remove(int cacheType, Status status, String userId, String instance){
return db.delete(Sqlite.TABLE_STATUSES_CACHE, Sqlite.COL_CACHED_ACTION + " = \""+ cacheType +"\" AND " + Sqlite.COL_STATUS_ID + " = \"" + status.getId() + "\" AND " + Sqlite.COL_INSTANCE + " = \"" + instance + "\" AND " + Sqlite.COL_USER_ID + " = '" + userId+ "'", null);
}
public int removeAllStatus(int cacheType){
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
@ -344,6 +399,19 @@ public class StatusCacheDAO {
}
/**
* Returns a cached status by id in db
* @return stored status StoredStatus
*/
public Status getStatus(int cacheType, String id, String userId, String instance){
try {
Cursor c = db.query(Sqlite.TABLE_STATUSES_CACHE, null, Sqlite.COL_CACHED_ACTION + " = '" + cacheType+ "' AND " + Sqlite.COL_STATUS_ID + " = '" + id + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + Sqlite.COL_USER_ID + " = '" + userId+ "'", null, null, null, null, null);
return cursorToStoredStatus(c);
} catch (Exception e) {
return null;
}
}
/***
* Method to hydrate statuses from database
* @param c Cursor

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>

View File

@ -8,6 +8,7 @@
<item
android:id="@+id/action_bookmark"
android:title="@string/bookmark_add"
android:actionLayout="@layout/bookmark_layout"
app:showAsAction="never" />
<item
android:id="@+id/action_open_browser"

View File

@ -631,6 +631,7 @@
<string name="block_domain">Block domain</string>
<string name="toast_block_domain">The domain is blocked</string>
<string name="toast_unblock_domain">The domain is no longer blocked!</string>
<string name="retrieve_remote_status">Fetching remote status</string>
<string-array name="filter_expire">
<item>Never</item>