Opens to other instances + some improvements + some bug fixes + privacy activity
This commit is contained in:
parent
e619a8651d
commit
9d66499883
|
@ -80,6 +80,11 @@
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
/>
|
/>
|
||||||
|
<activity android:name="fr.gouv.etalab.mastodon.activities.PrivacyActivity"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
/>
|
||||||
<activity android:name="fr.gouv.etalab.mastodon.activities.TootActivity"
|
<activity android:name="fr.gouv.etalab.mastodon.activities.TootActivity"
|
||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
|
|
|
@ -18,6 +18,7 @@ import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
@ -25,6 +26,13 @@ import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveDeveloperAccountsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Error;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface;
|
||||||
import mastodon.etalab.gouv.fr.mastodon.R;
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +41,10 @@ import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
* About activity
|
* About activity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class AboutActivity extends AppCompatActivity {
|
public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcAccountshInterface {
|
||||||
|
|
||||||
|
private Button about_developer;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -48,7 +59,7 @@ public class AboutActivity extends AppCompatActivity {
|
||||||
about_version.setText(getResources().getString(R.string.about_vesrion, version));
|
about_version.setText(getResources().getString(R.string.about_vesrion, version));
|
||||||
} catch (PackageManager.NameNotFoundException ignored) {}
|
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||||
|
|
||||||
Button about_developer = (Button) findViewById(R.id.about_developer);
|
about_developer = (Button) findViewById(R.id.about_developer);
|
||||||
Button about_code = (Button) findViewById(R.id.about_code);
|
Button about_code = (Button) findViewById(R.id.about_code);
|
||||||
Button about_license = (Button) findViewById(R.id.about_license);
|
Button about_license = (Button) findViewById(R.id.about_license);
|
||||||
|
|
||||||
|
@ -59,14 +70,15 @@ public class AboutActivity extends AppCompatActivity {
|
||||||
startActivity(browserIntent);
|
startActivity(browserIntent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if(Helper.isLoggedIn(getApplicationContext())) {
|
||||||
|
about_developer.setEnabled(false);
|
||||||
|
new RetrieveDeveloperAccountsAsyncTask(getApplicationContext(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
about_developer.setOnClickListener(new View.OnClickListener() {
|
about_developer.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Intent intent = new Intent(AboutActivity.this, ShowAccountActivity.class);
|
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://mastodon.etalab.gouv.fr/@tschneider"));
|
||||||
Bundle b = new Bundle();
|
startActivity(browserIntent);
|
||||||
b.putString("accountId", "2416");
|
|
||||||
intent.putExtras(b);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
about_license.setOnClickListener(new View.OnClickListener() {
|
about_license.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@ -89,4 +101,22 @@ public class AboutActivity extends AppCompatActivity {
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveSearchAccounts(final List<Account> 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ import android.os.Bundle;
|
||||||
import android.support.design.widget.NavigationView;
|
import android.support.design.widget.NavigationView;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
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();
|
Bundle b = getIntent().getExtras();
|
||||||
if(b != null)
|
if(b != null)
|
||||||
addAccount = b.getBoolean("addAccount", false);
|
addAccount = b.getBoolean("addAccount", false);
|
||||||
|
@ -106,6 +121,8 @@ public class LoginActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if( addAccount)
|
||||||
|
other_instance.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -199,7 +216,9 @@ public class LoginActivity extends AppCompatActivity {
|
||||||
requestParams.add("scope"," read write follow");
|
requestParams.add("scope"," read write follow");
|
||||||
client.setUserAgent(USER_AGENT);
|
client.setUserAgent(USER_AGENT);
|
||||||
try {
|
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() {
|
client.post("https://" + instance+ "/oauth/token", requestParams, new AsyncHttpResponseHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -282,6 +282,9 @@ public class MainActivity extends AppCompatActivity
|
||||||
}else if(id == R.id.action_about){
|
}else if(id == R.id.action_about){
|
||||||
Intent intent = new Intent(getApplicationContext(), AboutActivity.class);
|
Intent intent = new Intent(getApplicationContext(), AboutActivity.class);
|
||||||
startActivity(intent);
|
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){
|
}else if(id == R.id.action_search){
|
||||||
|
|
||||||
if( toolbar.getChildCount() > 0){
|
if( toolbar.getChildCount() > 0){
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses>. */
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -105,9 +105,6 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_show_account);
|
setContentView(R.layout.activity_show_account);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
imageLoader = ImageLoader.getInstance();
|
imageLoader = ImageLoader.getInstance();
|
||||||
statuses = new ArrayList<>();
|
statuses = new ArrayList<>();
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses>. */
|
||||||
|
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<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private List<Account> 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -850,6 +850,32 @@ public class API {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves Developer account when searching (ie: via @...) *synchronously*
|
||||||
|
*
|
||||||
|
* @return List<Account>
|
||||||
|
*/
|
||||||
|
public List<Account> 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*
|
* Retrieves Accounts when searching (ie: via @...) *synchronously*
|
||||||
*
|
*
|
||||||
|
@ -926,60 +952,10 @@ public class API {
|
||||||
try {
|
try {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < jsonArray.length() ){
|
while (i < jsonArray.length() ){
|
||||||
Status status = new Status();
|
|
||||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||||
status.setId(resobj.get("id").toString());
|
Status status = parseStatuses(resobj);
|
||||||
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<Attachment> 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<Mention> 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){}
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,6 +1001,20 @@ public class API {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status.setMedia_attachments(attachments);
|
status.setMedia_attachments(attachments);
|
||||||
|
List<Mention> 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.setAccount(parseAccountResponse(resobj.getJSONObject("account")));
|
||||||
status.setContent(resobj.get("content").toString());
|
status.setContent(resobj.get("content").toString());
|
||||||
status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString()));
|
status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString()));
|
||||||
|
@ -1082,23 +1072,8 @@ public class API {
|
||||||
try {
|
try {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < jsonArray.length() ) {
|
while (i < jsonArray.length() ) {
|
||||||
Account account = new Account();
|
|
||||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||||
account.setId(resobj.get("id").toString());
|
Account account = parseAccountResponse(resobj);
|
||||||
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());
|
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -1108,6 +1083,33 @@ public class API {
|
||||||
return accounts;
|
return accounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse json response for list of accounts which could contain the developer name
|
||||||
|
* @param jsonArray JSONArray
|
||||||
|
* @return List<Account>
|
||||||
|
*/
|
||||||
|
private List<Account> parseDeveloperResponse(JSONArray jsonArray){
|
||||||
|
|
||||||
|
List<Account> 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
|
* Parse json response for the context
|
||||||
* @param jsonObject JSONObject
|
* @param jsonObject JSONObject
|
||||||
|
@ -1208,16 +1210,9 @@ public class API {
|
||||||
try {
|
try {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < jsonArray.length() ) {
|
while (i < jsonArray.length() ) {
|
||||||
Notification notification = new Notification();
|
|
||||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||||
notification.setId(resobj.get("id").toString());
|
Notification notification = parseNotificationResponse(resobj);
|
||||||
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()));
|
|
||||||
notifications.add(notification);
|
notifications.add(notification);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -1246,7 +1241,9 @@ public class API {
|
||||||
client.setConnectTimeout(10000); //10s timeout
|
client.setConnectTimeout(10000); //10s timeout
|
||||||
client.setUserAgent(USER_AGENT);
|
client.setUserAgent(USER_AGENT);
|
||||||
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
|
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);
|
client.get(getAbsoluteUrl(action), params, responseHandler);
|
||||||
|
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||||
|
@ -1261,7 +1258,9 @@ public class API {
|
||||||
client.setConnectTimeout(10000); //10s timeout
|
client.setConnectTimeout(10000); //10s timeout
|
||||||
client.setUserAgent(USER_AGENT);
|
client.setUserAgent(USER_AGENT);
|
||||||
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
|
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);
|
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||||
Toast.makeText(context, R.string.toast_error,Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.toast_error,Toast.LENGTH_LONG).show();
|
||||||
|
@ -1274,7 +1273,9 @@ public class API {
|
||||||
client.setConnectTimeout(10000); //10s timeout
|
client.setConnectTimeout(10000); //10s timeout
|
||||||
client.setUserAgent(USER_AGENT);
|
client.setUserAgent(USER_AGENT);
|
||||||
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
|
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);
|
client.delete(getAbsoluteUrl(action), params, responseHandler);
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||||
Toast.makeText(context, R.string.toast_error,Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.toast_error,Toast.LENGTH_LONG).show();
|
||||||
|
|
|
@ -47,7 +47,9 @@ public class OauthClient {
|
||||||
try {
|
try {
|
||||||
client.setConnectTimeout(10000); //10s timeout
|
client.setConnectTimeout(10000); //10s timeout
|
||||||
client.setUserAgent(USER_AGENT);
|
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);
|
client.get(getAbsoluteUrl(action), params, responseHandler);
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -58,7 +60,9 @@ public class OauthClient {
|
||||||
try {
|
try {
|
||||||
client.setConnectTimeout(10000); //10s timeout
|
client.setConnectTimeout(10000); //10s timeout
|
||||||
client.setUserAgent(USER_AGENT);
|
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);
|
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -16,6 +16,8 @@ package fr.gouv.etalab.mastodon.drawers;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.content.ClipData;
|
||||||
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -32,6 +34,7 @@ import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.util.Linkify;
|
import android.text.util.Linkify;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -437,7 +440,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
|
||||||
final RelativeLayout loader = (RelativeLayout) view.findViewById(R.id.loader);
|
final RelativeLayout loader = (RelativeLayout) view.findViewById(R.id.loader);
|
||||||
switch (attachment.getType()){
|
switch (attachment.getType()){
|
||||||
case "image": {
|
case "image": {
|
||||||
String url = attachment.getRemote_url();
|
String url = attachment.getPreview_url();
|
||||||
if(url == null || url.trim().equals(""))
|
if(url == null || url.trim().equals(""))
|
||||||
url = attachment.getUrl();
|
url = attachment.getUrl();
|
||||||
final ImageView imageView = (ImageView) view.findViewById(R.id.dialog_imageview);
|
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);
|
AlertDialog.Builder builderInner = new AlertDialog.Builder(context);
|
||||||
builderInner.setTitle(stringArrayConf[which]);
|
builderInner.setTitle(stringArrayConf[which]);
|
||||||
if( isOwner) {
|
if( isOwner) {
|
||||||
|
if( which == 0) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||||
else
|
else
|
||||||
//noinspection deprecation
|
//noinspection deprecation
|
||||||
builderInner.setMessage(Html.fromHtml(status.getContent()));
|
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 {
|
}else {
|
||||||
if( which < 2 ){
|
if( which < 2 ){
|
||||||
builderInner.setMessage(status.getAccount().getAcct());
|
builderInner.setMessage(status.getAccount().getAcct());
|
||||||
}else {
|
}else if( which < 3) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||||
else
|
else
|
||||||
//noinspection deprecation
|
//noinspection deprecation
|
||||||
builderInner.setMessage(Html.fromHtml(status.getContent()));
|
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
|
//Text for report
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -55,7 +56,7 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
|
||||||
private Context context;
|
private Context context;
|
||||||
private AsyncTask<Void, Void, Void> asyncTask;
|
private AsyncTask<Void, Void, Void> asyncTask;
|
||||||
private NotificationsListAdapter notificationsListAdapter;
|
private NotificationsListAdapter notificationsListAdapter;
|
||||||
private String max_id = null;
|
private String max_id;
|
||||||
private List<Notification> notifications;
|
private List<Notification> notifications;
|
||||||
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
|
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
|
||||||
private boolean firstLoad;
|
private boolean firstLoad;
|
||||||
|
@ -66,7 +67,7 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
View rootView = inflater.inflate(R.layout.fragment_notifications, container, false);
|
View rootView = inflater.inflate(R.layout.fragment_notifications, container, false);
|
||||||
|
max_id = null;
|
||||||
context = getContext();
|
context = getContext();
|
||||||
firstLoad = true;
|
firstLoad = true;
|
||||||
flag_loading = true;
|
flag_loading = true;
|
||||||
|
|
|
@ -110,6 +110,7 @@ public class Helper {
|
||||||
public static final String WEBSITE = "website";
|
public static final String WEBSITE = "website";
|
||||||
public static final String LAST_NOTIFICATION_MAX_ID = "last_notification_max_id";
|
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 LAST_HOMETIMELINE_MAX_ID = "last_hometimeline_max_id";
|
||||||
|
public static final String CLIP_BOARD = "clipboard";
|
||||||
//Notifications
|
//Notifications
|
||||||
public static final int NOTIFICATION_INTENT = 1;
|
public static final int NOTIFICATION_INTENT = 1;
|
||||||
public static final int HOME_TIMELINE_INTENT = 2;
|
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
|
// prepare intent which is triggered if the user click on the notification
|
||||||
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
||||||
PendingIntent pIntent = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_ONE_SHOT);
|
PendingIntent pIntent = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_ONE_SHOT);
|
||||||
|
|
||||||
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||||
// build notification
|
// build notification
|
||||||
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
|
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
|
||||||
|
|
|
@ -22,7 +22,6 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.evernote.android.job.Job;
|
import com.evernote.android.job.Job;
|
||||||
import com.evernote.android.job.JobManager;
|
import com.evernote.android.job.JobManager;
|
||||||
|
@ -64,6 +63,7 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
|
||||||
static final String HOME_TIMELINE = "home_timeline";
|
static final String HOME_TIMELINE = "home_timeline";
|
||||||
private int notificationId;
|
private int notificationId;
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected Result onRunJob(Params params) {
|
protected Result onRunJob(Params params) {
|
||||||
|
@ -93,11 +93,17 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
|
||||||
* Task in background starts here.
|
* Task in background starts here.
|
||||||
*/
|
*/
|
||||||
private void callAsynchronousTask() {
|
private void callAsynchronousTask() {
|
||||||
|
|
||||||
|
|
||||||
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
boolean notif_hometimeline = sharedpreferences.getBoolean(Helper.SET_NOTIF_HOMETIMELINE, true);
|
boolean notif_hometimeline = sharedpreferences.getBoolean(Helper.SET_NOTIF_HOMETIMELINE, true);
|
||||||
|
|
||||||
//User disagree with home timeline refresh
|
//User disagree with home timeline refresh
|
||||||
if( !notif_hometimeline)
|
if( !notif_hometimeline)
|
||||||
return; //Nothing is done
|
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();
|
SQLiteDatabase db = Sqlite.getInstance(getContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
//If an Internet connection and user agrees with notification refresh
|
//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.
|
//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.
|
//Retrieve users in db that owner has.
|
||||||
for (Account account: accounts) {
|
for (Account account: accounts) {
|
||||||
String since_id = sharedpreferences.getString(Helper.LAST_HOMETIMELINE_MAX_ID + account.getId(), null);
|
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);
|
new RetrieveHomeTimelineServiceAsyncTask(getContext(), account.getInstance(), account.getToken(), since_id, account.getAcct(), account.getId(), HomeTimelineSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -162,6 +169,8 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
|
||||||
intent.putExtra(INTENT_ACTION, HOME_TIMELINE_INTENT);
|
intent.putExtra(INTENT_ACTION, HOME_TIMELINE_INTENT);
|
||||||
intent.putExtra(PREF_KEY_ID, userId);
|
intent.putExtra(PREF_KEY_ID, userId);
|
||||||
|
|
||||||
|
if( max_id != null)
|
||||||
notify_user(getContext(), intent, notificationId, icon_notification,title,message);
|
notify_user(getContext(), intent, notificationId, icon_notification,title,message);
|
||||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statuses.get(0).getId());
|
editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statuses.get(0).getId());
|
||||||
|
|
|
@ -22,8 +22,6 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
|
|
||||||
import com.evernote.android.job.Job;
|
import com.evernote.android.job.Job;
|
||||||
import com.evernote.android.job.JobManager;
|
import com.evernote.android.job.JobManager;
|
||||||
|
@ -110,6 +108,9 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
|
||||||
//User disagree with all notifications
|
//User disagree with all notifications
|
||||||
if( !notif_follow && !notif_add && !notif_ask && !notif_mention && !notif_share)
|
if( !notif_follow && !notif_add && !notif_ask && !notif_mention && !notif_share)
|
||||||
return; //Nothing is done
|
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 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())) {
|
if(!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(getContext())) {
|
||||||
List<Account> accounts = new AccountDAO(getContext(),db).getAllAccount();
|
List<Account> accounts = new AccountDAO(getContext(),db).getAllAccount();
|
||||||
|
@ -119,7 +120,8 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
|
||||||
//Retrieve users in db that owner has.
|
//Retrieve users in db that owner has.
|
||||||
for (Account account: accounts) {
|
for (Account account: accounts) {
|
||||||
String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId(), null);
|
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);
|
new RetrieveNotificationsAsyncTask(getContext(), account.getInstance(), account.getToken(), max_id, account.getAcct(), account.getId(), NotificationsSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,6 +223,7 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
|
||||||
intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT);
|
intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT);
|
||||||
intent.putExtra(PREF_KEY_ID, userId);
|
intent.putExtra(PREF_KEY_ID, userId);
|
||||||
|
if( max_id != null)
|
||||||
notify_user(getContext(), intent, notificationId, icon_notification,title,message);
|
notify_user(getContext(), intent, notificationId, icon_notification,title,message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,16 @@
|
||||||
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
|
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
|
||||||
see <http://www.gnu.org/licenses>.
|
see <http://www.gnu.org/licenses>.
|
||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:background="#fff"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/drawer_layout"
|
android:id="@+id/drawer_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:background="#fff"
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
>
|
>
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -37,8 +41,6 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:id="@+id/login_instance"
|
android:id="@+id/login_instance"
|
||||||
|
@ -47,7 +49,6 @@
|
||||||
android:inputType="textWebEmailAddress"
|
android:inputType="textWebEmailAddress"
|
||||||
android:hint="@string/instance"
|
android:hint="@string/instance"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/login_uid"
|
android:id="@+id/login_uid"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -55,7 +56,6 @@
|
||||||
android:inputType="textEmailAddress"
|
android:inputType="textEmailAddress"
|
||||||
android:hint="@string/email"
|
android:hint="@string/email"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id = "@+id/login_passwd"
|
android:id = "@+id/login_passwd"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
|
@ -63,7 +63,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/login_button"
|
android:id="@+id/login_button"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
|
@ -83,8 +82,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:text="@string/login" />
|
android:text="@string/login" />
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/login_two_step"
|
android:id="@+id/login_two_step"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
|
@ -97,6 +94,17 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/colorPrimary"
|
android:textColor="@color/colorPrimary"
|
||||||
android:text="@string/two_factor_authentification" />
|
android:text="@string/two_factor_authentification" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/other_instance"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:gravity="center"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:padding="20dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/colorPrimary"
|
||||||
|
android:text="@string/other_instance" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</ScrollView>
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
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 <http://www.gnu.org/licenses>.
|
||||||
|
-->
|
||||||
|
<ScrollView android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<!-- App authorizations -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:padding="@dimen/fab_margin"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
|
<!-- APPS AUTHORIZATIONS TITLE -->
|
||||||
|
<TextView
|
||||||
|
android:text="@string/privacy_authorizations_title"
|
||||||
|
android:background="@drawable/shape_border_bottom_settings"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<!-- APPS AUTHORIZATIONS CONTENT -->
|
||||||
|
<TextView
|
||||||
|
android:text="@string/privacy_authorizations"
|
||||||
|
android:autoLink="web"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- API authorizations -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:padding="@dimen/fab_margin"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
|
<!-- API AUTHORIZATIONS TITLE -->
|
||||||
|
<TextView
|
||||||
|
android:text="@string/privacy_API_authorizations_title"
|
||||||
|
android:background="@drawable/shape_border_bottom_settings"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<!-- API AUTHORIZATIONS CONTENT -->
|
||||||
|
<TextView
|
||||||
|
android:text="@string/privacy_API_authorizations"
|
||||||
|
android:autoLink="web"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -10,6 +10,10 @@
|
||||||
android:id="@+id/action_about"
|
android:id="@+id/action_about"
|
||||||
android:title="@string/action_about"
|
android:title="@string/action_about"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_privacy"
|
||||||
|
android:title="@string/action_privacy"
|
||||||
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_logout"
|
android:id="@+id/action_logout"
|
||||||
android:title="@string/action_logout"
|
android:title="@string/action_logout"
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_about"
|
||||||
|
android:title="@string/action_about"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_privacy"
|
||||||
|
android:title="@string/action_privacy"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
</menu>
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
<string name="action_settings">Paramètres</string>
|
<string name="action_settings">Paramètres</string>
|
||||||
<string name="action_about">A propos</string>
|
<string name="action_about">A propos</string>
|
||||||
|
<string name="action_privacy">Confidentialité</string>
|
||||||
<string name="action_logout">Déconnexion</string>
|
<string name="action_logout">Déconnexion</string>
|
||||||
|
|
||||||
<string name="login">Connexion</string>
|
<string name="login">Connexion</string>
|
||||||
|
@ -23,10 +24,12 @@
|
||||||
<string name="toots">Pouets</string>
|
<string name="toots">Pouets</string>
|
||||||
<string name="token">Jeton</string>
|
<string name="token">Jeton</string>
|
||||||
<string name="two_factor_authentification">Authentification en deux étapes ?</string>
|
<string name="two_factor_authentification">Authentification en deux étapes ?</string>
|
||||||
|
<string name="other_instance">Autre instance que mastodon.etalab.gouv.fr ?</string>
|
||||||
<string name="no_result">Aucun résultat !</string>
|
<string name="no_result">Aucun résultat !</string>
|
||||||
<string name="instance">Instance</string>
|
<string name="instance">Instance</string>
|
||||||
<string name="toast_account_changed">Utilisation du compte %1$s</string>
|
<string name="toast_account_changed">Utilisation du compte %1$s</string>
|
||||||
<string name="add_account">Ajouter un compte</string>
|
<string name="add_account">Ajouter un compte</string>
|
||||||
|
<string name="clipboard">Le contenu du pouet a été copié dans le presse-papier</string>
|
||||||
<!--- Menu -->
|
<!--- Menu -->
|
||||||
<string name="home_menu">Accueil</string>
|
<string name="home_menu">Accueil</string>
|
||||||
<string name="home_timeline">Accueil</string>
|
<string name="home_timeline">Accueil</string>
|
||||||
|
@ -61,15 +64,18 @@
|
||||||
<item>Masquer</item>
|
<item>Masquer</item>
|
||||||
<item>Bloquer</item>
|
<item>Bloquer</item>
|
||||||
<item>Signaler</item>
|
<item>Signaler</item>
|
||||||
|
<item>Copier</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="more_action_owner">
|
<string-array name="more_action_owner">
|
||||||
<item>Supprimer</item>
|
<item>Supprimer</item>
|
||||||
|
<item>Copier</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="more_action_confirm">
|
<string-array name="more_action_confirm">
|
||||||
<item>Masquer ce compte ?</item>
|
<item>Masquer ce compte ?</item>
|
||||||
<item>Bloquer ce compte ?</item>
|
<item>Bloquer ce compte ?</item>
|
||||||
<item>Signaler ce pouet ?</item>
|
<item>Signaler ce pouet ?</item>
|
||||||
|
<item>null</item> <!-- Ugly hack to fix confirm box-->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,6 +224,26 @@
|
||||||
<string name="request_sent">Demande envoyée</string>
|
<string name="request_sent">Demande envoyée</string>
|
||||||
<string name="followed_by">Vous suit</string>
|
<string name="followed_by">Vous suit</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="action_search">Recherche</string>
|
<string name="action_search">Recherche</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- PRIVACY -->
|
||||||
|
<string name="privacy_authorizations_title">Autorisations de l\'application</string>
|
||||||
|
<string name="privacy_authorizations">
|
||||||
|
- <b>ACCESS_NETWORK_STATE</b> : Utilisée pour savoir si l\'appareil est connecté au WIFI.\n
|
||||||
|
- <b>INTERNET</b> : Utilisée pour les requêtes vers l\'instance.\n
|
||||||
|
- <b>WRITE_EXTERNAL_STORAGE</b> : Utilisée pour télécharger les médias / déplacer sur la carte SD.\n
|
||||||
|
- <b>READ_EXTERNAL_STORAGE</b> : Utilisée pour ajouter des médias aux pouets.\n
|
||||||
|
- <b>BOOT_COMPLETED</b> : Utilisée pour lancer le service de notifications quand l\'appareil démarre.\n
|
||||||
|
- <b>WAKE_LOCK</b> : Utilisée lors du service de notifications.\n
|
||||||
|
</string>
|
||||||
|
|
||||||
|
<string name="privacy_API_authorizations_title">Autorisations de l\'API</string>
|
||||||
|
<string name="privacy_API_authorizations">
|
||||||
|
- <b>Read</b> : Lire les données du compte.\n
|
||||||
|
- <b>Write</b> : Envoyer des messages et attacher des médias aux messages.\n
|
||||||
|
- <b>Follow</b> : S\'abonner, se désabonner, bloquer, débloquer.\n\n
|
||||||
|
<b>⚠ Ces actions ne sont réalisées qu\'à la demande de l\'utilisateur.</b>
|
||||||
|
</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue