diff --git a/app/build.gradle b/app/build.gradle index 4e40fd5d5..b0f336223 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "fr.gouv.etalab.mastodon" minSdkVersion 15 targetSdkVersion 25 - versionCode 12 - versionName "1.1.5" + versionCode 13 + versionName "1.1.6" } buildTypes { release { diff --git a/app/mastodon-etalab-v1.1.4.apk b/app/mastodon-etalab-v1.1.4.apk new file mode 100644 index 000000000..eddfd03c8 Binary files /dev/null and b/app/mastodon-etalab-v1.1.4.apk differ diff --git a/app/mastodon-etalab-v1.1.5.apk b/app/mastodon-etalab-v1.1.5.apk new file mode 100644 index 000000000..d096bb78d Binary files /dev/null and b/app/mastodon-etalab-v1.1.5.apk differ diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/MainActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/MainActivity.java index 865a45572..e7c143e0e 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/MainActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/MainActivity.java @@ -148,8 +148,8 @@ public class MainActivity extends AppCompatActivity } }); - mamageNewIntent(getIntent()); - if (savedInstanceState == null) { + boolean matchingIntent = mamageNewIntent(getIntent()); + if (savedInstanceState == null && !matchingIntent) { navigationView.setCheckedItem(R.id.nav_home); navigationView.getMenu().performIdentifierAction(R.id.nav_home, 0); } @@ -199,11 +199,12 @@ public class MainActivity extends AppCompatActivity * Manages new intents * @param intent Intent - intent related to a notification in top bar */ - private void mamageNewIntent(Intent intent){ + private boolean mamageNewIntent(Intent intent){ if( intent == null || intent.getExtras() == null ) - return; + return false; Bundle extras = intent.getExtras(); String userIdIntent; + boolean matchingIntent = false; if( extras.containsKey(INTENT_ACTION) ){ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); //Id of the authenticated account @@ -212,19 +213,26 @@ public class MainActivity extends AppCompatActivity if (extras.getInt(INTENT_ACTION) == NOTIFICATION_INTENT){ if( userId!= null && !userId.equals(userIdIntent)) //Connected account is different from the id in the intent changeUser(MainActivity.this, userIdIntent); //Connects the account which is related to the notification - navigationView.setCheckedItem(R.id.nav_notification); + unCheckAllMenuItems(navigationView.getMenu()); navigationView.getMenu().performIdentifierAction(R.id.nav_notification, 0); + if( navigationView.getMenu().findItem(R.id.nav_notification) != null) + navigationView.getMenu().findItem(R.id.nav_notification).setChecked(true); + matchingIntent = true; }else if( extras.getInt(INTENT_ACTION) == HOME_TIMELINE_INTENT){ if( userId!= null && !userId.equals(userIdIntent)) //Connected account is different from the id in the intent changeUser(MainActivity.this, userIdIntent); //Connects the account which is related to the notification - navigationView.setCheckedItem(R.id.nav_home); + unCheckAllMenuItems(navigationView.getMenu()); navigationView.getMenu().performIdentifierAction(R.id.nav_home, 0); + if( navigationView.getMenu().findItem(R.id.nav_home) != null) + navigationView.getMenu().findItem(R.id.nav_home).setChecked(true); + matchingIntent = true; } } intent.replaceExtras(new Bundle()); intent.setAction(""); intent.setData(null); intent.setFlags(0); + return matchingIntent; } @Override diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java index 02fe1124c..5bbf2e324 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java @@ -58,19 +58,18 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask; -import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.RetrieveSearchAccountsAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.UploadActionAsyncTask; import fr.gouv.etalab.mastodon.client.API; 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.Mention; import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.drawers.AccountsSearchAdapter; import fr.gouv.etalab.mastodon.helper.Helper; import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAttachmentInterface; -import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface; import fr.gouv.etalab.mastodon.sqlite.AccountDAO; import fr.gouv.etalab.mastodon.sqlite.Sqlite; @@ -82,10 +81,9 @@ import mastodon.etalab.gouv.fr.mastodon.R; * Toot activity class */ -public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAccountshInterface, OnRetrieveAttachmentInterface, OnPostActionInterface, OnRetrieveFeedsInterface { +public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAccountshInterface, OnRetrieveAttachmentInterface, OnPostActionInterface { - private String inReplyTo = null; private int charsInCw; private int charsInToot; private int maxChar; @@ -101,10 +99,10 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc private Button toot_it; private EditText toot_content, toot_cw_content; private LinearLayout toot_reply_content_container; - private TextView toot_reply_content; private RelativeLayout toot_show_accounts; private ListView toot_lv_accounts; private BroadcastReceiver search_validate; + private Status tootReply = null; private String pattern = "^.*(@([a-zA-Z0-9_]{2,}))$"; @Override @@ -115,13 +113,74 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc if( getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true); + toot_it = (Button) findViewById(R.id.toot_it); + Button toot_cw = (Button) findViewById(R.id.toot_cw); + final TextView toot_space_left = (TextView) findViewById(R.id.toot_space_left); + toot_visibility = (ImageButton) findViewById(R.id.toot_visibility); + toot_picture = (ImageButton) findViewById(R.id.toot_picture); + loading_picture = (RelativeLayout) findViewById(R.id.loading_picture); + toot_picture_container = (LinearLayout) findViewById(R.id.toot_picture_container); + toot_content = (EditText) findViewById(R.id.toot_content); + toot_cw_content = (EditText) findViewById(R.id.toot_cw_content); + TextView toot_reply_content = (TextView) findViewById(R.id.toot_reply_content); + toot_reply_content_container = (LinearLayout) findViewById(R.id.toot_reply_content_container); + toot_show_accounts = (RelativeLayout) findViewById(R.id.toot_show_accounts); + toot_lv_accounts = (ListView) findViewById(R.id.toot_lv_accounts); + Bundle b = getIntent().getExtras(); - if(b != null) - inReplyTo = b.getString("inReplyTo", null); - if( inReplyTo != null) { + if(b != null) { + tootReply = b.getParcelable("tootReply"); + } + if( tootReply != null) { setTitle(R.string.toot_title_reply); - new RetrieveFeedsAsyncTask(getApplicationContext(), RetrieveFeedsAsyncTask.Type.ONESTATUS, inReplyTo,null, TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + boolean show_reply = sharedpreferences.getBoolean(Helper.SET_SHOW_REPLY, false); + if( show_reply ){ + toot_reply_content_container.setVisibility(View.VISIBLE); + }else { + toot_reply_content_container.setVisibility(View.GONE); + } + String content = tootReply.getContent(); + if(tootReply.isReblogged()) + content = tootReply.getReblog().getContent(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + toot_reply_content.setText(Html.fromHtml(content, Html.FROM_HTML_MODE_COMPACT)); + else + //noinspection deprecation + toot_reply_content.setText(Html.fromHtml(content)); + switch (tootReply.getVisibility()){ + case "public": + visibility = "public"; + toot_visibility.setImageResource(R.drawable.ic_action_globe); + break; + case "unlisted": + visibility = "unlisted"; + toot_visibility.setImageResource(R.drawable.ic_action_lock_open); + break; + case "private": + visibility = "private"; + toot_visibility.setImageResource(R.drawable.ic_action_lock_closed); + break; + case "direct": + visibility = "direct"; + toot_visibility.setImageResource(R.drawable.ic_local_post_office); + break; + } + //Retrieves mentioned accounts + OP and adds them at the beginin of the toot + if( tootReply.getAccount() != null && tootReply.getAccount().getAcct() != null && !tootReply.getAccount().getId().equals(userId)) { + toot_content.setText(String.format("@%s ", tootReply.getAccount().getAcct())); + } + if( tootReply.getMentions() != null ){ + for(Mention mention : tootReply.getMentions()){ + if( mention.getAcct() != null && !mention.getId().equals(userId)) { + String tootTemp = String.format("@%s ", mention.getAcct()); + toot_content.setText(String.format("%s ", (toot_content.getText().toString() + " " + tootTemp))); + } + } + } + toot_content.setSelection(toot_content.getText().length()); //Put cursor at the end }else { setTitle(R.string.toot_title); } @@ -152,19 +211,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc }; LocalBroadcastManager.getInstance(this).registerReceiver(search_validate, new IntentFilter(Helper.SEARCH_VALIDATE_ACCOUNT)); - toot_it = (Button) findViewById(R.id.toot_it); - Button toot_cw = (Button) findViewById(R.id.toot_cw); - final TextView toot_space_left = (TextView) findViewById(R.id.toot_space_left); - toot_visibility = (ImageButton) findViewById(R.id.toot_visibility); - toot_picture = (ImageButton) findViewById(R.id.toot_picture); - loading_picture = (RelativeLayout) findViewById(R.id.loading_picture); - toot_picture_container = (LinearLayout) findViewById(R.id.toot_picture_container); - toot_content = (EditText) findViewById(R.id.toot_content); - toot_cw_content = (EditText) findViewById(R.id.toot_cw_content); - toot_reply_content = (TextView) findViewById(R.id.toot_reply_content); - toot_reply_content_container = (LinearLayout) findViewById(R.id.toot_reply_content_container); - toot_show_accounts = (RelativeLayout) findViewById(R.id.toot_show_accounts); - toot_lv_accounts = (ListView) findViewById(R.id.toot_lv_accounts); + FloatingActionButton toot_close_accounts = (FloatingActionButton) findViewById(R.id.toot_close_accounts); SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); @@ -197,8 +244,6 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc } - - toot_space_left.setText(String.valueOf((maxChar - (charsInToot + charsInCw)))); toot_cw.setOnClickListener(new View.OnClickListener() { @Override @@ -239,8 +284,8 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc toot.setSpoiler_text(toot_cw_content.getText().toString().trim()); toot.setVisibility(visibility); toot.setContent(toot_content.getText().toString().trim()); - if( inReplyTo != null) - toot.setIn_reply_to_id(inReplyTo); + if( tootReply != null) + toot.setIn_reply_to_id(tootReply.getId()); new PostActionAsyncTask(getApplicationContext(), API.StatusAction.CREATESTATUS, null, toot, null, TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -490,51 +535,6 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc toot_it.setEnabled(true); } - @Override - public void onRetrieveFeeds(List statuses, Error error) { - if( error != 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; - } - if( statuses != null && statuses.size() > 0 ){ - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); - boolean show_reply = sharedpreferences.getBoolean(Helper.SET_SHOW_REPLY, false); - if( show_reply ){ - toot_reply_content_container.setVisibility(View.VISIBLE); - }else { - toot_reply_content_container.setVisibility(View.GONE); - } - String content = statuses.get(0).getContent(); - if(statuses.get(0).isReblogged()) - content = statuses.get(0).getReblog().getContent(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - toot_reply_content.setText(Html.fromHtml(content, Html.FROM_HTML_MODE_COMPACT)); - else - //noinspection deprecation - toot_reply_content.setText(Html.fromHtml(content)); - switch (statuses.get(0).getVisibility()){ - case "public": - visibility = "public"; - toot_visibility.setImageResource(R.drawable.ic_action_globe); - break; - case "unlisted": - visibility = "unlisted"; - toot_visibility.setImageResource(R.drawable.ic_action_lock_open); - break; - case "private": - visibility = "private"; - toot_visibility.setImageResource(R.drawable.ic_action_lock_closed); - break; - case "direct": - visibility = "direct"; - toot_visibility.setImageResource(R.drawable.ic_local_post_office); - break; - } - } - } 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 8330a209b..7e6b06ddc 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 @@ -954,7 +954,21 @@ public class API { attachments.add(attachment); } } + List mentions = new ArrayList<>(); + JSONArray arrayMention = resobj.getJSONArray("mentions"); + if( arrayMention != null){ + for(int j = 0 ; j < arrayMention.length() ; j++){ + JSONObject menObj = arrayMention.getJSONObject(j); + Mention mention = new Mention(); + mention.setId(menObj.get("id").toString()); + mention.setUrl(menObj.get("url").toString()); + mention.setAcct(menObj.get("acct").toString()); + mention.setUsername(menObj.get("username").toString()); + mentions.add(mention); + } + } status.setMedia_attachments(attachments); + status.setMentions(mentions); status.setAccount(parseAccountResponse(resobj.getJSONObject("account"))); status.setContent(resobj.get("content").toString()); status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString())); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Mention.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Mention.java index 7d5b7f878..d3e18fc19 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Mention.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Mention.java @@ -14,17 +14,42 @@ * see . */ package fr.gouv.etalab.mastodon.client.Entities; +import android.os.Parcel; +import android.os.Parcelable; + /** * Created by Thomas on 23/04/2017. + * Manages mentions in toots */ -public class Mention { +public class Mention implements Parcelable { private String url; private String username; private String acct; private String id; + private Mention(Parcel in) { + url = in.readString(); + username = in.readString(); + acct = in.readString(); + id = in.readString(); + } + + public Mention(){} + + public static final Creator CREATOR = new Creator() { + @Override + public Mention createFromParcel(Parcel in) { + return new Mention(in); + } + + @Override + public Mention[] newArray(int size) { + return new Mention[size]; + } + }; + public String getUrl() { return url; } @@ -56,4 +81,17 @@ public class Mention { public void setId(String id) { this.id = id; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(url); + dest.writeString(username); + dest.writeString(acct); + dest.writeString(id); + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java index 0fec5fef2..d3829b74b 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java @@ -45,6 +45,11 @@ public class Status implements Parcelable { private String spoiler_text; private String visibility; private boolean attachmentShown = false; + private List media_attachments; + private List mentions; + private List tags; + private Application application; + protected Status(Parcel in) { id = in.readString(); @@ -53,6 +58,8 @@ public class Status implements Parcelable { in_reply_to_id = in.readString(); in_reply_to_account_id = in.readString(); reblog = in.readParcelable(Status.class.getClassLoader()); + account = in.readParcelable(Account.class.getClassLoader()); + mentions = in.readArrayList(Mention.class.getClassLoader()); content = in.readString(); reblogs_count = in.readInt(); favourites_count = in.readInt(); @@ -199,11 +206,6 @@ public class Status implements Parcelable { } - - private List media_attachments; - private List mentions; - private List tags; - private Application application; public List getMedia_attachments() { return media_attachments; } @@ -266,6 +268,8 @@ public class Status implements Parcelable { dest.writeString(in_reply_to_id); dest.writeString(in_reply_to_account_id); dest.writeParcelable(reblog, flags); + dest.writeParcelable(account, flags); + dest.writeList(mentions); dest.writeString(content); dest.writeInt(reblogs_count); dest.writeInt(favourites_count); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java index b45a3346b..fddb675ea 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java @@ -213,7 +213,7 @@ public class NotificationsListAdapter extends BaseAdapter { public void onClick(View v) { Intent intent = new Intent(context, TootActivity.class); Bundle b = new Bundle(); - b.putString("inReplyTo", notification.getStatus().getId()); + b.putParcelable("tootReply", notification.getStatus()); intent.putExtras(b); context.startActivity(intent); } 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 d9a1aedb5..ce9405c55 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 @@ -218,7 +218,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf public void onClick(View v) { Intent intent = new Intent(context, TootActivity.class); Bundle b = new Bundle(); - b.putString("inReplyTo", status.getId()); //Your id + b.putParcelable("tootReply", status); intent.putExtras(b); //Put your id to your next Intent context.startActivity(intent); } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java index 9a492cc4f..5f6566078 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java @@ -109,7 +109,7 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe //Retrieve users in db that owner has. for (Account account: accounts) { String since_id = sharedpreferences.getString(Helper.LAST_HOMETIMELINE_MAX_ID + account.getId(), null); - notificationId = (int) Math.round(Double.parseDouble(account.getId())/100); + notificationId = (int) Math.round(Double.parseDouble(account.getId())/100) + 2; new RetrieveHomeTimelineServiceAsyncTask(getContext(), account.getInstance(), account.getToken(), since_id, account.getAcct(), account.getId(), HomeTimelineSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java index 4d81e5a10..cb3679ade 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java @@ -119,7 +119,7 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications //Retrieve users in db that owner has. for (Account account: accounts) { String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId(), null); - notificationId = (int) Math.round(Double.parseDouble(account.getId())/100); + notificationId = (int) Math.round(Double.parseDouble(account.getId())/100) + 1; new RetrieveNotificationsAsyncTask(getContext(), account.getInstance(), account.getToken(), max_id, account.getAcct(), account.getId(), NotificationsSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } }