Merge branch 'nitter_follow_accounts' into develop
This commit is contained in:
commit
14f9d7f4ee
|
@ -160,13 +160,19 @@ public class ReorderTimelinesActivity extends BaseActivity implements OnStartDra
|
|||
AutoCompleteTextView instance_list = dialogView.findViewById(R.id.search_instance);
|
||||
//Manage download of attachments
|
||||
RadioGroup radioGroup = dialogView.findViewById(R.id.set_attachment_group);
|
||||
|
||||
radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
|
||||
if( checkedId == R.id.twitter_accounts){
|
||||
instance_list.setHint(R.string.list_of_twitter_accounts);
|
||||
}else {
|
||||
instance_list.setHint(R.string.instance);
|
||||
}
|
||||
});
|
||||
instance_list.setFilters(new InputFilter[]{new InputFilter.LengthFilter(60)});
|
||||
dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||
String instanceName = instance_list.getText().toString().trim();
|
||||
String instanceName = instance_list.getText().toString().trim().replace("@","");
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -182,7 +188,6 @@ public class ReorderTimelinesActivity extends BaseActivity implements OnStartDra
|
|||
} else if (radioGroup.getCheckedRadioButtonId() == R.id.gnu_instance) {
|
||||
new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/statuses/public_timeline.json", 10, null, null);
|
||||
}
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
dialog.dismiss();
|
||||
|
@ -196,6 +201,8 @@ public class ReorderTimelinesActivity extends BaseActivity implements OnStartDra
|
|||
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "MISSKEY");
|
||||
} else if (radioGroup.getCheckedRadioButtonId() == R.id.gnu_instance) {
|
||||
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "GNU");
|
||||
}else if (radioGroup.getCheckedRadioButtonId() == R.id.twitter_accounts) {
|
||||
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "NITTER");
|
||||
}
|
||||
if (timelines != null && adapter != null) {
|
||||
List<RemoteInstance> instance = new InstancesDAO(ReorderTimelinesActivity.this, db).getInstanceByName(instanceName);
|
||||
|
@ -256,78 +263,84 @@ public class ReorderTimelinesActivity extends BaseActivity implements OnStartDra
|
|||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
Pattern host = Pattern.compile("([\\da-z\\.-]+\\.[a-z\\.]{2,12})");
|
||||
Matcher matcher = host.matcher(s.toString().trim());
|
||||
if (s.toString().trim().length() == 0 || !matcher.find()) {
|
||||
alertDialog.getButton(
|
||||
AlertDialog.BUTTON_POSITIVE).setEnabled(false);
|
||||
} else {
|
||||
// Something into edit text. Enable the button.
|
||||
if (radioGroup.getCheckedRadioButtonId() != R.id.twitter_accounts){
|
||||
Pattern host = Pattern.compile("([\\da-z\\.-]+\\.[a-z\\.]{2,12})");
|
||||
Matcher matcher = host.matcher(s.toString().trim());
|
||||
if (s.toString().trim().length() == 0 || !matcher.find()) {
|
||||
alertDialog.getButton(
|
||||
AlertDialog.BUTTON_POSITIVE).setEnabled(false);
|
||||
} else {
|
||||
// Something into edit text. Enable the button.
|
||||
alertDialog.getButton(
|
||||
AlertDialog.BUTTON_POSITIVE).setEnabled(true);
|
||||
}
|
||||
if (s.length() > 2 && !isLoadingInstance) {
|
||||
final String action = "/instances/search";
|
||||
final HashMap<String, String> parameters = new HashMap<>();
|
||||
parameters.put("q", s.toString().trim());
|
||||
parameters.put("count", String.valueOf(1000));
|
||||
parameters.put("name", String.valueOf(true));
|
||||
isLoadingInstance = true;
|
||||
|
||||
if (oldSearch == null || !oldSearch.equals(s.toString().trim()))
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final String response = new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://instances.social/api/1.0" + action, 30, parameters, Helper.THEKINRAR_SECRET_TOKEN);
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
isLoadingInstance = false;
|
||||
String[] instances;
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(response);
|
||||
JSONArray jsonArray = jsonObject.getJSONArray("instances");
|
||||
if (jsonArray != null) {
|
||||
int length = 0;
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
if (!jsonArray.getJSONObject(i).get("name").toString().contains("@") && jsonArray.getJSONObject(i).get("up").toString().equals("true"))
|
||||
length++;
|
||||
}
|
||||
instances = new String[length];
|
||||
int j = 0;
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
if (!jsonArray.getJSONObject(i).get("name").toString().contains("@") && jsonArray.getJSONObject(i).get("up").toString().equals("true")) {
|
||||
instances[j] = jsonArray.getJSONObject(i).get("name").toString();
|
||||
j++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
instances = new String[]{};
|
||||
}
|
||||
instance_list.setAdapter(null);
|
||||
ArrayAdapter<String> adapter =
|
||||
new ArrayAdapter<>(ReorderTimelinesActivity.this, android.R.layout.simple_list_item_1, instances);
|
||||
instance_list.setAdapter(adapter);
|
||||
if (instance_list.hasFocus() && !ReorderTimelinesActivity.this.isFinishing())
|
||||
instance_list.showDropDown();
|
||||
oldSearch = s.toString().trim();
|
||||
|
||||
} catch (JSONException ignored) {
|
||||
isLoadingInstance = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
isLoadingInstance = false;
|
||||
} catch (Exception e) {
|
||||
isLoadingInstance = false;
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
else
|
||||
isLoadingInstance = false;
|
||||
}
|
||||
}else {
|
||||
alertDialog.getButton(
|
||||
AlertDialog.BUTTON_POSITIVE).setEnabled(true);
|
||||
}
|
||||
if (s.length() > 2 && !isLoadingInstance) {
|
||||
final String action = "/instances/search";
|
||||
final HashMap<String, String> parameters = new HashMap<>();
|
||||
parameters.put("q", s.toString().trim());
|
||||
parameters.put("count", String.valueOf(1000));
|
||||
parameters.put("name", String.valueOf(true));
|
||||
isLoadingInstance = true;
|
||||
|
||||
if (oldSearch == null || !oldSearch.equals(s.toString().trim()))
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final String response = new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://instances.social/api/1.0" + action, 30, parameters, Helper.THEKINRAR_SECRET_TOKEN);
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
isLoadingInstance = false;
|
||||
String[] instances;
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(response);
|
||||
JSONArray jsonArray = jsonObject.getJSONArray("instances");
|
||||
if (jsonArray != null) {
|
||||
int length = 0;
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
if (!jsonArray.getJSONObject(i).get("name").toString().contains("@") && jsonArray.getJSONObject(i).get("up").toString().equals("true"))
|
||||
length++;
|
||||
}
|
||||
instances = new String[length];
|
||||
int j = 0;
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
if (!jsonArray.getJSONObject(i).get("name").toString().contains("@") && jsonArray.getJSONObject(i).get("up").toString().equals("true")) {
|
||||
instances[j] = jsonArray.getJSONObject(i).get("name").toString();
|
||||
j++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
instances = new String[]{};
|
||||
}
|
||||
instance_list.setAdapter(null);
|
||||
ArrayAdapter<String> adapter =
|
||||
new ArrayAdapter<>(ReorderTimelinesActivity.this, android.R.layout.simple_list_item_1, instances);
|
||||
instance_list.setAdapter(adapter);
|
||||
if (instance_list.hasFocus() && !ReorderTimelinesActivity.this.isFinishing())
|
||||
instance_list.showDropDown();
|
||||
oldSearch = s.toString().trim();
|
||||
|
||||
} catch (JSONException ignored) {
|
||||
isLoadingInstance = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
isLoadingInstance = false;
|
||||
} catch (Exception e) {
|
||||
isLoadingInstance = false;
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
else
|
||||
isLoadingInstance = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -249,7 +249,15 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
|
|||
status.setType(action);
|
||||
}
|
||||
}
|
||||
} else if (remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("PIXELFED")) {
|
||||
} else if (remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("NITTER")) {
|
||||
apiResponse = api.getNitter(this.instanceName, max_id);
|
||||
List<app.fedilab.android.client.Entities.Status> statusesTemp = apiResponse.getStatuses();
|
||||
if (statusesTemp != null) {
|
||||
for (app.fedilab.android.client.Entities.Status status : statusesTemp) {
|
||||
status.setType(action);
|
||||
}
|
||||
}
|
||||
}else if (remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("PIXELFED")) {
|
||||
apiResponse = api.getPixelfedTimeline(instanceName, max_id);
|
||||
} else if (remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("GNU")) {
|
||||
apiResponse = api.getGNUTimeline(instanceName, max_id);
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.SharedPreferences;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Bundle;
|
||||
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -28,15 +29,21 @@ import com.google.gson.JsonObject;
|
|||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
@ -45,6 +52,8 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
|
@ -760,6 +769,159 @@ public class API {
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse xml response for Nitter
|
||||
*
|
||||
* @param xml String
|
||||
* @return List<Status>
|
||||
*/
|
||||
|
||||
private List<Status> parseNitter(String xml) {
|
||||
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
String nitterHost = sharedpreferences.getString(Helper.SET_NITTER_HOST, Helper.DEFAULT_NITTER_HOST).toLowerCase();
|
||||
|
||||
List<Status> statuses = new ArrayList<>();
|
||||
try {
|
||||
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
XmlPullParser xpp = factory.newPullParser();
|
||||
|
||||
xpp.setInput( new StringReader( xml ) );
|
||||
int eventType = xpp.getEventType();
|
||||
Account account = null;
|
||||
Status status = null;
|
||||
HashMap<String, String> mappedProfile = new HashMap<>();
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
|
||||
if(eventType == XmlPullParser.START_TAG) {
|
||||
if( xpp.getName().compareTo("item") == 0 ){
|
||||
status = new Status();
|
||||
status.setReplies_count(0);
|
||||
status.setFavourites_count(0);
|
||||
status.setReblogs_count(0);
|
||||
status.setFavourited(false);
|
||||
status.setReblogged(false);
|
||||
status.setEmojiFound(true);
|
||||
status.setPollEmojiFound(true);
|
||||
status.setEmojiTranslateFound(true);
|
||||
status.setMedia_attachments(new ArrayList<>());
|
||||
account = new Account();
|
||||
}else if( xpp.getName().compareTo("creator") == 0 ){
|
||||
eventType = xpp.next();
|
||||
if(eventType == XmlPullParser.TEXT) {
|
||||
if( account != null ){
|
||||
account.setAcct(xpp.getText().replace("@","")+"@" + nitterHost);
|
||||
account.setDisplay_name(xpp.getText().replace("@",""));
|
||||
account.setUsername(xpp.getText().replace("@",""));
|
||||
account.setId("https://" + nitterHost + "/" + xpp.getText());
|
||||
account.setUuid("https://" + nitterHost + "/" + xpp.getText());
|
||||
account.setUrl("https://" + nitterHost + "/" + xpp.getText());
|
||||
if( !mappedProfile.containsKey(xpp.getText()) ){
|
||||
HttpsConnection httpsConnection = new HttpsConnection(context, nitterHost);
|
||||
try {
|
||||
String response = httpsConnection.get("https://" + nitterHost + "/" + xpp.getText() + "/rss", 10, null, null);
|
||||
XmlPullParserFactory factory2 = XmlPullParserFactory.newInstance();
|
||||
factory2.setNamespaceAware(true);
|
||||
XmlPullParser xpp2 = factory2.newPullParser();
|
||||
|
||||
xpp2.setInput( new StringReader( response ) );
|
||||
int eventType2 = xpp2.getEventType();
|
||||
while (eventType2 != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventType2 == XmlPullParser.START_TAG) {
|
||||
if (xpp2.getName().compareTo("url") == 0) {
|
||||
eventType2 = xpp2.next();
|
||||
if(eventType2 == XmlPullParser.TEXT ) {
|
||||
mappedProfile.put(xpp.getText(), xpp2.getText());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
eventType2 = xpp2.next();
|
||||
}
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException | HttpsConnection.HttpsConnectionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
account.setAvatar(mappedProfile.get(xpp.getText()));
|
||||
}
|
||||
}
|
||||
} else if( xpp.getName().compareTo("pubDate") == 0 ){
|
||||
eventType = xpp.next();
|
||||
if(eventType == XmlPullParser.TEXT && status != null) {
|
||||
if( xpp.getText() != null ) {
|
||||
try {
|
||||
DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
|
||||
Date date = formatter.parse(xpp.getText());
|
||||
status.setCreated_at(date);
|
||||
} catch (ParseException e) {
|
||||
status.setCreated_at(new Date());
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if( xpp.getName().compareTo("description") == 0 ){
|
||||
eventType = xpp.next();
|
||||
if(eventType == XmlPullParser.TEXT && status != null) {
|
||||
if( xpp.getText() != null ) {
|
||||
String description = xpp.getText();
|
||||
Pattern imgPattern = Pattern.compile("<img [^>]*src=\"([^\"]+)\"[^>]*>");
|
||||
Matcher matcher = imgPattern.matcher(description);
|
||||
List<String> imgs = new ArrayList<>();
|
||||
int i = 1;
|
||||
ArrayList<Attachment> attachments = new ArrayList<>();
|
||||
while (matcher.find()) {
|
||||
description = description.replaceAll(Pattern.quote(matcher.group()), "");
|
||||
imgs.add("[media_" + i + "]|" + matcher.group(1));
|
||||
Attachment attachment = new Attachment();
|
||||
attachment.setType("image");
|
||||
attachment.setDescription("");
|
||||
attachment.setUrl(matcher.group(1));
|
||||
attachment.setPreview_url(matcher.group(1));
|
||||
attachment.setId(matcher.group(1));
|
||||
attachments.add(attachment);
|
||||
}
|
||||
status.setMedia_attachments(attachments);
|
||||
status.setContent(context, description);
|
||||
}
|
||||
}
|
||||
}else if( xpp.getName().compareTo("guid") == 0 ){
|
||||
eventType = xpp.next();
|
||||
if(eventType == XmlPullParser.TEXT && status != null) {
|
||||
if( xpp.getText() != null ) {
|
||||
status.setUri(xpp.getText());
|
||||
Pattern idPattern = Pattern.compile("([0-9])+");
|
||||
Matcher matcher = idPattern.matcher(xpp.getText());
|
||||
while (matcher.find()) {
|
||||
status.setId(matcher.group(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if( xpp.getName().compareTo("link") == 0 ){
|
||||
eventType = xpp.next();
|
||||
if(eventType == XmlPullParser.TEXT && status != null) {
|
||||
if( xpp.getText() != null ) {
|
||||
status.setUrl(xpp.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(eventType == XmlPullParser.END_TAG) {
|
||||
if( xpp.getName().compareTo("item") == 0 ){
|
||||
if (status != null) {
|
||||
status.setAccount(account);
|
||||
statuses.add(status);
|
||||
}
|
||||
account = null;
|
||||
status = null;
|
||||
}
|
||||
}
|
||||
eventType = xpp.next();
|
||||
}
|
||||
} catch (XmlPullParserException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return statuses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse json response for several notes (Misskey)
|
||||
*
|
||||
|
@ -3237,8 +3399,51 @@ public class API {
|
|||
return apiResponse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves Peertube videos from an instance *synchronously*
|
||||
* Retrieves Nitter timeline from accounts *synchronously*
|
||||
*
|
||||
* @return APIResponse
|
||||
*/
|
||||
public APIResponse getNitter(String instance, String max_id) {
|
||||
|
||||
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
String nitterHost = sharedpreferences.getString(Helper.SET_NITTER_HOST, Helper.DEFAULT_NITTER_HOST).toLowerCase();
|
||||
String[] usernames = instance.split(" ");
|
||||
if( usernames.length == 0 ){
|
||||
Error error = new Error();
|
||||
error.setError(context.getString(R.string.toast_error));
|
||||
error.setStatusCode(404);
|
||||
apiResponse.setError(error);
|
||||
return apiResponse;
|
||||
}
|
||||
StringBuilder urlparams = new StringBuilder();
|
||||
for(String param: usernames){
|
||||
urlparams.append(param.trim()).append(",");
|
||||
}
|
||||
|
||||
String url = "https://" + nitterHost + "/" + urlparams + "/rss";
|
||||
if( max_id != null ){
|
||||
url += "?max_position=" + max_id;
|
||||
}
|
||||
try {
|
||||
statuses = new ArrayList<>();
|
||||
HttpsConnection httpsConnection = new HttpsConnection(context, this.instance);
|
||||
String response = httpsConnection.get(url, 30, null, null);
|
||||
apiResponse.setMax_id(httpsConnection.getMax_id());
|
||||
statuses = parseNitter(response);
|
||||
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
setError(e.getStatusCode(), e);
|
||||
} catch (NoSuchAlgorithmException | IOException | KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
apiResponse.setStatuses(statuses);
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves Misskey timeline from an instance *synchronously*
|
||||
*
|
||||
* @return APIResponse
|
||||
*/
|
||||
|
|
|
@ -474,18 +474,20 @@ public class Status implements Parcelable {
|
|||
account.setInstance(instance);
|
||||
account.setUrl(url);
|
||||
String accountId = null;
|
||||
for (Mention mention : mentions) {
|
||||
String[] accountMentionAcct = mention.getAcct().split("@");
|
||||
//Different isntance
|
||||
if (accountMentionAcct.length > 1) {
|
||||
if (mention.getAcct().equals(account.getAcct() + "@" + account.getInstance())) {
|
||||
accountId = mention.getId();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (mention.getAcct().equals(account.getAcct())) {
|
||||
accountId = mention.getId();
|
||||
break;
|
||||
if( mentions != null) {
|
||||
for (Mention mention : mentions) {
|
||||
String[] accountMentionAcct = mention.getAcct().split("@");
|
||||
//Different isntance
|
||||
if (accountMentionAcct.length > 1) {
|
||||
if (mention.getAcct().equals(account.getAcct() + "@" + account.getInstance())) {
|
||||
accountId = mention.getId();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (mention.getAcct().equals(account.getAcct())) {
|
||||
accountId = mention.getId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,13 +170,18 @@ public class HttpsConnection {
|
|||
}
|
||||
}
|
||||
StringBuilder postData = new StringBuilder();
|
||||
for (Map.Entry<String, Object> param : params.entrySet()) {
|
||||
if (postData.length() != 0) postData.append('&');
|
||||
postData.append(param.getKey());
|
||||
postData.append('=');
|
||||
postData.append(param.getValue());
|
||||
URL url;
|
||||
if( params.size() > 0 ) {
|
||||
for (Map.Entry<String, Object> param : params.entrySet()) {
|
||||
if (postData.length() != 0) postData.append('&');
|
||||
postData.append(param.getKey());
|
||||
postData.append('=');
|
||||
postData.append(param.getValue());
|
||||
}
|
||||
url = new URL(urlConnection + "?" + postData);
|
||||
}else{
|
||||
url = new URL(urlConnection);
|
||||
}
|
||||
URL url = new URL(urlConnection + "?" + postData);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(timeout, TimeUnit.SECONDS).cache(new Cache(context.getCacheDir(), cacheSize));
|
||||
|
@ -331,6 +336,7 @@ public class HttpsConnection {
|
|||
throw new HttpsConnectionException(code, error);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
URL url = new URL(urlConnection);
|
||||
if (proxy != null)
|
||||
|
@ -1443,6 +1449,12 @@ public class HttpsConnection {
|
|||
}
|
||||
|
||||
}
|
||||
}else if (entry.toString().startsWith("Min-Id") || entry.toString().startsWith("min-id")) {
|
||||
Pattern patternMaxId = Pattern.compile("min-id=\\[([0-9a-zA-Z]{1,}).*\\]");
|
||||
Matcher matcherMaxId = patternMaxId.matcher(entry.toString());
|
||||
if (matcherMaxId.find()) {
|
||||
max_id = matcherMaxId.group(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1454,6 +1466,7 @@ public class HttpsConnection {
|
|||
if (httpsURLConnection == null)
|
||||
return;
|
||||
Map<String, List<String>> map = httpsURLConnection.getHeaderFields();
|
||||
|
||||
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
|
||||
if (entry.toString().startsWith("Link") || entry.toString().startsWith("link")) {
|
||||
Pattern patternMaxId = Pattern.compile("max_id=([0-9a-zA-Z]{1,}).*");
|
||||
|
@ -1469,6 +1482,12 @@ public class HttpsConnection {
|
|||
}
|
||||
|
||||
}
|
||||
}else if (entry.toString().startsWith("Min-Id") || entry.toString().startsWith("min-id")) {
|
||||
Pattern patternMaxId = Pattern.compile("min-id=\\[([0-9a-zA-Z]{1,}).*\\]");
|
||||
Matcher matcherMaxId = patternMaxId.matcher(entry.toString());
|
||||
if (matcherMaxId.find()) {
|
||||
max_id = matcherMaxId.group(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -129,6 +129,9 @@ public class ReorderTabAdapter extends RecyclerView.Adapter<ReorderTabAdapter.It
|
|||
case "GNU":
|
||||
holder.iconView.setImageResource(R.drawable.ic_gnu_social);
|
||||
break;
|
||||
case "NITTER":
|
||||
holder.iconView.setImageResource(R.drawable.nitter);
|
||||
break;
|
||||
}
|
||||
holder.textView.setText(tl.getRemoteInstance().getHost());
|
||||
break;
|
||||
|
|
|
@ -227,6 +227,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
private List<ViewHolder> lstHolders;
|
||||
private List<Emojis> emojisPicker;
|
||||
private Status statusForQuickReply;
|
||||
private String instanceType;
|
||||
|
||||
private Runnable updateAnimatedEmoji = new Runnable() {
|
||||
@Override
|
||||
|
@ -266,6 +267,21 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
currentToId = -1;
|
||||
}
|
||||
|
||||
public StatusListAdapter(String instanceType, RetrieveFeedsAsyncTask.Type type, String targetedId, boolean isOnWifi, List<Status> statuses) {
|
||||
super();
|
||||
this.statuses = statuses;
|
||||
this.isOnWifi = isOnWifi;
|
||||
statusListAdapter = this;
|
||||
this.type = type;
|
||||
this.targetedId = targetedId;
|
||||
redraft = false;
|
||||
lstHolders = new ArrayList<>();
|
||||
toot_content = null;
|
||||
toot_cw_content = null;
|
||||
tootReply = null;
|
||||
currentToId = -1;
|
||||
this.instanceType = instanceType;
|
||||
}
|
||||
|
||||
public StatusListAdapter(TagTimeline tagTimeline, String targetedId, boolean isOnWifi, List<Status> statuses) {
|
||||
super();
|
||||
|
@ -283,6 +299,23 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
currentToId = -1;
|
||||
}
|
||||
|
||||
public StatusListAdapter(String instanceType, TagTimeline tagTimeline, String targetedId, boolean isOnWifi, List<Status> statuses) {
|
||||
super();
|
||||
this.statuses = statuses;
|
||||
this.isOnWifi = isOnWifi;
|
||||
statusListAdapter = this;
|
||||
this.type = RetrieveFeedsAsyncTask.Type.TAG;
|
||||
this.targetedId = targetedId;
|
||||
redraft = false;
|
||||
this.tagTimeline = tagTimeline;
|
||||
this.instanceType = instanceType;
|
||||
lstHolders = new ArrayList<>();
|
||||
toot_content = null;
|
||||
toot_cw_content = null;
|
||||
tootReply = null;
|
||||
currentToId = -1;
|
||||
}
|
||||
|
||||
public StatusListAdapter(int position, String targetedId, boolean isOnWifi, List<Status> statuses) {
|
||||
this.statuses = statuses;
|
||||
this.isOnWifi = isOnWifi;
|
||||
|
@ -616,15 +649,20 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
show_boosts = ((ShowAccountActivity) context).showBoosts();
|
||||
show_replies = ((ShowAccountActivity) context).showReplies();
|
||||
}
|
||||
if (type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && type != RetrieveFeedsAsyncTask.Type.NEWS && !Helper.filterToots(statuses.get(position), type, context instanceof ShowAccountActivity, show_boosts, show_replies))
|
||||
if (type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && type != RetrieveFeedsAsyncTask.Type.NEWS && !Helper.filterToots(statuses.get(position), type, context instanceof ShowAccountActivity, show_boosts, show_replies)) {
|
||||
return HIDDEN_STATUS;
|
||||
}
|
||||
if (statuses.get(position).isFocused() && type == RetrieveFeedsAsyncTask.Type.CONTEXT && statuses.get(position).getViewType() != CONSOLE_STATUS)
|
||||
return FOCUSED_STATUS;
|
||||
else {
|
||||
if (social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED && type == RetrieveFeedsAsyncTask.Type.CONTEXT) {
|
||||
return COMPACT_STATUS;
|
||||
} else {
|
||||
return statuses.get(position).getViewType();
|
||||
if( instanceType == null || instanceType.compareTo("NITTER") != 0 ) {
|
||||
return statuses.get(position).getViewType();
|
||||
}else{
|
||||
return COMPACT_STATUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -653,6 +691,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
|
||||
final String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||
context = viewHolder.itemView.getContext();
|
||||
|
||||
if (viewHolder.getItemViewType() != HIDDEN_STATUS) {
|
||||
final ViewHolder holder = (ViewHolder) viewHolder;
|
||||
synchronized (lock) {
|
||||
|
@ -662,9 +701,10 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
|
||||
holder.startUpdateTimer();
|
||||
final Status status = statuses.get(i);
|
||||
|
||||
|
||||
if (status == null)
|
||||
return;
|
||||
|
||||
//TODO:It sounds that sometimes this value is null - need deeper investigation
|
||||
if (status.getVisibility() == null) {
|
||||
status.setVisibility("public");
|
||||
|
@ -1301,6 +1341,38 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
status.setImageFound(true);
|
||||
Status.makeImage(context, this, status);
|
||||
}
|
||||
if (instanceType != null && instanceType.compareTo("NITTER") == 0) {
|
||||
holder.status_action_container.setVisibility(View.GONE);
|
||||
if( holder.status_action_container_twitter != null){
|
||||
holder.status_action_container_twitter.setVisibility(View.VISIBLE);
|
||||
holder.status_action_container_twitter.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
|
||||
String url = status.getUrl();
|
||||
String extra_text;
|
||||
|
||||
extra_text = (status.getReblog() != null) ? status.getReblog().getAccount().getAcct() : status.getAccount().getAcct();
|
||||
if (extra_text.split("@").length == 1)
|
||||
extra_text = "@" + extra_text + "@" + Helper.getLiveInstance(context);
|
||||
else
|
||||
extra_text = "@" + extra_text;
|
||||
extra_text += " " + Helper.shortnameToUnicode(":link:", true) + " " + url + "\r\n-\n";
|
||||
final String contentToot;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||
contentToot = Html.fromHtml((status.getReblog() != null) ? status.getReblog().getContent() : status.getContent(), Html.FROM_HTML_MODE_LEGACY).toString();
|
||||
else
|
||||
//noinspection deprecation
|
||||
contentToot = Html.fromHtml((status.getReblog() != null) ? status.getReblog().getContent() : status.getContent()).toString();
|
||||
extra_text += contentToot;
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, extra_text);
|
||||
sendIntent.setType("text/plain");
|
||||
context.startActivity(Intent.createChooser(sendIntent, context.getString(R.string.share_with)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
holder.status_content.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
|
@ -1328,7 +1400,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
});
|
||||
//Click on a conversation
|
||||
|
||||
if ((getItemViewType(viewHolder.getAdapterPosition()) == DISPLAYED_STATUS || getItemViewType(viewHolder.getAdapterPosition()) == COMPACT_STATUS || getItemViewType(viewHolder.getAdapterPosition()) == CONSOLE_STATUS)) {
|
||||
if (( instanceType == null || instanceType.compareTo("NITTER") != 0) && (getItemViewType(viewHolder.getAdapterPosition()) == DISPLAYED_STATUS || getItemViewType(viewHolder.getAdapterPosition()) == COMPACT_STATUS || getItemViewType(viewHolder.getAdapterPosition()) == CONSOLE_STATUS)) {
|
||||
|
||||
holder.status_spoiler.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -3152,7 +3224,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
} else if( instanceType == null || instanceType.compareTo("NITTER") != 0){
|
||||
holder.status_account_profile.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -3225,6 +3297,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void loadAttachments(final Status status, final ViewHolder holder, boolean blur) {
|
||||
|
@ -4220,6 +4293,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
ConstraintLayout main_container;
|
||||
TextView yandex_translate;
|
||||
ConstraintLayout status_action_container;
|
||||
ConstraintLayout status_action_container_twitter;
|
||||
Button fetch_more;
|
||||
ImageView new_element;
|
||||
LinearLayout status_spoiler_mention_container;
|
||||
|
@ -4325,6 +4399,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
yandex_translate = itemView.findViewById(R.id.yandex_translate);
|
||||
new_element = itemView.findViewById(R.id.new_element);
|
||||
status_action_container = itemView.findViewById(R.id.status_action_container);
|
||||
status_action_container_twitter = itemView.findViewById(R.id.status_action_container_twitter);
|
||||
status_spoiler_mention_container = itemView.findViewById(R.id.status_spoiler_mention_container);
|
||||
status_mention_spoiler = itemView.findViewById(R.id.status_mention_spoiler);
|
||||
status_cardview = itemView.findViewById(R.id.status_cardview);
|
||||
|
|
|
@ -206,7 +206,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
lastReadToot = sharedpreferences.getString(Helper.LAST_READ_TOOT_ID + userId + instance, null);
|
||||
lastReadTootDate = Helper.stringToDate(context, sharedpreferences.getString(Helper.LAST_READ_TOOT_DATE + userId + instance, null));
|
||||
}
|
||||
if (instanceType == null || instanceType.equals("MASTODON") || instanceType.equals("MISSKEY") || instanceType.equals("GNU")) {
|
||||
if (instanceType == null || instanceType.equals("MASTODON") || instanceType.equals("MISSKEY") || instanceType.equals("GNU") || instanceType.equals("NITTER")) {
|
||||
if (type == RetrieveFeedsAsyncTask.Type.TAG && tag != null) {
|
||||
BaseMainActivity.displayPeertube = null;
|
||||
List<TagTimeline> tagTimelines = new SearchDAO(context, db).getTimelineInfo(tag);
|
||||
|
@ -217,7 +217,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
}
|
||||
} else {
|
||||
BaseMainActivity.displayPeertube = null;
|
||||
statusListAdapter = new StatusListAdapter(type, targetedId, isOnWifi, this.statuses);
|
||||
statusListAdapter = new StatusListAdapter(instanceType, type, targetedId, isOnWifi, this.statuses);
|
||||
lv_status.setAdapter(statusListAdapter);
|
||||
}
|
||||
} else if (instanceType.equals("PEERTUBE")) {
|
||||
|
@ -580,7 +580,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
}
|
||||
//Let's deal with statuses
|
||||
if (statuses != null && statuses.size() > 0) {
|
||||
if (statusListAdapter != null && (instanceType.equals("MASTODON") || instanceType.equals("MISSKEY") || instanceType.equals("GNU"))) {
|
||||
if (statusListAdapter != null && (instanceType.equals("MASTODON") || instanceType.equals("NITTER") || instanceType.equals("MISSKEY") || instanceType.equals("GNU"))) {
|
||||
this.statuses.addAll(statuses);
|
||||
statusListAdapter.notifyItemRangeInserted(previousPosition, statuses.size());
|
||||
} else if (artListAdapter != null && instanceType.equals("ART")) {
|
||||
|
@ -863,6 +863,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
switch (instanceType) {
|
||||
case "MASTODON":
|
||||
case "MISSKEY":
|
||||
case "NITTER":
|
||||
case "GNU":
|
||||
statusListAdapter.notifyItemRangeChanged(0, this.statuses.size());
|
||||
break;
|
||||
|
@ -892,7 +893,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
Status status = it.next();
|
||||
for (Status status1 : statuses) {
|
||||
if (status.getConversationId() != null && status.getConversationId().equals(status1.getConversationId())) {
|
||||
if (instanceType.equals("MASTODON") || instanceType.equals("MISSKEY") || instanceType.equals("GNU"))
|
||||
if (instanceType.equals("MASTODON") || instanceType.equals("MISSKEY") || instanceType.equals("NITTER")|| instanceType.equals("GNU"))
|
||||
statusListAdapter.notifyItemRemoved(position);
|
||||
else if (instanceType.equals("PIXELFED"))
|
||||
pixelfedListAdapter.notifyItemRemoved(position);
|
||||
|
@ -931,7 +932,8 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
}
|
||||
}
|
||||
}
|
||||
if (statusListAdapter != null && (instanceType.equals("MASTODON") || instanceType.equals("MISSKEY") || instanceType.equals("GNU")))
|
||||
|
||||
if (statusListAdapter != null && (instanceType.equals("MASTODON") || instanceType.equals("MISSKEY") || instanceType.equals("NITTER") || instanceType.equals("GNU")))
|
||||
statusListAdapter.notifyItemRangeInserted(0, inserted);
|
||||
else if (pixelfedListAdapter != null && instanceType.equals("PIXELFED"))
|
||||
pixelfedListAdapter.notifyItemRangeInserted(0, inserted);
|
||||
|
@ -1158,6 +1160,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
switch (instanceType) {
|
||||
case "MASTODON":
|
||||
case "MISSKEY":
|
||||
case "NITTER":
|
||||
case "GNU":
|
||||
statusListAdapter.notifyItemRangeRemoved(0, lenght);
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<vector android:height="24dp" android:viewportHeight="500"
|
||||
android:viewportWidth="500" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#f00" android:pathData="M73.6,33.6L71,36.3v427.4l2.6,2.7 2.7,2.6h87.4l2.7,-2.6 2.6,-2.7L169,339.9c0,-102.6 0.2,-123.9 1.3,-123.9 0.8,0 41.1,56.1 89.7,124.7 48.5,68.7 89.2,125.6 90.4,126.5 1.9,1.6 5.5,1.8 37.7,1.8h35.6l2.7,-2.6 2.6,-2.7L429,36.3l-2.6,-2.7 -2.7,-2.6h-87.4l-2.7,2.6 -2.6,2.7v123.8c0,102.6 -0.2,123.9 -1.3,123.9 -0.8,0 -41.1,-56.1 -89.7,-124.8 -48.5,-68.6 -89.2,-125.5 -90.4,-126.4 -1.9,-1.6 -5.5,-1.8 -37.7,-1.8L76.3,31l-2.7,2.6zM232.5,180.7c51.2,72.3 94.4,133.1 96.1,134.9 2.9,3.1 3.6,3.4 9.1,3.4 5.2,0 6.4,-0.4 8.7,-2.6l2.6,-2.7L349,49h62v402l-25.2,-0.1h-25.3l-93,-131.6c-51.1,-72.3 -94.4,-133.1 -96.1,-134.9 -2.9,-3.1 -3.6,-3.4 -9.1,-3.4 -5.2,0 -6.4,0.4 -8.7,2.6l-2.6,2.7L151,451L89,451L89,49l25.3,0.1h25.2l93,131.6z"/>
|
||||
</vector>
|
|
@ -842,6 +842,24 @@
|
|||
android:textStyle="italic"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/status_action_container_twitter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
<ImageView
|
||||
android:id="@+id/status_share"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/ic_share_peertube"
|
||||
android:tint="?attr/iconColor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/status_action_container"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -48,5 +48,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gnu_instance" />
|
||||
<RadioButton
|
||||
android:id="@+id/twitter_accounts"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/twitter_accounts" />
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
|
@ -1205,4 +1205,6 @@
|
|||
<string name="action_trends">Trends</string>
|
||||
<string name="trending_now">Trending now</string>
|
||||
<string name="talking_about">%d people talking</string>
|
||||
<string name="twitter_accounts">Twitter accounts</string>
|
||||
<string name="list_of_twitter_accounts">Twitter usernames space separated</string>
|
||||
</resources>
|
Loading…
Reference in New Issue