diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 99b9a48f4..afdee598c 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"
/>
+
. */
+package fr.gouv.etalab.mastodon.activities;
+
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v7.app.AppCompatActivity;
+import android.text.Html;
+import android.util.Log;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import fr.gouv.etalab.mastodon.asynctasks.RetrieveInstanceAsyncTask;
+import fr.gouv.etalab.mastodon.client.APIResponse;
+import fr.gouv.etalab.mastodon.client.Entities.Instance;
+import fr.gouv.etalab.mastodon.helper.Helper;
+import fr.gouv.etalab.mastodon.interfaces.OnRetrieveInstanceInterface;
+import mastodon.etalab.gouv.fr.mastodon.R;
+
+
+/**
+ * Created by Thomas on 05/06/2017.
+ * Instance activity
+ */
+
+public class InstanceActivity extends AppCompatActivity implements OnRetrieveInstanceInterface {
+
+ private Button about_developer;
+ private LinearLayout instance_container;
+ private RelativeLayout loader;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if( getSupportActionBar() != null)
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ setContentView(R.layout.activity_instance);
+
+ instance_container = (LinearLayout) findViewById(R.id.instance_container);
+ loader = (RelativeLayout) findViewById(R.id.loader);
+ instance_container.setVisibility(View.GONE);
+ loader.setVisibility(View.VISIBLE);
+ setTitle(getString(R.string.action_about_instance));
+ new RetrieveInstanceAsyncTask(getApplicationContext(), InstanceActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+
+ @Override
+ public void onRetrieveInstance(APIResponse apiResponse) {
+ instance_container.setVisibility(View.VISIBLE);
+ loader.setVisibility(View.GONE);
+ if( apiResponse.getError() != null){
+ Toast.makeText(getApplicationContext(), R.string.toast_error, Toast.LENGTH_LONG).show();
+ return;
+ }
+ final Instance instance = apiResponse.getInstance();
+ TextView instance_title = (TextView) findViewById(R.id.instance_title);
+ TextView instance_description = (TextView) findViewById(R.id.instance_description);
+ TextView instance_version = (TextView) findViewById(R.id.instance_version);
+ TextView instance_uri = (TextView) findViewById(R.id.instance_uri);
+ FloatingActionButton instance_contact = (FloatingActionButton) findViewById(R.id.instance_contact);
+
+ instance_title.setText(instance.getTitle());
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ instance_description.setText(Html.fromHtml(instance.getDescription(), Html.FROM_HTML_MODE_COMPACT));
+ else
+ //noinspection deprecation
+ instance_description.setText(Html.fromHtml(instance.getDescription()));
+ if( instance.getDescription() == null || instance.getDescription().trim().length() == 0 )
+ instance_description.setText(getString(R.string.instance_no_description));
+ instance_version.setText(instance.getVersion());
+ instance_uri.setText(instance.getUri());
+ if( instance.getEmail() == null){
+ instance_contact.setVisibility(View.GONE);
+ }
+
+ instance_contact.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",instance.getEmail(), null));
+ emailIntent.putExtra(Intent.EXTRA_SUBJECT, "[Mastodon] - " + instance.getUri());
+ startActivity(Intent.createChooser(emailIntent, getString(R.string.send_email)));
+ }
+ });
+ }
+}
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 ec6f329f6..903342767 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
@@ -285,7 +285,10 @@ public class MainActivity extends AppCompatActivity
}else if(id == R.id.action_privacy){
Intent intent = new Intent(getApplicationContext(), PrivacyActivity.class);
startActivity(intent);
- }else if(id == R.id.action_search){
+ }else if(id == R.id.action_about_instance){
+ Intent intent = new Intent(getApplicationContext(), InstanceActivity.class);
+ startActivity(intent);
+ } else if(id == R.id.action_search){
if( toolbar.getChildCount() > 0){
for(int i = 0 ; i < toolbar.getChildCount() ; i++){
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveAccountInfoAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveAccountInfoAsyncTask.java
new file mode 100644
index 000000000..be739d7f3
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveAccountInfoAsyncTask.java
@@ -0,0 +1,52 @@
+/* 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 fr.gouv.etalab.mastodon.client.API;
+import fr.gouv.etalab.mastodon.client.Entities.Account;
+import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountInterface;
+
+/**
+ * Created by Thomas on 04/06/2017.
+ * Verify credential
+ */
+
+public class RetrieveAccountInfoAsyncTask extends AsyncTask {
+
+ private Context context;
+ private OnRetrieveAccountInterface listener;
+ private Account account;
+ private API api;
+
+ public RetrieveAccountInfoAsyncTask(Context context, OnRetrieveAccountInterface onRetrieveAccountInterface){
+ this.context = context;
+ this.listener = onRetrieveAccountInterface;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ api = new API(context);
+ account = api.verifyCredentials();
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ listener.onRetrieveAccount(account, api.getError());
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveInstanceAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveInstanceAsyncTask.java
new file mode 100644
index 000000000..48d18e729
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveInstanceAsyncTask.java
@@ -0,0 +1,52 @@
+/* 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 fr.gouv.etalab.mastodon.client.API;
+import fr.gouv.etalab.mastodon.client.APIResponse;
+import fr.gouv.etalab.mastodon.interfaces.OnRetrieveInstanceInterface;
+
+
+/**
+ * Created by Thomas on 05/06/2017.
+ * Retrieves the current instance
+ */
+
+public class RetrieveInstanceAsyncTask extends AsyncTask {
+
+ private Context context;
+ private OnRetrieveInstanceInterface listener;
+ private APIResponse apiResponse;
+
+ public RetrieveInstanceAsyncTask(Context context, OnRetrieveInstanceInterface onRetrieveInstanceInterface){
+ this.context = context;
+ this.listener = onRetrieveInstanceInterface;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ apiResponse = new API(context).getInstance();
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ listener.onRetrieveInstance(apiResponse);
+ }
+
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/UpdateCredentialAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/UpdateCredentialAsyncTask.java
new file mode 100644
index 000000000..c99b8f97a
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/UpdateCredentialAsyncTask.java
@@ -0,0 +1,56 @@
+/* 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 fr.gouv.etalab.mastodon.client.API;
+import fr.gouv.etalab.mastodon.client.APIResponse;
+import fr.gouv.etalab.mastodon.interfaces.OnUpdateCredentialInterface;
+
+/**
+ * Created by Thomas on 05/06/2017.
+ * Update account credential
+ */
+
+public class UpdateCredentialAsyncTask extends AsyncTask {
+
+ private Context context;
+ private String display_name, note, avatar, header;
+ private APIResponse apiResponse;
+ private OnUpdateCredentialInterface listener;
+
+ public UpdateCredentialAsyncTask(Context context, String display_name, String note, String avatar, String header, OnUpdateCredentialInterface onUpdateCredentialInterface){
+ this.context = context;
+ this.display_name = display_name;
+ this.note = note;
+ this.avatar = avatar;
+ this.header = header;
+ this.listener = onUpdateCredentialInterface;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ apiResponse = new API(context).updateCredential(display_name, note, avatar, header);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ listener.onUpdateCredential(apiResponse);
+ }
+
+}
\ No newline at end of file
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 5363871e5..8377ee75a 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
@@ -16,6 +16,7 @@ package fr.gouv.etalab.mastodon.client;
import android.content.Context;
import android.content.SharedPreferences;
+import android.util.Log;
import android.widget.Toast;
import com.loopj.android.http.AsyncHttpResponseHandler;
@@ -71,6 +72,7 @@ public class API {
private int tootPerPage, accountPerPage, notificationPerPage;
private int actionCode;
private String instance;
+ private Instance instanceEntity;
private String prefKeyOauthTokenT;
private APIResponse apiResponse;
private Error APIError;
@@ -123,6 +125,57 @@ public class API {
}
+ /***
+ * Get info on the current Instance *synchronously*
+ * @return APIResponse
+ */
+ public APIResponse getInstance() {
+ get("/instance", null, new JsonHttpResponseHandler() {
+ @Override
+ public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
+ instanceEntity = parseInstance(response);
+ }
+ @Override
+ public void onFailure(int statusCode, Header[] headers, Throwable error, JSONObject response){
+ setError(statusCode, error);
+ }
+ });
+ apiResponse.setInstance(instanceEntity);
+ return apiResponse;
+ }
+
+ /***
+ * Update credential of the authenticated user *synchronously*
+ * @return APIResponse
+ */
+ public APIResponse updateCredential(String display_name, String note, String avatar, String header) {
+ RequestParams requestParams = new RequestParams();
+
+ if( display_name != null)
+ requestParams.add("display_name",display_name);
+ if( note != null)
+ requestParams.add("note",note);
+ if( avatar != null)
+ requestParams.add("avatar",avatar);
+ if( header != null)
+ requestParams.add("header",header);
+ patch("/accounts/update_credentials", requestParams, new JsonHttpResponseHandler() {
+ @Override
+ public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
+ }
+ @Override
+ public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
+ }
+
+ @Override
+ public void onFailure(int statusCode, Header[] headers, Throwable error, JSONObject response){
+ setError(statusCode, error);
+ }
+ });
+ return apiResponse;
+ }
+
+
/***
* Verifiy credential of the authenticated user *synchronously*
* @return Account
@@ -215,7 +268,7 @@ public class API {
* Retrieves status for the account *synchronously*
*
* @param accountId String Id of the account
- * @return List
+ * @return APIResponse
*/
public APIResponse getStatus(String accountId) {
return getStatus(accountId, false, false, null, null, tootPerPage);
@@ -226,7 +279,7 @@ public class API {
*
* @param accountId String Id of the account
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getStatus(String accountId, String max_id) {
return getStatus(accountId, false, false, max_id, null, tootPerPage);
@@ -288,7 +341,7 @@ public class API {
* Retrieves one status *synchronously*
*
* @param statusId String Id of the status
- * @return List
+ * @return APIResponse
*/
public APIResponse getStatusbyId(String statusId) {
statuses = new ArrayList<>();
@@ -341,7 +394,7 @@ public class API {
/**
* Retrieves home timeline for the account *synchronously*
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getHomeTimeline( String max_id) {
return getHomeTimeline(max_id, null, tootPerPage);
@@ -349,7 +402,7 @@ public class API {
/**
* Retrieves home timeline for the account since an Id value *synchronously*
- * @return List
+ * @return APIResponse
*/
public APIResponse getHomeTimelineSinceId(String since_id) {
return getHomeTimeline(null, since_id, tootPerPage);
@@ -402,7 +455,7 @@ public class API {
* Retrieves public timeline for the account *synchronously*
* @param local boolean only local timeline
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getPublicTimeline(boolean local, String max_id){
return getPublicTimeline(local, max_id, null, tootPerPage);
@@ -457,7 +510,7 @@ public class API {
* @param tag String
* @param local boolean only local timeline
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getPublicTimelineTag(String tag, boolean local, String max_id){
return getPublicTimelineTag(tag, local, max_id, null, tootPerPage);
@@ -513,7 +566,7 @@ public class API {
/**
* Retrieves muted users by the authenticated account *synchronously*
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getMuted(String max_id){
return getAccounts("/mutes", max_id, null, accountPerPage);
@@ -522,7 +575,7 @@ public class API {
/**
* Retrieves blocked users by the authenticated account *synchronously*
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getBlocks(String max_id){
return getAccounts("/blocks", max_id, null, accountPerPage);
@@ -533,7 +586,7 @@ public class API {
* Retrieves following for the account specified by targetedId *synchronously*
* @param targetedId String targetedId
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getFollowing(String targetedId, String max_id){
return getAccounts(String.format("/accounts/%s/following",targetedId),max_id, null, accountPerPage);
@@ -543,7 +596,7 @@ public class API {
* Retrieves followers for the account specified by targetedId *synchronously*
* @param targetedId String targetedId
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getFollowers(String targetedId, String max_id){
return getAccounts(String.format("/accounts/%s/followers",targetedId),max_id, null, accountPerPage);
@@ -595,7 +648,7 @@ public class API {
/**
* Retrieves favourited status for the authenticated account *synchronously*
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getFavourites(String max_id){
return getFavourites(max_id, null, tootPerPage);
@@ -788,7 +841,7 @@ public class API {
/**
* Retrieves notifications for the authenticated account since an id*synchronously*
* @param since_id String since max
- * @return List
+ * @return APIResponse
*/
public APIResponse getNotificationsSince(String since_id){
return getNotifications(null, since_id, notificationPerPage);
@@ -797,7 +850,7 @@ public class API {
/**
* Retrieves notifications for the authenticated account *synchronously*
* @param max_id String id max
- * @return List
+ * @return APIResponse
*/
public APIResponse getNotifications(String max_id){
return getNotifications(max_id, null, notificationPerPage);
@@ -899,7 +952,7 @@ public class API {
/**
* Retrieves Developer account when searching (ie: via @...) *synchronously*
*
- * @return List
+ * @return APIResponse
*/
public APIResponse searchDeveloper() {
RequestParams params = new RequestParams();
@@ -931,7 +984,7 @@ public class API {
* Retrieves Accounts when searching (ie: via @...) *synchronously*
*
* @param query String search
- * @return List
+ * @return APIResponse
*/
public APIResponse searchAccounts(String query) {
@@ -1086,6 +1139,25 @@ public class API {
return status;
}
+ /**
+ * Parse json response an unique instance
+ * @param resobj JSONObject
+ * @return Instance
+ */
+ private Instance parseInstance(JSONObject resobj){
+
+ Instance instance = new Instance();
+ try {
+ instance.setUri(resobj.get("uri").toString());
+ instance.setTitle(resobj.get("title").toString());
+ instance.setDescription(resobj.get("description").toString());
+ instance.setEmail(resobj.get("email").toString());
+ instance.setVersion(resobj.get("version").toString());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return instance;
+ }
/**
* Parse json response an unique account
@@ -1340,6 +1412,21 @@ public class API {
}
}
+ private void patch(String action, RequestParams params, AsyncHttpResponseHandler responseHandler){
+ try {
+ client.setConnectTimeout(10000); //10s timeout
+ client.setUserAgent(USER_AGENT);
+ client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
+ MastalabSSLSocketFactory mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore());
+ mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ client.setSSLSocketFactory(mastalabSSLSocketFactory);
+ client.patch(getAbsoluteUrl(action), params, responseHandler);
+ } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
+ Toast.makeText(context, R.string.toast_error,Toast.LENGTH_LONG).show();
+ e.printStackTrace();
+ }
+ }
+
public Error getError(){
return APIError;
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java
index 57940d922..9ad0872ca 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java
@@ -20,6 +20,7 @@ public class APIResponse {
private List notifications = null;
private fr.gouv.etalab.mastodon.client.Entities.Error error = null;
private String since_id, max_id;
+ private Instance instance;
public List getAccounts() {
return accounts;
@@ -76,4 +77,12 @@ public class APIResponse {
public void setSince_id(String since_id) {
this.since_id = since_id;
}
+
+ public Instance getInstance() {
+ return instance;
+ }
+
+ public void setInstance(Instance instance) {
+ this.instance = instance;
+ }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Instance.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Instance.java
new file mode 100644
index 000000000..df115abab
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Instance.java
@@ -0,0 +1,69 @@
+/* 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.client.Entities;
+
+/**
+ * Created by Thomas on 05/06/2017.
+ * Describes instance
+ */
+
+public class Instance {
+
+ private String uri;
+ private String title;
+ private String description;
+ private String email;
+ private String version;
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsProfileFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsProfileFragment.java
new file mode 100644
index 000000000..adeacd465
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsProfileFragment.java
@@ -0,0 +1,361 @@
+package fr.gouv.etalab.mastodon.fragments;
+/* 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 . */
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.Html;
+import android.text.TextWatcher;
+import android.util.Base64;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.nostra13.universalimageloader.core.DisplayImageOptions;
+import com.nostra13.universalimageloader.core.ImageLoader;
+import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+import fr.gouv.etalab.mastodon.activities.MainActivity;
+import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountInfoAsyncTask;
+import fr.gouv.etalab.mastodon.asynctasks.UpdateCredentialAsyncTask;
+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.interfaces.OnRetrieveAccountInterface;
+import fr.gouv.etalab.mastodon.interfaces.OnUpdateCredentialInterface;
+import mastodon.etalab.gouv.fr.mastodon.R;
+
+
+/**
+ * Created by Thomas on 04/06/2017.
+ * Fragment for profile settings
+ */
+public class SettingsProfileFragment extends Fragment implements OnRetrieveAccountInterface, OnUpdateCredentialInterface {
+
+
+ private Context context;
+ private EditText set_profile_name, set_profile_description;
+ private ImageView set_profile_picture, set_header_picture;
+ private Button set_change_profile_picture, set_change_header_picture, set_profile_save;
+ private TextView set_header_picture_overlay;
+ private ImageLoader imageLoader;
+ private DisplayImageOptions options;
+ private static final int PICK_IMAGE_HEADER = 4565;
+ private static final int PICK_IMAGE_PROFILE = 6545;
+ private String profile_picture, header_picture, profile_username, profile_note;
+ private Bitmap profile_picture_bmp, profile_header_bmp;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ View rootView = inflater.inflate(R.layout.fragment_settings_profile, container, false);
+
+ set_profile_name = (EditText) rootView.findViewById(R.id.set_profile_name);
+ set_profile_description = (EditText) rootView.findViewById(R.id.set_profile_description);
+ set_profile_picture = (ImageView) rootView.findViewById(R.id.set_profile_picture);
+ set_header_picture = (ImageView) rootView.findViewById(R.id.set_header_picture);
+ set_change_profile_picture = (Button) rootView.findViewById(R.id.set_change_profile_picture);
+ set_change_header_picture = (Button) rootView.findViewById(R.id.set_change_header_picture);
+ set_profile_save = (Button) rootView.findViewById(R.id.set_profile_save);
+ set_header_picture_overlay = (TextView) rootView.findViewById(R.id.set_header_picture_overlay);
+
+ set_profile_save.setEnabled(false);
+ set_change_header_picture.setEnabled(false);
+ set_change_profile_picture.setEnabled(false);
+ set_profile_name.setEnabled(false);
+ set_profile_description.setEnabled(false);
+ context = getContext();
+ imageLoader = ImageLoader.getInstance();
+ options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
+ .cacheOnDisk(true).resetViewBeforeLoading(true).build();
+ new RetrieveAccountInfoAsyncTask(context, SettingsProfileFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return rootView;
+ }
+
+
+
+ @Override
+ public void onCreate(Bundle saveInstance) {
+ super.onCreate(saveInstance);
+ }
+
+
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ this.context = context;
+ }
+
+
+ @Override
+ public void onRetrieveAccount(Account account, Error error) {
+ if( error != null ){
+ Toast.makeText(context,R.string.toast_error, Toast.LENGTH_LONG).show();
+ return;
+ }
+ set_profile_name.setText(account.getDisplay_name());
+
+ final String content;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ content = Html.fromHtml(account.getNote(), Html.FROM_HTML_MODE_COMPACT).toString();
+ else
+ //noinspection deprecation
+ content = Html.fromHtml(account.getNote()).toString();
+ set_profile_description.setText(content);
+
+ set_profile_save.setEnabled(true);
+ set_change_header_picture.setEnabled(true);
+ set_change_profile_picture.setEnabled(true);
+ set_profile_name.setEnabled(true);
+ set_profile_description.setEnabled(true);
+
+ set_profile_description.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ @Override
+ public void afterTextChanged(Editable s) {
+ if( s.length() > 160){
+ String content = s.toString().substring(0,160);
+ set_profile_description.setText(content);
+ set_profile_description.setSelection(set_profile_description.getText().length());
+ Toast.makeText(context,R.string.note_no_space,Toast.LENGTH_LONG).show();
+ }
+ }
+ });
+
+ set_profile_name.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ @Override
+ public void afterTextChanged(Editable s) {
+ if( s.length() > 30){
+ String content = s.toString().substring(0,30);
+ set_profile_name.setText(content);
+ set_profile_name.setSelection(set_profile_name.getText().length());
+ Toast.makeText(context,R.string.username_no_space,Toast.LENGTH_LONG).show();
+ }
+ }
+ });
+
+
+ set_change_header_picture.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ getIntent.setType("image/*");
+
+ Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+ pickIntent.setType("image/*");
+
+ Intent chooserIntent = Intent.createChooser(getIntent, getString(R.string.toot_select_image));
+ chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
+ startActivityForResult(chooserIntent, PICK_IMAGE_HEADER);
+ }
+ });
+
+ set_change_profile_picture.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ getIntent.setType("image/*");
+
+ Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+ pickIntent.setType("image/*");
+
+ Intent chooserIntent = Intent.createChooser(getIntent, getString(R.string.toot_select_image));
+ chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
+ startActivityForResult(chooserIntent, PICK_IMAGE_PROFILE);
+ }
+ });
+
+ imageLoader.displayImage(account.getAvatar(), set_profile_picture, options);
+ imageLoader.displayImage(account.getHeader(), set_header_picture, options);
+
+ if( account.getHeader() == null || account.getHeader().contains("missing.png"))
+ set_header_picture_overlay.setVisibility(View.VISIBLE);
+
+
+ set_profile_save.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if(set_profile_name.getText() != null && !set_profile_name.getText().toString().equals(set_profile_name.getHint()))
+ profile_username = set_profile_name.getText().toString().trim();
+ else
+ profile_username = null;
+
+ if(set_profile_description.getText() != null && !set_profile_description.getText().toString().equals(set_profile_description.getHint()))
+ profile_note = set_profile_description.getText().toString().trim();
+ else
+ profile_note = null;
+
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
+ LayoutInflater inflater = ((MainActivity) context).getLayoutInflater();
+ View dialogView = inflater.inflate(R.layout.dialog_profile, null);
+ dialogBuilder.setView(dialogView);
+
+ ImageView back_ground_image = (ImageView) dialogView.findViewById(R.id.back_ground_image);
+ ImageView dialog_profile_picture = (ImageView) dialogView.findViewById(R.id.dialog_profile_picture);
+ TextView dialog_profile_name = (TextView) dialogView.findViewById(R.id.dialog_profile_name);
+ TextView dialog_profile_description = (TextView) dialogView.findViewById(R.id.dialog_profile_description);
+
+ if( profile_username != null)
+ dialog_profile_name.setText(profile_username);
+ if( profile_note != null)
+ dialog_profile_description.setText(profile_note);
+ if( profile_header_bmp != null) {
+ BitmapDrawable background = new BitmapDrawable(context.getResources(), profile_header_bmp);
+ if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ //noinspection deprecation
+ back_ground_image.setBackgroundDrawable(background);
+ } else {
+ back_ground_image.setBackground(background);
+ }
+ }else {
+ if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ //noinspection deprecation
+ back_ground_image.setBackgroundDrawable(set_header_picture.getDrawable());
+ } else {
+ back_ground_image.setBackground(set_header_picture.getDrawable());
+ }
+ }
+ if( profile_picture_bmp != null) {
+ BitmapDrawable background = new BitmapDrawable(context.getResources(), profile_picture_bmp);
+ if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ //noinspection deprecation
+ dialog_profile_picture.setBackgroundDrawable(background);
+ } else {
+ dialog_profile_picture.setBackground(background);
+ }
+ }else {
+ if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ //noinspection deprecation
+ dialog_profile_picture.setBackgroundDrawable(set_profile_picture.getDrawable());
+ } else {
+ dialog_profile_picture.setBackground(set_profile_picture.getDrawable());
+ }
+ }
+ dialogBuilder.setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ set_profile_save.setEnabled(false);
+ new UpdateCredentialAsyncTask(context, profile_username, profile_note, profile_picture, header_picture, SettingsProfileFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+ dialogBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+ AlertDialog alertDialog = dialogBuilder.create();
+ alertDialog.show();
+
+ }
+ });
+ }
+
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == PICK_IMAGE_HEADER && resultCode == Activity.RESULT_OK) {
+ if (data == null) {
+ Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ return;
+ }
+ try {
+ InputStream inputStream = context.getContentResolver().openInputStream(data.getData());
+ BufferedInputStream bufferedInputStream;
+ if (inputStream != null) {
+ bufferedInputStream = new BufferedInputStream(inputStream);
+ }else {
+ Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ return;
+ }
+ Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
+ profile_header_bmp = Bitmap.createScaledBitmap(bmp, 700, 335, true);
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ profile_header_bmp.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
+ set_header_picture.setImageBitmap(profile_header_bmp);
+ byte[] byteArray = byteArrayOutputStream .toByteArray();
+ header_picture = "data:image/png;base64, " + Base64.encodeToString(byteArray, Base64.DEFAULT);
+
+ } catch (FileNotFoundException e) {
+ Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ e.printStackTrace();
+ }
+ }else if(requestCode == PICK_IMAGE_PROFILE && resultCode == Activity.RESULT_OK) {
+ if (data == null) {
+ Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ return;
+ }
+ try {
+ InputStream inputStream = context.getContentResolver().openInputStream(data.getData());
+ BufferedInputStream bufferedInputStream;
+ if (inputStream != null) {
+ bufferedInputStream = new BufferedInputStream(inputStream);
+ }else {
+ Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ return;
+ }
+ Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
+ profile_picture_bmp = Bitmap.createScaledBitmap(bmp, 120, 120, true);
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ profile_picture_bmp.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
+ set_profile_picture.setImageBitmap(profile_picture_bmp);
+ byte[] byteArray = byteArrayOutputStream .toByteArray();
+ profile_picture = "data:image/png;base64, " + Base64.encodeToString(byteArray, Base64.DEFAULT);
+ } catch (FileNotFoundException e) {
+ Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void onUpdateCredential(APIResponse apiResponse) {
+ if( apiResponse.getError() != null){
+ Toast.makeText(context, R.string.toast_error, Toast.LENGTH_LONG).show();
+ return;
+ }
+ Toast.makeText(context, R.string.toast_update_credential_ok, Toast.LENGTH_LONG).show();
+ set_profile_save.setEnabled(true);
+ }
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java
index 758076190..07f568433 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java
@@ -42,6 +42,7 @@ public class TabLayoutSettingsFragment extends Fragment {
TabLayout tabLayout = (TabLayout) inflatedView.findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.notifications)));
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.optimization)));
+ tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.profile)));
final ViewPager viewPager = (ViewPager) inflatedView.findViewById(R.id.viewpager);
viewPager.setAdapter(new PagerAdapter
@@ -86,6 +87,8 @@ public class TabLayoutSettingsFragment extends Fragment {
return new SettingsNotificationsFragment();
case 1:
return new SettingsOptimizationFragment();
+ case 2:
+ return new SettingsProfileFragment();
default:
return new SettingsNotificationsFragment();
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveInstanceInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveInstanceInterface.java
new file mode 100644
index 000000000..9b0b050a2
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveInstanceInterface.java
@@ -0,0 +1,25 @@
+/* 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.interfaces;
+
+import fr.gouv.etalab.mastodon.client.APIResponse;
+
+/**
+ * Created by Thomas on 05/06/2017.
+ * Interface when an instance has been retrieved
+ */
+public interface OnRetrieveInstanceInterface {
+ void onRetrieveInstance(APIResponse apiResponse);
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnUpdateCredentialInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnUpdateCredentialInterface.java
new file mode 100644
index 000000000..f89bc728d
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnUpdateCredentialInterface.java
@@ -0,0 +1,26 @@
+/* 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.interfaces;
+
+
+import fr.gouv.etalab.mastodon.client.APIResponse;
+
+/**
+ * Created by Thomas on 05/06/2017.
+ * Interface when credentials are updated
+ */
+public interface OnUpdateCredentialInterface {
+ void onUpdateCredential(APIResponse apiResponse);
+}
diff --git a/app/src/main/res/drawable-hdpi/ic_email_white.png b/app/src/main/res/drawable-hdpi/ic_email_white.png
new file mode 100644
index 000000000..715102565
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_email_white.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_email_white.png b/app/src/main/res/drawable-ldpi/ic_email_white.png
new file mode 100644
index 000000000..985135adb
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_email_white.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_email_white.png b/app/src/main/res/drawable-mdpi/ic_email_white.png
new file mode 100644
index 000000000..f1aea58fe
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_email_white.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_email_white.png b/app/src/main/res/drawable-xhdpi/ic_email_white.png
new file mode 100644
index 000000000..77ddef573
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_email_white.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_email_white.png b/app/src/main/res/drawable-xxhdpi/ic_email_white.png
new file mode 100644
index 000000000..107653456
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_email_white.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_email_white.png b/app/src/main/res/drawable-xxxhdpi/ic_email_white.png
new file mode 100644
index 000000000..2b7b8cda6
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_email_white.png differ
diff --git a/app/src/main/res/layout/activity_instance.xml b/app/src/main/res/layout/activity_instance.xml
new file mode 100644
index 000000000..d352661cf
--- /dev/null
+++ b/app/src/main/res/layout/activity_instance.xml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_profile.xml b/app/src/main/res/layout/dialog_profile.xml
new file mode 100644
index 000000000..e6b60e39b
--- /dev/null
+++ b/app/src/main/res/layout/dialog_profile.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_settings_profile.xml b/app/src/main/res/layout/fragment_settings_profile.xml
new file mode 100644
index 000000000..bb725b90f
--- /dev/null
+++ b/app/src/main/res/layout/fragment_settings_profile.xml
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml
index 3a6e1f684..b9fdacf85 100644
--- a/app/src/main/res/menu/main.xml
+++ b/app/src/main/res/menu/main.xml
@@ -14,6 +14,10 @@
android:id="@+id/action_privacy"
android:title="@string/action_privacy"
app:showAsAction="never" />
+
- #E0E0E0
#424242
#FDD835
+
+
+ #282c37
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8ff4b0b6b..75e57b567 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -6,6 +6,7 @@
Paramètres
A propos
+ A propos de l\'instance
Confidentialité
Déconnexion
@@ -24,6 +25,7 @@
Pouets
Tags
Jeton
+ Sauvegarder
Authentification en deux étapes ?
Autre instance que mastodon.etalab.gouv.fr ?
Aucun résultat !
@@ -31,6 +33,8 @@
Utilisation du compte %1$s
Ajouter un compte
Le contenu du pouet a été copié dans le presse-papier
+ Changer
+ Changer l\'image…
Accueil
Accueil
@@ -45,9 +49,11 @@
Utilisateurs bloqués
Notifications
Optimisation
+ Profil
Que souhaitez-vous faire ?
Supprimer un compte
Supprimer le compte %1$s de l\'application ?
+ Envoyer un email
Aucun pouet à afficher !
@@ -135,6 +141,8 @@
- N\'afficher que pour les personnes mentionnées
+
+ Aucune description !
Version %1$s
@@ -190,6 +198,7 @@
Oups ! Une erreur s\'est produite !
Une erreur s\'est produite en chargeant le compte !
Impossible de vous connecter !
+ Les données du profil ont été sauvegardées !
Optimisation du chargement
Nombre de pouets par chargement
@@ -213,11 +222,18 @@
Notifier en WIFI seulement
Utiliser le vibreur
+ Modifier le profil
+ Présentation…
+ Enregistrer les modifications
+ Choisissez une image d\'entête
+ Vous avez atteint les 160 caractères autorisés !
+ Vous avez atteint les 30 caractères autorisés !
+
Actualités
Notifier lors de nouveaux pouets sur la page d\'accueil
Afficher les messages d\'erreur
Suivre
- Se désabonner
+ Se désabonners
Bloquer
Débloquer
Masquer