diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8a0bfa1ae..99b9a48f4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -80,6 +80,11 @@ android:configChanges="orientation|screenSize" android:label="@string/app_name" /> + accounts, Error error) { + about_developer.setEnabled(true); + if( accounts != null && accounts.size() > 0 && accounts.get(0) != null) { + about_developer.setOnClickListener(null); + about_developer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(AboutActivity.this, ShowAccountActivity.class); + Bundle b = new Bundle(); + b.putString("accountId", accounts.get(0).getId()); + intent.putExtras(b); + startActivity(intent); + } + }); + } + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/LoginActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/LoginActivity.java index 27fc0ddb2..d3fab022f 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/LoginActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/LoginActivity.java @@ -24,6 +24,8 @@ import android.os.Bundle; import android.support.design.widget.NavigationView; import android.support.v7.app.AppCompatActivity; import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; @@ -87,6 +89,19 @@ public class LoginActivity extends AppCompatActivity { } }); + //For other instances + TextView other_instance = (TextView) findViewById(R.id.other_instance); + other_instance.setPaintFlags(other_instance.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + other_instance.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(LoginActivity.this, LoginActivity.class); + intent.putExtra("addAccount", true); + startActivity(intent); + finish(); + } + }); + Bundle b = getIntent().getExtras(); if(b != null) addAccount = b.getBoolean("addAccount", false); @@ -106,6 +121,8 @@ public class LoginActivity extends AppCompatActivity { } }); } + if( addAccount) + other_instance.setVisibility(View.GONE); } @Override @@ -199,7 +216,9 @@ public class LoginActivity extends AppCompatActivity { requestParams.add("scope"," read write follow"); client.setUserAgent(USER_AGENT); try { - client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore())); + MastalabSSLSocketFactory mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()); + mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + client.setSSLSocketFactory(mastalabSSLSocketFactory); client.post("https://" + instance+ "/oauth/token", requestParams, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { @@ -236,6 +255,29 @@ public class LoginActivity extends AppCompatActivity { } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main_login, menu); + return true; + } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + //noinspection SimplifiableIfStatement + if (id == R.id.action_about) { + Intent intent = new Intent(getApplicationContext(), AboutActivity.class); + startActivity(intent); + }else if(id == R.id.action_privacy){ + Intent intent = new Intent(getApplicationContext(), PrivacyActivity.class); + startActivity(intent); + } + return super.onOptionsItemSelected(item); + } } \ No newline at end of file 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 e7c143e0e..ec6f329f6 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 @@ -282,6 +282,9 @@ public class MainActivity extends AppCompatActivity }else if(id == R.id.action_about){ Intent intent = new Intent(getApplicationContext(), AboutActivity.class); startActivity(intent); + }else if(id == R.id.action_privacy){ + Intent intent = new Intent(getApplicationContext(), PrivacyActivity.class); + startActivity(intent); }else if(id == R.id.action_search){ if( toolbar.getChildCount() > 0){ diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/PrivacyActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/PrivacyActivity.java new file mode 100644 index 000000000..223aad6e4 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/PrivacyActivity.java @@ -0,0 +1,49 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr + * + * 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. + * + * Mastodon Etalab 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 Thomas Schneider; if not, + * see . */ +package fr.gouv.etalab.mastodon.activities; + + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.MenuItem; +import mastodon.etalab.gouv.fr.mastodon.R; + + +/** + * Created by Thomas on 03/06/2017. + * Privacy activity + */ + +public class PrivacyActivity extends AppCompatActivity { + @SuppressWarnings("deprecation") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if( getSupportActionBar() != null) + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + setContentView(R.layout.activity_privacy); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } +} diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java index f85233d58..69df1ec6b 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java @@ -105,9 +105,6 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_account); - - - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); imageLoader = ImageLoader.getInstance(); statuses = new ArrayList<>(); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java new file mode 100644 index 000000000..d1f9fa0c2 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java @@ -0,0 +1,53 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr + * + * 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. + * + * Mastodon Etalab 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 Thomas Schneider; if not, + * see . */ +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.interfaces.OnRetrieveSearcAccountshInterface; + + +/** + * Created by Thomas on 03/06/2017. + * Retrieves developer from search (ie: starting with @ when writing a toot) + */ + +public class RetrieveDeveloperAccountsAsyncTask extends AsyncTask { + + private Context context; + private List accounts; + private OnRetrieveSearcAccountshInterface listener; + private API api; + + public RetrieveDeveloperAccountsAsyncTask(Context context, OnRetrieveSearcAccountshInterface onRetrieveSearcAccountshInterface){ + this.context = context; + this.listener = onRetrieveSearcAccountshInterface; + } + + @Override + protected Void doInBackground(Void... params) { + api = new API(context); + accounts = api.searchDeveloper(); + return null; + } + @Override + protected void onPostExecute(Void result) { + listener.onRetrieveSearchAccounts(accounts, api.getError()); + } + +} 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 7e6b06ddc..e1083a81f 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 @@ -850,6 +850,32 @@ public class API { return results; } + /** + * Retrieves Developer account when searching (ie: via @...) *synchronously* + * + * @return List + */ + public List searchDeveloper() { + RequestParams params = new RequestParams(); + params.add("q", "tschneider"); + get("/accounts/search", params, new JsonHttpResponseHandler() { + @Override + public void onSuccess(int statusCode, Header[] headers, JSONObject response) { + accounts = new ArrayList<>(); + account = parseAccountResponse(response); + accounts.add(account); + } + @Override + public void onSuccess(int statusCode, Header[] headers, JSONArray response) { + accounts = parseDeveloperResponse(response); + } + @Override + public void onFailure(int statusCode, Header[] headers, Throwable error, JSONObject response){ + setError(statusCode, error); + } + }); + return accounts; + } /** * Retrieves Accounts when searching (ie: via @...) *synchronously* * @@ -926,60 +952,10 @@ public class API { try { int i = 0; while (i < jsonArray.length() ){ - Status status = new Status(); + JSONObject resobj = jsonArray.getJSONObject(i); - status.setId(resobj.get("id").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()); - status.setSensitive(Boolean.getBoolean(resobj.get("sensitive").toString())); - status.setSpoiler_text(resobj.get("spoiler_text").toString()); - status.setVisibility(resobj.get("visibility").toString()); - - //TODO: replace by the value - status.setApplication(new Application()); - - JSONArray arrayAttachement = resobj.getJSONArray("media_attachments"); - List attachments = new ArrayList<>(); - if( arrayAttachement != null){ - for(int j = 0 ; j < arrayAttachement.length() ; j++){ - JSONObject attObj = arrayAttachement.getJSONObject(j); - Attachment attachment = new Attachment(); - attachment.setId(attObj.get("id").toString()); - attachment.setPreview_url(attObj.get("preview_url").toString()); - attachment.setRemote_url(attObj.get("remote_url").toString()); - attachment.setType(attObj.get("type").toString()); - attachment.setText_url(attObj.get("text_url").toString()); - attachment.setUrl(attObj.get("url").toString()); - 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())); - status.setReblogs_count(Integer.valueOf(resobj.get("reblogs_count").toString())); - status.setReblogged(Boolean.valueOf(resobj.get("reblogged").toString())); - status.setFavourited(Boolean.valueOf(resobj.get("favourited").toString())); - try{ - status.setReblog(parseStatuses(resobj.getJSONObject("reblog"))); - }catch (Exception ignored){} + Status status = parseStatuses(resobj); i++; - statuses.add(status); } @@ -1025,6 +1001,20 @@ public class API { } } status.setMedia_attachments(attachments); + 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.setMentions(mentions); status.setAccount(parseAccountResponse(resobj.getJSONObject("account"))); status.setContent(resobj.get("content").toString()); status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString())); @@ -1082,23 +1072,8 @@ public class API { try { int i = 0; while (i < jsonArray.length() ) { - Account account = new Account(); JSONObject resobj = jsonArray.getJSONObject(i); - account.setId(resobj.get("id").toString()); - account.setUsername(resobj.get("username").toString()); - account.setAcct(resobj.get("acct").toString()); - account.setDisplay_name(resobj.get("display_name").toString()); - account.setLocked(Boolean.parseBoolean(resobj.get("locked").toString())); - account.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString())); - account.setFollowers_count(Integer.valueOf(resobj.get("followers_count").toString())); - account.setFollowing_count(Integer.valueOf(resobj.get("following_count").toString())); - account.setStatuses_count(Integer.valueOf(resobj.get("statuses_count").toString())); - account.setNote(resobj.get("note").toString()); - account.setUrl(resobj.get("url").toString()); - account.setAvatar(resobj.get("avatar").toString()); - account.setAvatar_static(resobj.get("avatar_static").toString()); - account.setHeader(resobj.get("header").toString()); - account.setHeader_static(resobj.get("header_static").toString()); + Account account = parseAccountResponse(resobj); accounts.add(account); i++; } @@ -1108,6 +1083,33 @@ public class API { return accounts; } + + /** + * Parse json response for list of accounts which could contain the developer name + * @param jsonArray JSONArray + * @return List + */ + private List parseDeveloperResponse(JSONArray jsonArray){ + + List accounts = new ArrayList<>(); + try { + int i = 0; + Account account = null; + while (i < jsonArray.length() ) { + JSONObject resobj = jsonArray.getJSONObject(i); + account = parseAccountResponse(resobj); + if( account.getAcct().contains(Helper.INSTANCE)) + accounts.add(account); + i++; + } + if( accounts.size() == 0) + accounts.add(account); + } catch (JSONException e) { + e.printStackTrace(); + } + return accounts; + } + /** * Parse json response for the context * @param jsonObject JSONObject @@ -1208,16 +1210,9 @@ public class API { try { int i = 0; while (i < jsonArray.length() ) { - Notification notification = new Notification(); + JSONObject resobj = jsonArray.getJSONObject(i); - notification.setId(resobj.get("id").toString()); - notification.setType(resobj.get("type").toString()); - notification.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString())); - notification.setAccount(parseAccountResponse(resobj.getJSONObject("account"))); - try{ - notification.setStatus(parseStatuses(resobj.getJSONObject("status"))); - }catch (Exception ignored){} - notification.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString())); + Notification notification = parseNotificationResponse(resobj); notifications.add(notification); i++; } @@ -1246,7 +1241,9 @@ public class API { client.setConnectTimeout(10000); //10s timeout client.setUserAgent(USER_AGENT); client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT); - client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore())); + MastalabSSLSocketFactory mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()); + mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + client.setSSLSocketFactory(mastalabSSLSocketFactory); client.get(getAbsoluteUrl(action), params, responseHandler); } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) { @@ -1261,7 +1258,9 @@ public class API { client.setConnectTimeout(10000); //10s timeout client.setUserAgent(USER_AGENT); client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT); - client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore())); + MastalabSSLSocketFactory mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()); + mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + client.setSSLSocketFactory(mastalabSSLSocketFactory); client.post(getAbsoluteUrl(action), params, responseHandler); } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) { Toast.makeText(context, R.string.toast_error,Toast.LENGTH_LONG).show(); @@ -1274,7 +1273,9 @@ public class API { client.setConnectTimeout(10000); //10s timeout client.setUserAgent(USER_AGENT); client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT); - client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore())); + MastalabSSLSocketFactory mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()); + mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + client.setSSLSocketFactory(mastalabSSLSocketFactory); client.delete(getAbsoluteUrl(action), params, responseHandler); } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) { Toast.makeText(context, R.string.toast_error,Toast.LENGTH_LONG).show(); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/OauthClient.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/OauthClient.java index 9b5f66c38..00b952c52 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/OauthClient.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/OauthClient.java @@ -47,7 +47,9 @@ public class OauthClient { try { client.setConnectTimeout(10000); //10s timeout client.setUserAgent(USER_AGENT); - client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore())); + MastalabSSLSocketFactory mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()); + mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + client.setSSLSocketFactory(mastalabSSLSocketFactory); client.get(getAbsoluteUrl(action), params, responseHandler); } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) { e.printStackTrace(); @@ -58,7 +60,9 @@ public class OauthClient { try { client.setConnectTimeout(10000); //10s timeout client.setUserAgent(USER_AGENT); - client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore())); + MastalabSSLSocketFactory mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()); + mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + client.setSSLSocketFactory(mastalabSSLSocketFactory); client.post(getAbsoluteUrl(action), params, responseHandler); } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) { e.printStackTrace(); 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 ce9405c55..b4a8f0640 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 @@ -16,6 +16,8 @@ package fr.gouv.etalab.mastodon.drawers; import android.Manifest; import android.app.AlertDialog; +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -32,6 +34,7 @@ import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.text.Html; import android.text.util.Linkify; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -437,7 +440,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf final RelativeLayout loader = (RelativeLayout) view.findViewById(R.id.loader); switch (attachment.getType()){ case "image": { - String url = attachment.getRemote_url(); + String url = attachment.getPreview_url(); if(url == null || url.trim().equals("")) url = attachment.getUrl(); final ImageView imageView = (ImageView) view.findViewById(R.id.dialog_imageview); @@ -666,20 +669,48 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf AlertDialog.Builder builderInner = new AlertDialog.Builder(context); builderInner.setTitle(stringArrayConf[which]); if( isOwner) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT)); - else - //noinspection deprecation - builderInner.setMessage(Html.fromHtml(status.getContent())); - }else { - if( which < 2 ){ - builderInner.setMessage(status.getAccount().getAcct()); - }else { + if( which == 0) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT)); else //noinspection deprecation builderInner.setMessage(Html.fromHtml(status.getContent())); + }else{ + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + String content; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + content = Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT).toString(); + else + //noinspection deprecation + content = Html.fromHtml(status.getContent()).toString(); + ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, content); + clipboard.setPrimaryClip(clip); + Toast.makeText(context,R.string.clipboard,Toast.LENGTH_LONG).show(); + dialog.dismiss(); + return; + } + }else { + if( which < 2 ){ + builderInner.setMessage(status.getAccount().getAcct()); + }else if( which < 3) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT)); + else + //noinspection deprecation + builderInner.setMessage(Html.fromHtml(status.getContent())); + }else{ + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + String content; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + content = Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT).toString(); + else + //noinspection deprecation + content = Html.fromHtml(status.getContent()).toString(); + ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, content); + clipboard.setPrimaryClip(clip); + Toast.makeText(context,R.string.clipboard,Toast.LENGTH_LONG).show(); + dialog.dismiss(); + return; } } //Text for report diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java index 5a0e48237..29940bb29 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java @@ -20,6 +20,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -55,7 +56,7 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve private Context context; private AsyncTask asyncTask; private NotificationsListAdapter notificationsListAdapter; - private String max_id = null; + private String max_id; private List notifications; private RelativeLayout mainLoader, nextElementLoader, textviewNoAction; private boolean firstLoad; @@ -66,7 +67,7 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_notifications, container, false); - + max_id = null; context = getContext(); firstLoad = true; flag_loading = true; 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 754bec481..f3bde33d1 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 @@ -110,6 +110,7 @@ public class Helper { public static final String WEBSITE = "website"; public static final String LAST_NOTIFICATION_MAX_ID = "last_notification_max_id"; public static final String LAST_HOMETIMELINE_MAX_ID = "last_hometimeline_max_id"; + public static final String CLIP_BOARD = "clipboard"; //Notifications public static final int NOTIFICATION_INTENT = 1; public static final int HOME_TIMELINE_INTENT = 2; @@ -418,6 +419,7 @@ public class Helper { // prepare intent which is triggered if the user click on the notification NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); PendingIntent pIntent = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_ONE_SHOT); + RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); // build notification NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context) 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 5f6566078..25b66dcd1 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 @@ -22,7 +22,6 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.support.annotation.NonNull; -import android.widget.Toast; import com.evernote.android.job.Job; import com.evernote.android.job.JobManager; @@ -64,6 +63,7 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe static final String HOME_TIMELINE = "home_timeline"; private int notificationId; + @NonNull @Override protected Result onRunJob(Params params) { @@ -93,11 +93,17 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe * Task in background starts here. */ private void callAsynchronousTask() { + + final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean notif_hometimeline = sharedpreferences.getBoolean(Helper.SET_NOTIF_HOMETIMELINE, true); + //User disagree with home timeline refresh if( !notif_hometimeline) return; //Nothing is done + //No account connected, the service is stopped + if(!Helper.isLoggedIn(getContext())) + return; SQLiteDatabase db = Sqlite.getInstance(getContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); //If an Internet connection and user agrees with notification refresh //If WIFI only and on WIFI OR user defined any connections to use the service. @@ -109,7 +115,8 @@ 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) + 2; + long notif_id = Long.parseLong(account.getId()); + notificationId = ((notif_id + 2) > 2147483647 )?(int)(2147483647 - notif_id -2):(int)(notif_id + 2); new RetrieveHomeTimelineServiceAsyncTask(getContext(), account.getInstance(), account.getToken(), since_id, account.getAcct(), account.getId(), HomeTimelineSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -162,7 +169,9 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK ); intent.putExtra(INTENT_ACTION, HOME_TIMELINE_INTENT); intent.putExtra(PREF_KEY_ID, userId); - notify_user(getContext(), intent, notificationId, icon_notification,title,message); + + if( max_id != null) + notify_user(getContext(), intent, notificationId, icon_notification,title,message); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statuses.get(0).getId()); editor.apply(); 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 cb3679ade..373ff742e 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 @@ -22,8 +22,6 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.support.annotation.NonNull; -import android.util.Log; - import com.evernote.android.job.Job; import com.evernote.android.job.JobManager; @@ -110,6 +108,9 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications //User disagree with all notifications if( !notif_follow && !notif_add && !notif_ask && !notif_mention && !notif_share) return; //Nothing is done + //No account connected, the service is stopped + if(!Helper.isLoggedIn(getContext())) + return; //If WIFI only and on WIFI OR user defined any connections to use the service. if(!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(getContext())) { List accounts = new AccountDAO(getContext(),db).getAllAccount(); @@ -119,7 +120,8 @@ 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) + 1; + long notif_id = Long.parseLong(account.getId()); + notificationId = ((notif_id + 1) > 2147483647 )?(int)(2147483647 - notif_id - 1):(int)(notif_id + 1); new RetrieveNotificationsAsyncTask(getContext(), account.getInstance(), account.getToken(), max_id, account.getAcct(), account.getId(), NotificationsSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } } @@ -221,7 +223,8 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK ); intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT); intent.putExtra(PREF_KEY_ID, userId); - notify_user(getContext(), intent, notificationId, icon_notification,title,message); + if( max_id != null) + notify_user(getContext(), intent, notificationId, icon_notification,title,message); } SharedPreferences.Editor editor = sharedpreferences.edit(); diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 06bfd9422..a402c4f07 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -15,88 +15,96 @@ You should have received a copy of the GNU General Public License along with Thomas Schneider; if not, see . --> - - - + - - - - - - - - -