diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/PostActionAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/PostActionAsyncTask.java index 59a0b099b..a9b81d285 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/PostActionAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/PostActionAsyncTask.java @@ -16,7 +16,13 @@ package fr.gouv.etalab.mastodon.asynctasks; import android.content.Context; import android.os.AsyncTask; + +import java.util.List; + import fr.gouv.etalab.mastodon.client.API; +import fr.gouv.etalab.mastodon.client.Entities.Account; +import fr.gouv.etalab.mastodon.client.Entities.Results; +import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface; @@ -35,6 +41,9 @@ public class PostActionAsyncTask extends AsyncTask { private String comment; private fr.gouv.etalab.mastodon.client.Entities.Status status; private API api; + private Account account; + private fr.gouv.etalab.mastodon.client.Entities.Status remoteStatus; + public PostActionAsyncTask(Context context, API.StatusAction apiAction, String targetedId, OnPostActionInterface onPostActionInterface){ this.context = context; @@ -43,6 +52,22 @@ public class PostActionAsyncTask extends AsyncTask { this.targetedId = targetedId; } + public PostActionAsyncTask(Context context, Account account, API.StatusAction apiAction, String targetedId, OnPostActionInterface onPostActionInterface){ + this.context = context; + this.listener = onPostActionInterface; + this.apiAction = apiAction; + this.targetedId = targetedId; + this.account = account; + } + + public PostActionAsyncTask(Context context, Account account, fr.gouv.etalab.mastodon.client.Entities.Status remoteStatus, API.StatusAction apiAction, OnPostActionInterface onPostActionInterface){ + this.context = context; + this.listener = onPostActionInterface; + this.apiAction = apiAction; + this.remoteStatus = remoteStatus; + this.account = account; + } + public PostActionAsyncTask(Context context, API.StatusAction apiAction, String targetedId, fr.gouv.etalab.mastodon.client.Entities.Status status, String comment, OnPostActionInterface onPostActionInterface){ this.context = context; this.listener = onPostActionInterface; @@ -55,13 +80,30 @@ public class PostActionAsyncTask extends AsyncTask { @Override protected Void doInBackground(Void... params) { - api = new API(context); - if(apiAction == API.StatusAction.REPORT) - statusCode = api.reportAction(status, comment); - else if(apiAction == API.StatusAction.CREATESTATUS) - statusCode = api.statusAction(status); + //Remote action + if( account !=null) + api = new API(context, account.getInstance(), account.getToken()); else - statusCode = api.postAction(apiAction, targetedId); + api = new API(context); + if( remoteStatus != null){ + Results search = api.search(status.getUri()); + if( search != null){ + List remoteStatuses = search.getStatuses(); + if( remoteStatuses != null && remoteStatuses.size() > 0 ){ + fr.gouv.etalab.mastodon.client.Entities.Status statusTmp = remoteStatuses.get(0); + this.targetedId = statusTmp.getId(); + statusCode = api.postAction(apiAction, targetedId); + } + } + } else { + + if (apiAction == API.StatusAction.REPORT) + statusCode = api.reportAction(status, comment); + else if (apiAction == API.StatusAction.CREATESTATUS) + statusCode = api.statusAction(status); + else + statusCode = api.postAction(apiAction, targetedId); + } return null; } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java index e2b1d7fad..357cd7960 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java @@ -1428,6 +1428,7 @@ public class API { Status status = new Status(); try { status.setId(resobj.get("id").toString()); + status.setUri(resobj.get("uri").toString()); status.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString())); status.setIn_reply_to_id(resobj.get("in_reply_to_id").toString()); status.setIn_reply_to_account_id(resobj.get("in_reply_to_account_id").toString()); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java index cede1ca07..b8b6f83dc 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java @@ -14,8 +14,8 @@ package fr.gouv.etalab.mastodon.drawers; * You should have received a copy of the GNU General Public License along with Mastalab; if not, * see . */ +import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; -import android.os.Environment; import android.os.Handler; import android.support.design.widget.FloatingActionButton; import android.support.v7.app.AlertDialog; @@ -45,8 +45,6 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.Window; -import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.EditText; @@ -66,21 +64,17 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; -import fr.gouv.etalab.mastodon.activities.LoginActivity; -import fr.gouv.etalab.mastodon.activities.MainActivity; import fr.gouv.etalab.mastodon.activities.MediaActivity; import fr.gouv.etalab.mastodon.activities.ShowAccountActivity; import fr.gouv.etalab.mastodon.activities.ShowConversationActivity; @@ -89,6 +83,7 @@ import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask; import fr.gouv.etalab.mastodon.client.API; import fr.gouv.etalab.mastodon.client.APIResponse; +import fr.gouv.etalab.mastodon.client.Entities.Account; import fr.gouv.etalab.mastodon.client.Entities.Attachment; import fr.gouv.etalab.mastodon.client.Entities.Error; import fr.gouv.etalab.mastodon.client.Entities.Status; @@ -97,6 +92,8 @@ import fr.gouv.etalab.mastodon.helper.Helper; import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface; import fr.gouv.etalab.mastodon.interfaces.OnTranslatedInterface; +import fr.gouv.etalab.mastodon.sqlite.AccountDAO; +import fr.gouv.etalab.mastodon.sqlite.Sqlite; import fr.gouv.etalab.mastodon.translation.GoogleTranslateQuery; import fr.gouv.etalab.mastodon.translation.YandexQuery; import mastodon.etalab.gouv.fr.mastodon.R; @@ -241,7 +238,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); final String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); - + //Display a preview for accounts that have replied *if enabled and only for home timeline* if( type == RetrieveFeedsAsyncTask.Type.HOME ) { boolean showPreview = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES, false); @@ -839,27 +836,123 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf holder.status_favorite_count.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION_FAV, false); - if( confirmation ) - displayConfirmationDialog(FAVOURITE,status); - else - favouriteAction(status); + List accounts = Helper.connectedAccounts(context); + if( accounts.size() == 1) { + boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION_FAV, false); + if (confirmation) + displayConfirmationDialog(FAVOURITE, status); + else + favouriteAction(status); + }else { + AlertDialog.Builder builderSingle = new AlertDialog.Builder(context); + builderSingle.setTitle(context.getString(R.string.choose_accounts)); + final AccountsSearchAdapter accountsSearchAdapter = new AccountsSearchAdapter(context, accounts); + 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(DialogInterface dialog, int which) { + Account selectedAccount = accountArray[which]; + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + Account loggedAccount = new AccountDAO(context, db).getAccountByID(userId); + if(loggedAccount.getInstance().equals(selectedAccount.getInstance())){ + if( status.isReblogged() || (status.getReblog()!= null && status.getReblog().isReblogged())){ + new PostActionAsyncTask(context, selectedAccount, API.StatusAction.UNFAVOURITE, targetedId, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(false); + }else{ + new PostActionAsyncTask(context, selectedAccount, API.StatusAction.FAVOURITE, targetedId, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(true); + } + }else{ //Account is from another instance + if( status.isReblogged() || (status.getReblog()!= null && status.getReblog().isReblogged())){ + new PostActionAsyncTask(context, selectedAccount, status, API.StatusAction.UNFAVOURITE, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(false); + }else{ + new PostActionAsyncTask(context, selectedAccount, status, API.StatusAction.FAVOURITE, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(true); + } + } + + statusListAdapter.notifyDataSetChanged(); + dialog.dismiss(); + } + }); + builderSingle.show(); + } } }); + holder.status_reblog_count.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, true); - if( confirmation ) - displayConfirmationDialog(REBLOG,status); - else - reblogAction(status); + List accounts = Helper.connectedAccounts(context); + if( accounts.size() == 1) { + boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, true); + if (confirmation) + displayConfirmationDialog(REBLOG, status); + else + reblogAction(status); + }else{ + AlertDialog.Builder builderSingle = new AlertDialog.Builder(context); + builderSingle.setTitle(context.getString(R.string.choose_accounts)); + final AccountsSearchAdapter accountsSearchAdapter = new AccountsSearchAdapter(context, accounts); + 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(DialogInterface dialog, int which) { + Account selectedAccount = accountArray[which]; + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + Account loggedAccount = new AccountDAO(context, db).getAccountByID(userId); + if(loggedAccount.getInstance().equals(selectedAccount.getInstance())){ + if( status.isReblogged() || (status.getReblog()!= null && status.getReblog().isReblogged())){ + new PostActionAsyncTask(context, selectedAccount, API.StatusAction.UNREBLOG, targetedId, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(false); + }else{ + new PostActionAsyncTask(context, selectedAccount, API.StatusAction.REBLOG, targetedId, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(true); + } + }else{ //Account is from another instance + if( status.isReblogged() || (status.getReblog()!= null && status.getReblog().isReblogged())){ + new PostActionAsyncTask(context, selectedAccount, status, API.StatusAction.UNREBLOG, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(false); + }else{ + new PostActionAsyncTask(context, selectedAccount, status, API.StatusAction.REBLOG, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + status.setReblogged(true); + } + } + statusListAdapter.notifyDataSetChanged(); + dialog.dismiss(); + } + }); + builderSingle.show(); + } } }); - - final View finalConvertView = convertView; final View attached = holder.status_more; holder.status_more.setOnClickListener(new View.OnClickListener() { diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java index 21b40cec1..ef0ca9599 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java @@ -242,7 +242,7 @@ public class Helper { public static final String SET_TOOT_VISIBILITY = "set_toot_visibility"; public static final String SET_DISPLAY_LOCAL = "set_display_local"; public static final String SET_DISPLAY_GLOBAL = "set_display_global"; - + public static final String SET_ALLOW_CROSS_ACTIONS = "set_allow_cross_actions"; //End points public static final String EP_AUTHORIZE = "/oauth/authorize"; @@ -302,7 +302,6 @@ public class Helper { input = input.replace(":" + matcher.group(2) + ":", ""); } } - return input; } //Emoji manager @@ -1559,6 +1558,27 @@ public class Helper { tableLayout.setVisibility(View.VISIBLE); } + /** + * Returns the list of connected accounts when cross actions are allowed otherwise, returns the current account + * @param context Context + * @return List + */ + public static List connectedAccounts(Context context){ + final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + List accounts = new AccountDAO(context, db).getAllAccount(); + if( sharedpreferences.getBoolean(Helper.SET_ALLOW_CROSS_ACTIONS, true) && accounts.size() > 1 ){ + return accounts; + }else { + + List oneAccount = new ArrayList<>(); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + Account account = new AccountDAO(context, db).getAccountByID(userId); + oneAccount.add(account); + return oneAccount; + } + } + /** * Get a bitmap from a view * @param view The view to convert diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 69666e21a..b6e8f222e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -181,6 +181,7 @@ Kein Entwurf! Wähle einen toot + Wähle einen konto Entwurf entfernen? Klicke auf das Auge um den ursprünglichen toot zu sehen diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a3ec2ed30..60ab5314c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -179,6 +179,7 @@ Aucun brouillon ! Choisissez un pouet + Choisissez un compte Supprimer le brouillon ? Cliquer sur le bouton pour afficher le pouet d\'origine diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6ef38baab..61c7e23f5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -179,6 +179,7 @@ No draft! Choose a toot + Choose an account Remove draft? Click on the button to display the original toot