Merge branch 'develop'

This commit is contained in:
Thomas 2020-07-08 13:54:17 +02:00
commit 89899557df
99 changed files with 2904 additions and 1695 deletions

View File

@ -6,8 +6,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 29 targetSdkVersion 29
versionCode 372 versionCode 374
versionName "2.35.8" versionName "2.36.0"
multiDexEnabled true multiDexEnabled true
renderscriptTargetApi 28 as int renderscriptTargetApi 28 as int
renderscriptSupportModeEnabled true renderscriptSupportModeEnabled true
@ -117,6 +117,7 @@ dependencies {
implementation "info.guardianproject.netcipher:netcipher:2.0.0-alpha1" implementation "info.guardianproject.netcipher:netcipher:2.0.0-alpha1"
implementation "info.guardianproject.netcipher:netcipher-okhttp3:2.0.0-alpha1" implementation "info.guardianproject.netcipher:netcipher-okhttp3:2.0.0-alpha1"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.github.adrielcafe:AndroidAudioRecorder:0.3.0' implementation 'com.github.adrielcafe:AndroidAudioRecorder:0.3.0'
implementation 'yogesh.firzen:MukkiyaSevaigal:1.0.6' implementation 'yogesh.firzen:MukkiyaSevaigal:1.0.6'
implementation 'com.iceteck.silicompressorr:silicompressor:2.2.2' implementation 'com.iceteck.silicompressorr:silicompressor:2.2.2'

View File

@ -69,6 +69,11 @@
android:name="app.fedilab.android.services.BackupNotificationInDataBaseService" android:name="app.fedilab.android.services.BackupNotificationInDataBaseService"
android:exported="false" /> android:exported="false" />
<receiver android:name=".services.UpgradeReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
<receiver <receiver
android:name="app.fedilab.android.services.RestartLiveNotificationReceiver" android:name="app.fedilab.android.services.RestartLiveNotificationReceiver"
android:exported="false"> android:exported="false">
@ -527,5 +532,6 @@
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /> android:resource="@xml/file_paths" />
</provider> </provider>
</application> </application>
</manifest> </manifest>

View File

@ -0,0 +1,18 @@
Added:
- Select text for media description
changed:
- Increase media description length to 1500 chars
- More details about accounts in notifications
- Media management in timelines
- Allow cross-account replies on followed instances
Fixed:
- Remove extra spaces at the bottom of messages
- Some issue with custom emoji
- Fix issue with "Your toots/notifications"
- Fix issue with CW and Pixelfed
- Fix some media not loaded in profiles
- Scheduled toots from server side have an incorrect date
- Incorrect feeds when checking instance admin account
- Some crashes

View File

@ -0,0 +1,19 @@
Added:
- Select text for media description
changed:
- Increase media description length to 1500 chars
- More details about accounts in notifications
- Media management in timelines
- Allow cross-account replies on followed instances
Fixed:
- Crash when adding media
- Remove extra spaces at the bottom of messages
- Some issue with custom emoji
- Fix issue with "Your toots/notifications"
- Fix issue with CW and Pixelfed
- Fix some media not loaded in profiles
- Scheduled toots from server side have an incorrect date
- Incorrect feeds when checking instance admin account
- Some crashes

View File

@ -5,9 +5,11 @@ import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.ActionMode; import android.view.ActionMode;
import android.view.View; import android.view.View;
import android.view.Window;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -67,6 +69,9 @@ public class BaseActivity extends CyaneaAppCompatActivity {
.build()); .build());
}*/ }*/
canShowActionMode = true; canShowActionMode = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
}
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }

View File

@ -986,8 +986,8 @@ public abstract class BaseMainActivity extends BaseActivity
SeekBar set_icon_size = popup_quick_settings.findViewById(R.id.set_icon_size); SeekBar set_icon_size = popup_quick_settings.findViewById(R.id.set_icon_size);
final TextView set_text_size_value = popup_quick_settings.findViewById(R.id.set_text_size_value); final TextView set_text_size_value = popup_quick_settings.findViewById(R.id.set_text_size_value);
final TextView set_icon_size_value = popup_quick_settings.findViewById(R.id.set_icon_size_value); final TextView set_icon_size_value = popup_quick_settings.findViewById(R.id.set_icon_size_value);
set_text_size_value.setText(String.format("%s%%", String.valueOf(textSize))); set_text_size_value.setText(String.format("%s%%", textSize));
set_icon_size_value.setText(String.format("%s%%", String.valueOf(iconSize))); set_icon_size_value.setText(String.format("%s%%", iconSize));
set_text_size.setMax(20); set_text_size.setMax(20);
set_icon_size.setMax(20); set_icon_size.setMax(20);
@ -1008,7 +1008,7 @@ public abstract class BaseMainActivity extends BaseActivity
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int value = 80 + progress * 5; int value = 80 + progress * 5;
set_text_size_value.setText(String.format("%s%%", String.valueOf(value))); set_text_size_value.setText(String.format("%s%%", value));
SharedPreferences.Editor editor = sharedpreferences1.edit(); SharedPreferences.Editor editor = sharedpreferences1.edit();
editor.putInt(Helper.SET_TEXT_SIZE, value); editor.putInt(Helper.SET_TEXT_SIZE, value);
editor.apply(); editor.apply();
@ -1026,7 +1026,7 @@ public abstract class BaseMainActivity extends BaseActivity
@Override @Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int value = 80 + progress * 5; int value = 80 + progress * 5;
set_icon_size_value.setText(String.format("%s%%", String.valueOf(value))); set_icon_size_value.setText(String.format("%s%%", value));
SharedPreferences.Editor editor = sharedpreferences1.edit(); SharedPreferences.Editor editor = sharedpreferences1.edit();
editor.putInt(Helper.SET_ICON_SIZE, value); editor.putInt(Helper.SET_ICON_SIZE, value);
editor.apply(); editor.apply();
@ -1503,9 +1503,9 @@ public abstract class BaseMainActivity extends BaseActivity
} }
} else if (type.startsWith("image/") || type.startsWith("video/")) { } else if (type.startsWith("image/") || type.startsWith("video/")) {
Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (!TootActivity.active) { if (!TootActivity.active) {
Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) { if (imageUri != null) {
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putParcelable("sharedUri", imageUri); b.putParcelable("sharedUri", imageUri);
@ -1513,7 +1513,6 @@ public abstract class BaseMainActivity extends BaseActivity
CrossActions.doCrossShare(BaseMainActivity.this, b); CrossActions.doCrossShare(BaseMainActivity.this, b);
} }
} else { } else {
Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) { if (imageUri != null) {
intent = new Intent(BaseMainActivity.this, TootActivity.class); intent = new Intent(BaseMainActivity.this, TootActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
@ -2381,7 +2380,13 @@ public abstract class BaseMainActivity extends BaseActivity
} }
} }
final NavigationView navigationView = findViewById(R.id.nav_view); final NavigationView navigationView = findViewById(R.id.nav_view);
if (navigationView == null) {
return;
}
MenuItem item = navigationView.getMenu().findItem(R.id.nav_announcements); MenuItem item = navigationView.getMenu().findItem(R.id.nav_announcements);
if (item == null || item.getActionView() == null) {
return;
}
TextView actionView = item.getActionView().findViewById(R.id.counter); TextView actionView = item.getActionView().findViewById(R.id.counter);
if (actionView != null) { if (actionView != null) {
if (unread > 0) { if (unread > 0) {

View File

@ -122,7 +122,7 @@ public class InstanceProfileActivity extends BaseActivity {
finish(); finish();
return; return;
} }
if (instanceNodeInfo.getThumbnail() != null && !instanceNodeInfo.getThumbnail().equals("null")) if (instanceNodeInfo.getThumbnail() != null && !instanceNodeInfo.getThumbnail().equals("null") && Helper.isValidContextForGlide(InstanceProfileActivity.this))
Glide.with(InstanceProfileActivity.this) Glide.with(InstanceProfileActivity.this)
.asBitmap() .asBitmap()
.load(instanceNodeInfo.getThumbnail()) .load(instanceNodeInfo.getThumbnail())
@ -149,7 +149,7 @@ public class InstanceProfileActivity extends BaseActivity {
accounts.add(instanceNodeInfo.getStaffAccount()); accounts.add(instanceNodeInfo.getStaffAccount());
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
AccountsListAdapter accountsListAdapter = new AccountsListAdapter(RetrieveAccountsAsyncTask.Type.FOLLOWERS, userId, accounts); AccountsListAdapter accountsListAdapter = new AccountsListAdapter(RetrieveAccountsAsyncTask.Type.FOLLOWERS, userId, true, accounts);
lv_accounts.setAdapter(accountsListAdapter); lv_accounts.setAdapter(accountsListAdapter);
final LinearLayoutManager mLayoutManager; final LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(InstanceProfileActivity.this); mLayoutManager = new LinearLayoutManager(InstanceProfileActivity.this);

View File

@ -175,7 +175,7 @@ public class OwnerChartsActivity extends BaseActivity implements OnRetrieveChart
dateEnd = new StatusCacheDAO(OwnerChartsActivity.this, db).getGreaterDate(StatusCacheDAO.ARCHIVE_CACHE); dateEnd = new StatusCacheDAO(OwnerChartsActivity.this, db).getGreaterDate(StatusCacheDAO.ARCHIVE_CACHE);
if( dateIni == null){ if (dateIni == null) {
dateIni = new Date(); dateIni = new Date();
dateEnd = new Date(); dateEnd = new Date();
} }
@ -417,7 +417,7 @@ public class OwnerChartsActivity extends BaseActivity implements OnRetrieveChart
@Override @Override
public MPPointF getOffset() { public MPPointF getOffset() {
if (mOffset == null) { if (mOffset == null) {
mOffset = new MPPointF(-((float)getWidth() / 2), -getHeight()); mOffset = new MPPointF(-((float) getWidth() / 2), -getHeight());
} }
return mOffset; return mOffset;
} }

View File

@ -15,6 +15,7 @@
package app.fedilab.android.activities; package app.fedilab.android.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -260,27 +261,26 @@ public class OwnerNotificationChartsActivity extends BaseActivity implements OnR
List<Entry> boostsEntry = new ArrayList<>(); List<Entry> boostsEntry = new ArrayList<>();
Iterator<Map.Entry<Long, Integer>> it = charts.getReblogs().entrySet().iterator();
Iterator it = charts.getReblogs().entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Long, Integer> pair = it.next();
boostsEntry.add(new Entry((long) pair.getKey(), (int) pair.getValue())); boostsEntry.add(new Entry(pair.getKey(), pair.getValue()));
it.remove(); it.remove();
} }
List<Entry> favEntry = new ArrayList<>(); List<Entry> favEntry = new ArrayList<>();
it = charts.getFavourites().entrySet().iterator(); it = charts.getFavourites().entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Long, Integer> pair = it.next();
favEntry.add(new Entry((long) pair.getKey(), (int) pair.getValue())); favEntry.add(new Entry(pair.getKey(), pair.getValue()));
it.remove(); it.remove();
} }
List<Entry> mentionEntry = new ArrayList<>(); List<Entry> mentionEntry = new ArrayList<>();
it = charts.getMentions().entrySet().iterator(); it = charts.getMentions().entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Long, Integer> pair = it.next();
mentionEntry.add(new Entry((long) pair.getKey(), (int) pair.getValue())); mentionEntry.add(new Entry(pair.getKey(), pair.getValue()));
it.remove(); it.remove();
} }
@ -288,8 +288,8 @@ public class OwnerNotificationChartsActivity extends BaseActivity implements OnR
List<Entry> followEntry = new ArrayList<>(); List<Entry> followEntry = new ArrayList<>();
it = charts.getFollows().entrySet().iterator(); it = charts.getFollows().entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Long, Integer> pair = it.next();
followEntry.add(new Entry((long) pair.getKey(), (int) pair.getValue())); followEntry.add(new Entry(pair.getKey(), pair.getValue()));
it.remove(); it.remove();
} }
@ -482,6 +482,7 @@ public class OwnerNotificationChartsActivity extends BaseActivity implements OnR
super.onDestroy(); super.onDestroy();
} }
@SuppressLint("ViewConstructor")
public static class CustomMarkerView extends MarkerView { public static class CustomMarkerView extends MarkerView {
private TextView tvContent; private TextView tvContent;
private MPPointF mOffset; private MPPointF mOffset;
@ -503,7 +504,7 @@ public class OwnerNotificationChartsActivity extends BaseActivity implements OnR
@Override @Override
public MPPointF getOffset() { public MPPointF getOffset() {
if (mOffset == null) { if (mOffset == null) {
mOffset = new MPPointF(-(getWidth() / 2), -getHeight()); mOffset = new MPPointF(-((float) getWidth() / 2), -getHeight());
} }
return mOffset; return mOffset;
} }

View File

@ -522,11 +522,11 @@ public class OwnerStatusActivity extends BaseActivity implements OnRetrieveFeeds
frequency.setText(getString(R.string.toot_per_day, df.format(statistics.getFrequency()))); frequency.setText(getString(R.string.toot_per_day, df.format(statistics.getFrequency())));
if (statistics.getTagsTrend() != null && statistics.getTagsTrend().size() > 0) { if (statistics.getTagsTrend() != null && statistics.getTagsTrend().size() > 0) {
Iterator it = statistics.getTagsTrend().entrySet().iterator(); Iterator<Map.Entry<String, Integer>> it = statistics.getTagsTrend().entrySet().iterator();
StringBuilder text = new StringBuilder(); StringBuilder text = new StringBuilder();
int i = 1; int i = 1;
while (it.hasNext() && i <= 10) { while (it.hasNext() && i <= 10) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, Integer> pair = it.next();
System.out.println(pair.getKey() + " = " + pair.getValue()); System.out.println(pair.getKey() + " = " + pair.getValue());
text.append(i).append(" - ").append(pair.getKey()).append("").append(pair.getValue()).append("\r\n"); text.append(i).append(" - ").append(pair.getKey()).append("").append(pair.getValue()).append("\r\n");
i++; i++;

View File

@ -639,26 +639,18 @@ public class PeertubeActivity extends BaseActivity implements OnRetrievePeertube
@Override @Override
public void onConfigurationChanged(@NotNull Configuration newConfig) { public void onConfigurationChanged(@NotNull Configuration newConfig) {
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (mode != Helper.VIDEO_MODE_WEBVIEW) { if (mode != Helper.VIDEO_MODE_WEBVIEW) {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
openFullscreenDialog(); openFullscreenDialog();
setFullscreen(FullScreenMediaController.fullscreen.ON); }
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { setFullscreen(FullScreenMediaController.fullscreen.ON);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
if (mode != Helper.VIDEO_MODE_WEBVIEW) {
closeFullscreenDialog(); closeFullscreenDialog();
setFullscreen(FullScreenMediaController.fullscreen.OFF);
} }
change(); setFullscreen(FullScreenMediaController.fullscreen.OFF);
} else {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setFullscreen(FullScreenMediaController.fullscreen.ON);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
setFullscreen(FullScreenMediaController.fullscreen.OFF);
}
change();
} }
change();
} }

View File

@ -80,7 +80,6 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
private String videoId; private String videoId;
private Account channel; private Account channel;
@SuppressWarnings("SuspiciousMethodCalls")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -168,12 +167,12 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
translations = new LinkedHashMap<>(peertubeInformation.getTranslations()); translations = new LinkedHashMap<>(peertubeInformation.getTranslations());
//Populate catgories //Populate catgories
String[] categoriesA = new String[categories.size()]; String[] categoriesA = new String[categories.size()];
Iterator it = categories.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = categories.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue())) if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
categoriesA[i] = (String) pair.getValue(); categoriesA[i] = pair.getValue();
else else
categoriesA[i] = translations.get(pair.getValue()); categoriesA[i] = translations.get(pair.getValue());
it.remove(); it.remove();
@ -189,9 +188,9 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
it = licences.entrySet().iterator(); it = licences.entrySet().iterator();
i = 0; i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue())) if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
licensesA[i] = (String) pair.getValue(); licensesA[i] = pair.getValue();
else else
licensesA[i] = translations.get(pair.getValue()); licensesA[i] = translations.get(pair.getValue());
it.remove(); it.remove();
@ -204,12 +203,12 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
//Populate languages //Populate languages
String[] languagesA = new String[languages.size()]; String[] languagesA = new String[languages.size()];
it = languages.entrySet().iterator(); Iterator<Map.Entry<String, String>> itl = languages.entrySet().iterator();
i = 0; i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = itl.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue())) if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
languagesA[i] = (String) pair.getValue(); languagesA[i] = pair.getValue();
else else
languagesA[i] = translations.get(pair.getValue()); languagesA[i] = translations.get(pair.getValue());
it.remove(); it.remove();
@ -225,9 +224,9 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
it = privacies.entrySet().iterator(); it = privacies.entrySet().iterator();
i = 0; i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue())) if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
privaciesA[i] = (String) pair.getValue(); privaciesA[i] = pair.getValue();
else else
privaciesA[i] = translations.get(pair.getValue()); privaciesA[i] = translations.get(pair.getValue());
it.remove(); it.remove();
@ -347,9 +346,9 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
int languagePosition = 0; int languagePosition = 0;
if (languages.containsValue(language)) { if (languages.containsValue(language)) {
Iterator it = languages.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = languages.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
if (pair.getValue().equals(language)) if (pair.getValue().equals(language))
break; break;
it.remove(); it.remove();
@ -358,9 +357,9 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
} }
int privacyPosition = 0; int privacyPosition = 0;
if (privacy != null && privacies.containsValue(privacy)) { if (privacy != null && privacies.containsValue(privacy)) {
Iterator it = privacies.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = privacies.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (pair.getValue().equals(privacy)) if (pair.getValue().equals(privacy))
break; break;
it.remove(); it.remove();
@ -369,9 +368,9 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
} }
int licensePosition = 0; int licensePosition = 0;
if (license != null && licences.containsValue(license)) { if (license != null && licences.containsValue(license)) {
Iterator it = licences.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = licences.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (pair.getValue().equals(license)) if (pair.getValue().equals(license))
break; break;
it.remove(); it.remove();
@ -380,9 +379,9 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
} }
int categoryPosition = 0; int categoryPosition = 0;
if (category != null && categories.containsValue(category)) { if (category != null && categories.containsValue(category)) {
Iterator it = categories.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = categories.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (pair.getValue().equals(category)) if (pair.getValue().equals(category))
break; break;
it.remove(); it.remove();
@ -395,13 +394,13 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies()); LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Iterator it = privaciesCheck.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = privaciesCheck.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (i == position) { if (i == position) {
privacyToSend = new HashMap<>(); privacyToSend = new HashMap<>();
privacyToSend.put((Integer) pair.getKey(), (String) pair.getValue()); privacyToSend.put(pair.getKey(), pair.getValue());
break; break;
} }
it.remove(); it.remove();
@ -418,13 +417,13 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> licensesCheck = new LinkedHashMap<>(peertubeInformation.getLicences()); LinkedHashMap<Integer, String> licensesCheck = new LinkedHashMap<>(peertubeInformation.getLicences());
Iterator it = licensesCheck.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = licensesCheck.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (i == position) { if (i == position) {
licenseToSend = new HashMap<>(); licenseToSend = new HashMap<>();
licenseToSend.put((Integer) pair.getKey(), (String) pair.getValue()); licenseToSend.put(pair.getKey(), pair.getValue());
break; break;
} }
it.remove(); it.remove();
@ -442,13 +441,13 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> categoriesCheck = new LinkedHashMap<>(peertubeInformation.getCategories()); LinkedHashMap<Integer, String> categoriesCheck = new LinkedHashMap<>(peertubeInformation.getCategories());
Iterator it = categoriesCheck.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = categoriesCheck.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (i == position) { if (i == position) {
categoryToSend = new HashMap<>(); categoryToSend = new HashMap<>();
categoryToSend.put((Integer) pair.getKey(), (String) pair.getValue()); categoryToSend.put(pair.getKey(), pair.getValue());
break; break;
} }
it.remove(); it.remove();
@ -467,13 +466,13 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<String, String> languagesCheck = new LinkedHashMap<>(peertubeInformation.getLanguages()); LinkedHashMap<String, String> languagesCheck = new LinkedHashMap<>(peertubeInformation.getLanguages());
Iterator it = languagesCheck.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = languagesCheck.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
if (i == position) { if (i == position) {
languageToSend = new HashMap<>(); languageToSend = new HashMap<>();
languageToSend.put((String) pair.getKey(), (String) pair.getValue()); languageToSend.put(pair.getKey(), pair.getValue());
break; break;
} }
it.remove(); it.remove();
@ -491,13 +490,13 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels); LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels);
Iterator it = channelsCheck.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = channelsCheck.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
if (i == position) { if (i == position) {
channelToSend = new HashMap<>(); channelToSend = new HashMap<>();
channelToSend.put((String) pair.getKey(), (String) pair.getValue()); channelToSend.put(pair.getKey(), pair.getValue());
break; break;
} }
@ -540,8 +539,7 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
List<String> tags = peertube.getTags(); List<String> tags = peertube.getTags();
if (tags != null && tags.size() > 0) { if (tags != null && tags.size() > 0) {
//noinspection ToArrayCallWithZeroLengthArrayArgument String[] tagsA = tags.toArray(new String[0]);
String[] tagsA = tags.toArray(new String[tags.size()]);
p_video_tags.setTags(tagsA); p_video_tags.setTags(tagsA);
} }
@ -578,12 +576,12 @@ public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrie
int channelPosition = 0; int channelPosition = 0;
if (channels.containsKey(channel.getUsername())) { if (channels.containsKey(channel.getUsername())) {
LinkedHashMap<String, String> channelsIterator = new LinkedHashMap<>(channels); LinkedHashMap<String, String> channelsIterator = new LinkedHashMap<>(channels);
Iterator it = channelsIterator.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = channelsIterator.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
if (pair.getKey().equals(channel.getUsername())) { if (pair.getKey().equals(channel.getUsername())) {
channelToSend = new HashMap<>(); channelToSend = new HashMap<>();
channelToSend.put((String) pair.getKey(), (String) pair.getValue()); channelToSend.put(pair.getKey(), pair.getValue());
break; break;
} }
it.remove(); it.remove();

View File

@ -194,7 +194,6 @@ public class PeertubeUploadActivity extends BaseActivity implements OnRetrievePe
} }
@SuppressWarnings("SuspiciousMethodCalls")
@Override @Override
public void onRetrievePeertubeChannels(APIResponse apiResponse) { public void onRetrievePeertubeChannels(APIResponse apiResponse) {
if (apiResponse.getError() != null || apiResponse.getAccounts() == null || apiResponse.getAccounts().size() == 0) { if (apiResponse.getError() != null || apiResponse.getAccounts() == null || apiResponse.getAccounts().size() == 0) {
@ -237,12 +236,12 @@ public class PeertubeUploadActivity extends BaseActivity implements OnRetrievePe
LinkedHashMap<Integer, String> privacies = new LinkedHashMap<>(peertubeInformation.getPrivacies()); LinkedHashMap<Integer, String> privacies = new LinkedHashMap<>(peertubeInformation.getPrivacies());
//Populate privacies //Populate privacies
String[] privaciesA = new String[privacies.size()]; String[] privaciesA = new String[privacies.size()];
Iterator it = privacies.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = privacies.entrySet().iterator();
i = 0; i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue())) if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
privaciesA[i] = (String) pair.getValue(); privaciesA[i] = pair.getValue();
else else
privaciesA[i] = translations.get(pair.getValue()); privaciesA[i] = translations.get(pair.getValue());
it.remove(); it.remove();
@ -258,13 +257,13 @@ public class PeertubeUploadActivity extends BaseActivity implements OnRetrievePe
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies()); LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Iterator it = privaciesCheck.entrySet().iterator(); Iterator<Map.Entry<Integer, String>> it = privaciesCheck.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<Integer, String> pair = it.next();
if (i == position) { if (i == position) {
privacyToSend = new HashMap<>(); privacyToSend = new HashMap<>();
privacyToSend.put((Integer) pair.getKey(), (String) pair.getValue()); privacyToSend.put(pair.getKey(), pair.getValue());
break; break;
} }
it.remove(); it.remove();
@ -309,13 +308,13 @@ public class PeertubeUploadActivity extends BaseActivity implements OnRetrievePe
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels); LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels);
Iterator it = channelsCheck.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = channelsCheck.entrySet().iterator();
int i = 0; int i = 0;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
if (i == position) { if (i == position) {
channelToSend = new HashMap<>(); channelToSend = new HashMap<>();
channelToSend.put((String) pair.getKey(), (String) pair.getValue()); channelToSend.put(pair.getKey(), pair.getValue());
break; break;
} }

View File

@ -18,6 +18,7 @@ import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.net.Uri; import android.net.Uri;
@ -33,6 +34,8 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet; import androidx.constraintlayout.widget.ConstraintSet;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.exifinterface.media.ExifInterface; import androidx.exifinterface.media.ExifInterface;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
@ -74,6 +77,7 @@ public class PhotoEditorActivity extends BaseActivity implements OnPhotoEditorLi
private static final int CAMERA_REQUEST = 52; private static final int CAMERA_REQUEST = 52;
private static final int PICK_REQUEST = 53; private static final int PICK_REQUEST = 53;
private final int STORE_REQUEST = 54;
private PhotoEditor mPhotoEditor; private PhotoEditor mPhotoEditor;
private PhotoEditorView mPhotoEditorView; private PhotoEditorView mPhotoEditorView;
private PropertiesBSFragment mPropertiesBSFragment; private PropertiesBSFragment mPropertiesBSFragment;
@ -302,6 +306,13 @@ public class PhotoEditorActivity extends BaseActivity implements OnPhotoEditorLi
.setClearViewsEnabled(true) .setClearViewsEnabled(true)
.setTransparencyEnabled(true) .setTransparencyEnabled(true)
.build(); .build();
if (ContextCompat.checkSelfPermission(PhotoEditorActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PhotoEditorActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
STORE_REQUEST);
return;
}
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() { mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
@Override @Override
public void onSuccess(@NonNull String imagePath) { public void onSuccess(@NonNull String imagePath) {
@ -332,6 +343,18 @@ public class PhotoEditorActivity extends BaseActivity implements OnPhotoEditorLi
} }
} }
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == STORE_REQUEST) {// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// We have the permission.
saveImage();
}
}
}
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);

View File

@ -254,8 +254,7 @@ public class PixelfedComposeActivity extends BaseActivity implements UploadStatu
final int[] currentCursorPosition = {toot_content.getSelectionStart()}; final int[] currentCursorPosition = {toot_content.getSelectionStart()};
final String[] newContent = {null}; final String[] newContent = {null};
final int[] searchLength = {searchDeep}; final int[] searchLength = {searchDeep};
TextWatcher textw = null; TextWatcher textw;
TextWatcher finalTextw = textw;
textw = new TextWatcher() { textw = new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -270,7 +269,7 @@ public class PixelfedComposeActivity extends BaseActivity implements UploadStatu
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
if (autocomplete) { if (autocomplete) {
toot_content.removeTextChangedListener(finalTextw); toot_content.removeTextChangedListener(this);
Thread thread = new Thread() { Thread thread = new Thread() {
@Override @Override
public void run() { public void run() {
@ -357,11 +356,8 @@ public class PixelfedComposeActivity extends BaseActivity implements UploadStatu
if (s.toString().length() == 0) if (s.toString().length() == 0)
currentCursorPosition[0] = 0; currentCursorPosition[0] = 0;
//Only check last 15 characters before cursor position to avoid lags //Only check last 15 characters before cursor position to avoid lags
if (currentCursorPosition[0] < searchDeep) { //Less than 15 characters are written before the cursor position //Less than 15 characters are written before the cursor position
searchLength[0] = currentCursorPosition[0]; searchLength[0] = Math.min(currentCursorPosition[0], searchDeep);
} else {
searchLength[0] = searchDeep;
}
int totalChar = countLength(social, toot_content); int totalChar = countLength(social, toot_content);
@ -700,6 +696,9 @@ public class PixelfedComposeActivity extends BaseActivity implements UploadStatu
} }
restored = b.getLong("restored", -1); restored = b.getLong("restored", -1);
} }
if (!sharedUri.isEmpty()) {
uploadSharedImage(sharedUri);
}
if (scheduledstatus != null) if (scheduledstatus != null)
toot_it.setText(R.string.modify); toot_it.setText(R.string.modify);
if (restoredScheduled) { if (restoredScheduled) {

View File

@ -81,9 +81,6 @@ public class PlaylistsActivity extends BaseActivity implements OnPlaylistActionI
case Helper.THEME_LIGHT: case Helper.THEME_LIGHT:
setTheme(R.style.AppTheme_NoActionBar_Fedilab); setTheme(R.style.AppTheme_NoActionBar_Fedilab);
break; break;
case Helper.THEME_DARK:
setTheme(R.style.AppThemeDark_NoActionBar);
break;
case Helper.THEME_BLACK: case Helper.THEME_BLACK:
setTheme(R.style.AppThemeBlack_NoActionBar); setTheme(R.style.AppThemeBlack_NoActionBar);
break; break;
@ -102,12 +99,7 @@ public class PlaylistsActivity extends BaseActivity implements OnPlaylistActionI
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close); ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title); TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
toolbar_close.setOnClickListener(new View.OnClickListener() { toolbar_close.setOnClickListener(v -> finish());
@Override
public void onClick(View v) {
finish();
}
});
toolbar_title.setText(R.string.upload_video); toolbar_title.setText(R.string.upload_video);
} }
@ -140,7 +132,6 @@ public class PlaylistsActivity extends BaseActivity implements OnPlaylistActionI
mainLoader.setVisibility(View.VISIBLE); mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE); nextElementLoader.setVisibility(View.GONE);
boolean isOnWifi = Helper.isOnWIFI(PlaylistsActivity.this);
peertubeAdapter = new PeertubeAdapter(Helper.getLiveInstance(PlaylistsActivity.this), false, this.peertubes); peertubeAdapter = new PeertubeAdapter(Helper.getLiveInstance(PlaylistsActivity.this), false, this.peertubes);
@ -181,16 +172,13 @@ public class PlaylistsActivity extends BaseActivity implements OnPlaylistActionI
}); });
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { swipeRefreshLayout.setOnRefreshListener(() -> {
@Override max_id = null;
public void onRefresh() { firstLoad = true;
max_id = null; flag_loading = true;
firstLoad = true; swiped = true;
flag_loading = true; MainActivity.countNewStatus = 0;
swiped = true; new ManagePlaylistsAsyncTask(PlaylistsActivity.this, GET_LIST_VIDEOS, playlist, null, null, PlaylistsActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
MainActivity.countNewStatus = 0;
new ManagePlaylistsAsyncTask(PlaylistsActivity.this, GET_LIST_VIDEOS, playlist, null, null, PlaylistsActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}); });
new ManagePlaylistsAsyncTask(PlaylistsActivity.this, GET_LIST_VIDEOS, playlist, null, null, PlaylistsActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new ManagePlaylistsAsyncTask(PlaylistsActivity.this, GET_LIST_VIDEOS, playlist, null, null, PlaylistsActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@ -199,19 +187,16 @@ public class PlaylistsActivity extends BaseActivity implements OnPlaylistActionI
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { if (item.getItemId() == android.R.id.home) {
case android.R.id.home: finish();
finish(); return true;
return true;
default:
return super.onOptionsItemSelected(item);
} }
return super.onOptionsItemSelected(item);
} }
@Override @Override
public void onActionDone(ManagePlaylistsAsyncTask.action actionType, APIResponse apiResponse, int statusCode) { public void onActionDone(ManagePlaylistsAsyncTask.action actionType, APIResponse apiResponse, int statusCode) {
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
mainLoader.setVisibility(View.GONE); mainLoader.setVisibility(View.GONE);
nextElementLoader.setVisibility(View.GONE); nextElementLoader.setVisibility(View.GONE);
//Discards 404 - error which can often happen due to toots which have been deleted //Discards 404 - error which can often happen due to toots which have been deleted
@ -236,9 +221,7 @@ public class PlaylistsActivity extends BaseActivity implements OnPlaylistActionI
if (swiped) { if (swiped) {
if (previousPosition > 0) { if (previousPosition > 0) {
for (int i = 0; i < previousPosition; i++) { this.peertubes.subList(0, previousPosition).clear();
this.peertubes.remove(0);
}
peertubeAdapter.notifyItemRangeRemoved(0, previousPosition); peertubeAdapter.notifyItemRangeRemoved(0, previousPosition);
} }
swiped = false; swiped = false;

View File

@ -60,13 +60,10 @@ public class ProxyActivity extends BaseActivity {
boolean enable_proxy = sharedpreferences.getBoolean(Helper.SET_PROXY_ENABLED, false); boolean enable_proxy = sharedpreferences.getBoolean(Helper.SET_PROXY_ENABLED, false);
final CheckBox set_enable_proxy = findViewById(R.id.enable_proxy); final CheckBox set_enable_proxy = findViewById(R.id.enable_proxy);
set_enable_proxy.setChecked(enable_proxy); set_enable_proxy.setChecked(enable_proxy);
set_enable_proxy.setOnClickListener(new View.OnClickListener() { set_enable_proxy.setOnClickListener(v -> {
@Override SharedPreferences.Editor editor = sharedpreferences.edit();
public void onClick(View v) { editor.putBoolean(Helper.SET_PROXY_ENABLED, set_enable_proxy.isChecked());
SharedPreferences.Editor editor = sharedpreferences.edit(); editor.apply();
editor.putBoolean(Helper.SET_PROXY_ENABLED, set_enable_proxy.isChecked());
editor.apply();
}
}); });
Button save = findViewById(R.id.set_proxy_save); Button save = findViewById(R.id.set_proxy_save);
@ -112,34 +109,29 @@ public class ProxyActivity extends BaseActivity {
} }
}); });
save.setOnClickListener(new View.OnClickListener() { save.setOnClickListener(view -> {
@Override String hostVal1 = host.getText().toString().trim();
public void onClick(View view) { String portVal1 = port.getText().toString().trim();
String hostVal = host.getText().toString().trim(); String proxy_loginVal = proxy_login.getText().toString().trim();
String portVal = port.getText().toString().trim(); String proxy_passwordVal = proxy_password.getText().toString().trim();
String proxy_loginVal = proxy_login.getText().toString().trim(); SharedPreferences.Editor editor = sharedpreferences.edit();
String proxy_passwordVal = proxy_password.getText().toString().trim(); editor.putString(Helper.SET_PROXY_HOST, hostVal1);
SharedPreferences.Editor editor = sharedpreferences.edit(); if (portVal1.matches("\\d+"))
editor.putString(Helper.SET_PROXY_HOST, hostVal); editor.putInt(Helper.SET_PROXY_PORT, Integer.parseInt(portVal1));
if (portVal.matches("\\d+")) editor.putString(Helper.SET_PROXY_LOGIN, proxy_loginVal);
editor.putInt(Helper.SET_PROXY_PORT, Integer.parseInt(portVal)); editor.putString(Helper.SET_PROXY_PASSWORD, proxy_passwordVal);
editor.putString(Helper.SET_PROXY_LOGIN, proxy_loginVal); editor.apply();
editor.putString(Helper.SET_PROXY_PASSWORD, proxy_passwordVal); finish();
editor.apply();
finish();
}
}); });
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { if (item.getItemId() == android.R.id.home) {
case android.R.id.home: finish();
finish(); return true;
return true;
default:
return super.onOptionsItemSelected(item);
} }
return super.onOptionsItemSelected(item);
} }

View File

@ -15,7 +15,6 @@
package app.fedilab.android.activities; package app.fedilab.android.activities;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
@ -33,7 +32,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView; import android.widget.AutoCompleteTextView;
import android.widget.ImageView; import android.widget.ImageView;
@ -138,212 +136,174 @@ public class ReorderTimelinesActivity extends BaseActivity implements OnStartDra
ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close); ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title); TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
ImageView add_remote_instance = actionBar.getCustomView().findViewById(R.id.add_remote_instance); ImageView add_remote_instance = actionBar.getCustomView().findViewById(R.id.add_remote_instance);
toolbar_close.setOnClickListener(new View.OnClickListener() { toolbar_close.setOnClickListener(v -> finish());
@Override
public void onClick(View v) {
finish();
}
});
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) {
add_remote_instance.setVisibility(View.VISIBLE); add_remote_instance.setVisibility(View.VISIBLE);
} else { } else {
add_remote_instance.setVisibility(View.GONE); add_remote_instance.setVisibility(View.GONE);
} }
add_remote_instance.setOnClickListener(new View.OnClickListener() { add_remote_instance.setOnClickListener(v -> {
@Override AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(ReorderTimelinesActivity.this, style);
public void onClick(View v) { LayoutInflater inflater1 = getLayoutInflater();
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(ReorderTimelinesActivity.this, style); @SuppressLint("InflateParams") View dialogView = inflater1.inflate(R.layout.search_instance, null);
LayoutInflater inflater = getLayoutInflater(); dialogBuilder.setView(dialogView);
@SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.search_instance, null);
dialogBuilder.setView(dialogView);
AutoCompleteTextView instance_list = dialogView.findViewById(R.id.search_instance); AutoCompleteTextView instance_list = dialogView.findViewById(R.id.search_instance);
//Manage download of attachments //Manage download of attachments
RadioGroup radioGroup = dialogView.findViewById(R.id.set_attachment_group); RadioGroup radioGroup = dialogView.findViewById(R.id.set_attachment_group);
radioGroup.setOnCheckedChangeListener((group, checkedId) -> { radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.twitter_accounts) { if (checkedId == R.id.twitter_accounts) {
instance_list.setHint(R.string.list_of_twitter_accounts); instance_list.setHint(R.string.list_of_twitter_accounts);
} else { } else {
instance_list.setHint(R.string.instance); instance_list.setHint(R.string.instance);
} }
}); });
instance_list.setFilters(new InputFilter[]{new InputFilter.LengthFilter(60)}); instance_list.setFilters(new InputFilter[]{new InputFilter.LengthFilter(60)});
dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() { dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
@Override SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
public void onClick(DialogInterface dialog, int id) { String instanceName = instance_list.getText().toString().trim().replace("@", "");
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); new Thread(() -> {
String instanceName = instance_list.getText().toString().trim().replace("@", ""); try {
new Thread(new Runnable() { if (radioGroup.getCheckedRadioButtonId() == R.id.mastodon_instance)
@Override new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/v1/timelines/public?local=true", 10, null, null);
public void run() { else if (radioGroup.getCheckedRadioButtonId() == R.id.peertube_instance)
try { new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/v1/videos/", 10, null, null);
if (radioGroup.getCheckedRadioButtonId() == R.id.mastodon_instance) else if (radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) {
new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/v1/timelines/public?local=true", 10, null, null); new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/v1/timelines/public", 10, null, null);
else if (radioGroup.getCheckedRadioButtonId() == R.id.peertube_instance) } else if (radioGroup.getCheckedRadioButtonId() == R.id.misskey_instance) {
new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/v1/videos/", 10, null, null); new HttpsConnection(ReorderTimelinesActivity.this, null).post("https://" + instanceName + "/api/notes/local-timeline", 10, null, null);
else if (radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) { } else if (radioGroup.getCheckedRadioButtonId() == R.id.gnu_instance) {
new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/v1/timelines/public", 10, null, null); new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/statuses/public_timeline.json", 10, null, null);
} else if (radioGroup.getCheckedRadioButtonId() == R.id.misskey_instance) { }
new HttpsConnection(ReorderTimelinesActivity.this, null).post("https://" + instanceName + "/api/notes/local-timeline", 10, null, null); runOnUiThread(() -> {
} else if (radioGroup.getCheckedRadioButtonId() == R.id.gnu_instance) { dialog.dismiss();
new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://" + instanceName + "/api/statuses/public_timeline.json", 10, null, null); if (radioGroup.getCheckedRadioButtonId() == R.id.mastodon_instance) {
} new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "MASTODON");
runOnUiThread(new Runnable() { } else if (radioGroup.getCheckedRadioButtonId() == R.id.peertube_instance) {
public void run() { new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "PEERTUBE");
dialog.dismiss(); } else if (radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) {
if (radioGroup.getCheckedRadioButtonId() == R.id.mastodon_instance) { new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "PIXELFED");
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "MASTODON"); } else if (radioGroup.getCheckedRadioButtonId() == R.id.misskey_instance) {
} else if (radioGroup.getCheckedRadioButtonId() == R.id.peertube_instance) { new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "MISSKEY");
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "PEERTUBE"); } else if (radioGroup.getCheckedRadioButtonId() == R.id.gnu_instance) {
} else if (radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) { new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "GNU");
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "PIXELFED"); } else if (radioGroup.getCheckedRadioButtonId() == R.id.twitter_accounts) {
} else if (radioGroup.getCheckedRadioButtonId() == R.id.misskey_instance) { new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "NITTER");
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "MISSKEY"); }
} else if (radioGroup.getCheckedRadioButtonId() == R.id.gnu_instance) { if (timelines != null && adapter != null) {
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "GNU"); List<RemoteInstance> instance = new InstancesDAO(ReorderTimelinesActivity.this, db).getInstanceByName(instanceName);
} else if (radioGroup.getCheckedRadioButtonId() == R.id.twitter_accounts) { if (instance != null && instance.size() > 0) {
new InstancesDAO(ReorderTimelinesActivity.this, db).insertInstance(instanceName, "NITTER"); ManageTimelines manageTimelines = new ManageTimelines();
} manageTimelines.setRemoteInstance(instance.get(0));
if (timelines != null && adapter != null) { manageTimelines.setPosition(timelines.size());
List<RemoteInstance> instance = new InstancesDAO(ReorderTimelinesActivity.this, db).getInstanceByName(instanceName); manageTimelines.setDisplayed(true);
if (instance != null && instance.size() > 0) { manageTimelines.setType(ManageTimelines.Type.INSTANCE);
ManageTimelines manageTimelines = new ManageTimelines(); timelines.add(manageTimelines);
manageTimelines.setRemoteInstance(instance.get(0)); adapter.notifyItemInserted((timelines.size() - 1));
manageTimelines.setPosition(timelines.size());
manageTimelines.setDisplayed(true);
manageTimelines.setType(ManageTimelines.Type.INSTANCE);
timelines.add(manageTimelines);
adapter.notifyItemInserted((timelines.size() - 1));
}
updated = true;
}
}
});
} catch (final Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
Toasty.warning(ReorderTimelinesActivity.this, getString(R.string.toast_instance_unavailable), Toast.LENGTH_LONG).show();
}
});
} }
updated = true;
} }
}).start(); });
} catch (final Exception e) {
e.printStackTrace();
runOnUiThread(() -> Toasty.warning(ReorderTimelinesActivity.this, getString(R.string.toast_instance_unavailable), Toast.LENGTH_LONG).show());
} }
}); }).start();
AlertDialog alertDialog = dialogBuilder.create(); });
alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { AlertDialog alertDialog = dialogBuilder.create();
@Override alertDialog.setOnDismissListener(dialogInterface -> {
public void onDismiss(DialogInterface dialogInterface) { //Hide keyboard
//Hide keyboard InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); assert imm != null;
assert imm != null; imm.hideSoftInputFromWindow(instance_list.getWindowToken(), 0);
imm.hideSoftInputFromWindow(instance_list.getWindowToken(), 0); });
} if (alertDialog.getWindow() != null)
}); alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
if (alertDialog.getWindow() != null) alertDialog.show();
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
alertDialog.show();
instance_list.setOnItemClickListener(new AdapterView.OnItemClickListener() { instance_list.setOnItemClickListener((parent, view1, position, id) -> {
@Override });
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { instance_list.addTextChangedListener(new TextWatcher() {
String oldSearch = parent.getItemAtPosition(position).toString().trim(); @Override
} public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}); }
instance_list.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
} }
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
if (radioGroup.getCheckedRadioButtonId() != R.id.twitter_accounts) { if (radioGroup.getCheckedRadioButtonId() != R.id.twitter_accounts) {
Pattern host = Pattern.compile("([\\da-z\\.-]+\\.[a-z\\.]{2,12})"); Pattern host = Pattern.compile("([\\da-z.-]+\\.[a-z.]{2,12})");
Matcher matcher = host.matcher(s.toString().trim()); Matcher matcher = host.matcher(s.toString().trim());
if (s.toString().trim().length() == 0 || !matcher.find()) { if (s.toString().trim().length() == 0 || !matcher.find()) {
alertDialog.getButton( alertDialog.getButton(
AlertDialog.BUTTON_POSITIVE).setEnabled(false); 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 { } else {
// Something into edit text. Enable the button.
alertDialog.getButton( alertDialog.getButton(
AlertDialog.BUTTON_POSITIVE).setEnabled(true); 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(() -> {
try {
final String response = new HttpsConnection(ReorderTimelinesActivity.this, null).get("https://instances.social/api/1.0" + action, 30, parameters, Helper.THEKINRAR_SECRET_TOKEN);
runOnUiThread(() -> {
isLoadingInstance = false;
String[] instances;
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("instances");
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++;
}
}
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 (Exception e) {
isLoadingInstance = false;
}
}).start();
else
isLoadingInstance = false;
}
} else {
alertDialog.getButton(
AlertDialog.BUTTON_POSITIVE).setEnabled(true);
} }
});
} }
});
}); });
toolbar_title.setText(R.string.action_reorder_timeline); toolbar_title.setText(R.string.action_reorder_timeline);
} }
@ -390,40 +350,34 @@ public class ReorderTimelinesActivity extends BaseActivity implements OnStartDra
break; break;
} }
undo_action.setPaintFlags(undo_action.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); undo_action.setPaintFlags(undo_action.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
Runnable runnable = new Runnable() { Runnable runnable = () -> {
@Override undo_container.setVisibility(View.GONE);
public void run() { SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
undo_container.setVisibility(View.GONE); switch (manageTimelines.getType()) {
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); case TAG:
switch (manageTimelines.getType()) { new SearchDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines.getTagTimeline().getName());
case TAG: new TimelinesDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines);
new SearchDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines.getTagTimeline().getName()); break;
new TimelinesDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines); case INSTANCE:
break; new InstancesDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines.getRemoteInstance().getHost());
case INSTANCE: new TimelinesDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines);
new InstancesDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines.getRemoteInstance().getHost()); break;
new TimelinesDAO(ReorderTimelinesActivity.this, db).remove(manageTimelines); case LIST:
break; timeline = manageTimelines;
case LIST: new ManageListsAsyncTask(ReorderTimelinesActivity.this, ManageListsAsyncTask.action.DELETE_LIST, null, null, manageTimelines.getListTimeline().getId(), null, ReorderTimelinesActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
timeline = manageTimelines; new TimelinesDAO(ReorderTimelinesActivity.this, db).remove(timeline);
new ManageListsAsyncTask(ReorderTimelinesActivity.this, ManageListsAsyncTask.action.DELETE_LIST, null, null, manageTimelines.getListTimeline().getId(), null, ReorderTimelinesActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); refresh_list = true;
new TimelinesDAO(ReorderTimelinesActivity.this, db).remove(timeline); break;
refresh_list = true;
break;
}
updated = true;
} }
updated = true;
}; };
Handler handler = new Handler(); Handler handler = new Handler();
handler.postDelayed(runnable, 4000); handler.postDelayed(runnable, 4000);
undo_action.setOnClickListener(new View.OnClickListener() { undo_action.setOnClickListener(v -> {
@Override timelines.add(position, manageTimelines);
public void onClick(View v) { adapter.notifyItemInserted(position);
timelines.add(position, manageTimelines); undo_container.setVisibility(View.GONE);
adapter.notifyItemInserted(position); handler.removeCallbacks(runnable);
undo_container.setVisibility(View.GONE);
handler.removeCallbacks(runnable);
}
}); });
} }

View File

@ -48,6 +48,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -545,14 +546,14 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
if ((MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) && account.getFields() != null && account.getFields().size() > 0) { if ((MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) && account.getFields() != null && account.getFields().size() > 0) {
LinkedHashMap<String, String> fields = account.getFields(); LinkedHashMap<String, String> fields = account.getFields();
LinkedHashMap<String, Boolean> fieldsVerified = account.getFieldsVerified(); LinkedHashMap<String, Boolean> fieldsVerified = account.getFieldsVerified();
Iterator it = fields.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = fields.entrySet().iterator();
int i = 1; int i = 1;
LinearLayout fields_container = findViewById(R.id.fields_container); LinearLayout fields_container = findViewById(R.id.fields_container);
if (fields_container != null) if (fields_container != null)
fields_container.setVisibility(View.VISIBLE); fields_container.setVisibility(View.VISIBLE);
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
String label = (String) pair.getKey(); String label = pair.getKey();
if (label != null && fieldsVerified != null && fieldsVerified.containsKey(label)) { if (label != null && fieldsVerified != null && fieldsVerified.containsKey(label)) {
boolean verified = fieldsVerified.get(label); boolean verified = fieldsVerified.get(label);
@ -618,7 +619,7 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
SpannableString spannableString = Helper.clickableElementsDescription(ShowAccountActivity.this, account.getNote()); SpannableString spannableString = Helper.clickableElementsDescription(ShowAccountActivity.this, account.getNote());
account.setNoteSpan(spannableString); account.setNoteSpan(spannableString);
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA)
account.makeEmojisAccountProfile(ShowAccountActivity.this, ShowAccountActivity.this, account); account.fillProfileAccount(ShowAccountActivity.this, ShowAccountActivity.this, account);
account_note.setText(account.getNoteSpan(), TextView.BufferType.SPANNABLE); account_note.setText(account.getNoteSpan(), TextView.BufferType.SPANNABLE);
account_note.setMovementMethod(LinkMovementMethod.getInstance()); account_note.setMovementMethod(LinkMovementMethod.getInstance());
if (!peertubeAccount && tabLayout.getTabAt(0) != null && tabLayout.getTabAt(1) != null && tabLayout.getTabAt(2) != null) { if (!peertubeAccount && tabLayout.getTabAt(0) != null && tabLayout.getTabAt(1) != null && tabLayout.getTabAt(2) != null) {
@ -739,7 +740,15 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
b.putInt("position", 1); b.putInt("position", 1);
b.putInt("bgcolor", getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", getResources().getColor(R.color.cyanea_primary_dark));
intent.putExtras(b); intent.putExtras(b);
startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(ShowAccountActivity.this, account_pp, attachment.getUrl());
// start the new activity
startActivity(intent, options.toBundle());
} else {
// start the new activity
startActivity(intent);
}
}); });
//Follow button //Follow button
String target = account.getId(); String target = account.getId();
@ -962,24 +971,20 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
LinkedHashMap<String, Boolean> fieldsVerified = account.getFieldsVerified(); LinkedHashMap<String, Boolean> fieldsVerified = account.getFieldsVerified();
if (account.getFieldsSpan() != null && account.getFieldsSpan().size() > 0) { if (account.getFieldsSpan() != null && account.getFieldsSpan().size() > 0) {
HashMap<SpannableString, SpannableString> fieldsSpan = account.getFieldsSpan(); HashMap<SpannableString, SpannableString> fieldsSpan = account.getFieldsSpan();
Iterator it = fieldsSpan.entrySet().iterator();
Iterator<Map.Entry<SpannableString, SpannableString>> it = fieldsSpan.entrySet().iterator();
int i = 1; int i = 1;
LinearLayout fields_container = findViewById(R.id.fields_container); LinearLayout fields_container = findViewById(R.id.fields_container);
if (fields_container != null) if (fields_container != null)
fields_container.setVisibility(View.VISIBLE); fields_container.setVisibility(View.VISIBLE);
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<SpannableString, SpannableString> pair = it.next();
SpannableString label = (SpannableString) pair.getKey(); SpannableString label = pair.getKey();
SpannableString value = (SpannableString) pair.getValue(); SpannableString value = pair.getValue();
LinearLayout field; LinearLayout field;
TextView labelView; TextView labelView;
TextView valueView; TextView valueView;
switch (i) { switch (i) {
case 1:
field = findViewById(R.id.field1);
labelView = findViewById(R.id.label1);
valueView = findViewById(R.id.value1);
break;
case 2: case 2:
field = findViewById(R.id.field2); field = findViewById(R.id.field2);
labelView = findViewById(R.id.label2); labelView = findViewById(R.id.label2);
@ -1166,7 +1171,7 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
tags = new ArrayList<>(featuredTagsSet); tags = new ArrayList<>(featuredTagsSet);
} }
tags.add(0, getString(R.string.no_tags)); tags.add(0, getString(R.string.no_tags));
String[] tagsString = tags.toArray(new String[tags.size()]); String[] tagsString = tags.toArray(new String[0]);
List<String> finalTags = tags; List<String> finalTags = tags;
String tag = sharedpreferences.getString(Helper.SET_FEATURED_TAG_ACTION, null); String tag = sharedpreferences.getString(Helper.SET_FEATURED_TAG_ACTION, null);
int checkedposition = 0; int checkedposition = 0;

View File

@ -111,10 +111,6 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve
detailsStatus.setFocused(true); detailsStatus.setFocused(true);
//Some spannable //Some spannable
Status.fillSpan(new WeakReference<>(ShowConversationActivity.this), detailsStatus); Status.fillSpan(new WeakReference<>(ShowConversationActivity.this), detailsStatus);
if (detailsStatus.getPoll() != null) {
Status.makeEmojiPoll(new WeakReference<>(ShowConversationActivity.this), detailsStatus.getPoll());
}
Account.makeAccountNameEmoji(new WeakReference<>(ShowConversationActivity.this), detailsStatus.getAccount());
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) {

View File

@ -24,6 +24,7 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.net.Uri; import android.net.Uri;
@ -35,10 +36,12 @@ import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
@ -92,13 +95,13 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
Intent shareIntent = new Intent(Intent.ACTION_SEND); Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri); shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
ContentResolver cR = context.getContentResolver(); ContentResolver cR = context.getContentResolver();
if( cR != null && uri != null) { if (cR != null && uri != null) {
shareIntent.setType(cR.getType(uri)); shareIntent.setType(cR.getType(uri));
try { try {
startActivity(shareIntent); startActivity(shareIntent);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
}else { } else {
Toasty.error(context, context.getString(R.string.toast_error), Toasty.LENGTH_LONG).show(); Toasty.error(context, context.getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
} }
} else { } else {
@ -123,8 +126,14 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
default: default:
setTheme(R.style.TransparentDark); setTheme(R.style.TransparentDark);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ActivityCompat.postponeEnterTransition(SlideMediaActivity.this);
}
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
setContentView(R.layout.activity_media_pager); setContentView(R.layout.activity_media_pager);
fullscreen = false; fullscreen = false;
media_description = findViewById(R.id.media_description); media_description = findViewById(R.id.media_description);
final int med_desc_timeout = sharedpreferences.getInt(Helper.SET_MED_DESC_TIMEOUT, 3) * 1000; final int med_desc_timeout = sharedpreferences.getInt(Helper.SET_MED_DESC_TIMEOUT, 3) * 1000;
@ -136,39 +145,37 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = getSupportActionBar();
if (actionBar != null) { if (actionBar != null) {
actionBar.setBackgroundDrawable(new ColorDrawable(bgColor));
actionBar.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
actionBar.setElevation(0);
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
assert inflater != null; assert inflater != null;
View view = inflater.inflate(R.layout.media_action_bar, new LinearLayout(SlideMediaActivity.this), false); View view = inflater.inflate(R.layout.media_action_bar, new LinearLayout(SlideMediaActivity.this), false);
view.setBackgroundColor(bgColor);
actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close); ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title); TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
ImageView media_save = actionBar.getCustomView().findViewById(R.id.media_save); ImageView media_save = actionBar.getCustomView().findViewById(R.id.media_save);
ImageView media_share = actionBar.getCustomView().findViewById(R.id.media_share); ImageView media_share = actionBar.getCustomView().findViewById(R.id.media_share);
toolbar_close.setOnClickListener(v -> finish()); toolbar_close.setOnClickListener(v -> ActivityCompat.finishAfterTransition(this));
media_save.setOnClickListener(view12 -> { media_save.setOnClickListener(view12 -> {
int position = mPager.getCurrentItem(); int position = mPager.getCurrentItem();
Attachment attachment = attachments.get(position); Attachment attachment = attachments.get(position);
if (attachment.getType().compareTo("image") == 0) { if (Build.VERSION.SDK_INT >= 23) {
if (Build.VERSION.SDK_INT >= 23) { if (ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(SlideMediaActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE_MEDIA_SAVE);
ActivityCompat.requestPermissions(SlideMediaActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
} else {
Helper.manageMove(SlideMediaActivity.this, attachment.getUrl(), false);
}
} else { } else {
Helper.manageMove(SlideMediaActivity.this, attachment.getUrl(), false); if (attachment.getType().compareTo("image") == 0) {
} Helper.manageMove(SlideMediaActivity.this, attachment.getUrl(), false);
} else {
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(SlideMediaActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
} else { } else {
Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl()); Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl());
downloadID = -1; downloadID = -1;
} }
}
} else {
if (attachment.getType().compareTo("image") == 0) {
Helper.manageMove(SlideMediaActivity.this, attachment.getUrl(), false);
} else { } else {
Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl()); Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl());
downloadID = -1; downloadID = -1;
@ -186,7 +193,7 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
} else { } else {
if (Build.VERSION.SDK_INT >= 23) { if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(SlideMediaActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(SlideMediaActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE); ActivityCompat.requestPermissions(SlideMediaActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE_MEDIA_SHARE);
} else { } else {
downloadID = Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl()); downloadID = Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl());
} }
@ -208,6 +215,7 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
mPager.setAdapter(mPagerAdapter); mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(mediaPosition - 1); mPager.setCurrentItem(mediaPosition - 1);
mPager.setOffscreenPageLimit(0);
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
String description = attachments.get(mediaPosition - 1).getDescription(); String description = attachments.get(mediaPosition - 1).getDescription();
@ -216,10 +224,16 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
media_description.setText(description); media_description.setText(description);
media_description.setVisibility(View.VISIBLE); media_description.setVisibility(View.VISIBLE);
handler.postDelayed(() -> media_description.setVisibility(View.GONE), med_desc_timeout); handler.postDelayed(() -> {
if (!media_description.hasSelection()) {
media_description.setVisibility(View.GONE);
}
}, med_desc_timeout);
} else { } else {
media_description.setVisibility(View.GONE); if (!media_description.hasSelection()) {
media_description.setVisibility(View.GONE);
}
} }
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) { public void onPageScrollStateChanged(int state) {
@ -238,10 +252,16 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
media_description.setText(description); media_description.setText(description);
media_description.setVisibility(View.VISIBLE); media_description.setVisibility(View.VISIBLE);
handler.postDelayed(() -> media_description.setVisibility(View.GONE), med_desc_timeout); handler.postDelayed(() -> {
if (!media_description.hasSelection()) {
media_description.setVisibility(View.GONE);
}
}, med_desc_timeout);
} else { } else {
media_description.setVisibility(View.GONE); if (!media_description.hasSelection()) {
media_description.setVisibility(View.GONE);
}
} }
} }
}); });
@ -257,12 +277,36 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
} }
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case Helper.EXTERNAL_STORAGE_REQUEST_CODE_MEDIA_SAVE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
int position = mPager.getCurrentItem();
Attachment attachment = attachments.get(position);
if (attachment.getType().compareTo("image") == 0) {
Helper.manageMove(SlideMediaActivity.this, attachment.getUrl(), false);
} else {
Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl());
downloadID = -1;
}
} else { /*Todo: Toast "Storage Permission Required" */ }
return;
case Helper.EXTERNAL_STORAGE_REQUEST_CODE_MEDIA_SHARE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
int position = mPager.getCurrentItem();
Attachment attachment = attachments.get(position);
downloadID = Helper.manageDownloadsNoPopup(SlideMediaActivity.this, attachment.getUrl());
} else { /*Todo: Toast "Storage Permission Required" */ }
break;
}
}
@Override @Override
public boolean dispatchTouchEvent(MotionEvent event) { public boolean dispatchTouchEvent(MotionEvent event) {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
final int med_desc_timeout = sharedpreferences.getInt(Helper.SET_MED_DESC_TIMEOUT, 3) * 1000; final int med_desc_timeout = sharedpreferences.getInt(Helper.SET_MED_DESC_TIMEOUT, 3) * 1000;
switch (event.getAction()) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
startX = event.getX(); startX = event.getX();
@ -283,10 +327,16 @@ public class SlideMediaActivity extends BaseFragmentActivity implements OnDownlo
media_description.setText(description); media_description.setText(description);
media_description.setVisibility(View.VISIBLE); media_description.setVisibility(View.VISIBLE);
handler.postDelayed(() -> media_description.setVisibility(View.GONE), med_desc_timeout); handler.postDelayed(() -> {
if (!media_description.hasSelection()) {
media_description.setVisibility(View.GONE);
}
}, med_desc_timeout);
} else { } else {
media_description.setVisibility(View.GONE); if (!media_description.hasSelection()) {
media_description.setVisibility(View.GONE);
}
} }
} }
} }

View File

@ -19,7 +19,6 @@ import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
@ -70,40 +69,34 @@ public class TagCacheActivity extends BaseActivity {
EditText tag_add = findViewById(R.id.tag_add); EditText tag_add = findViewById(R.id.tag_add);
ImageButton save_tag = findViewById(R.id.save_tag); ImageButton save_tag = findViewById(R.id.save_tag);
save_tag.setOnClickListener(new View.OnClickListener() { save_tag.setOnClickListener(v -> {
@Override if (tag_add.getText() != null && tag_add.getText().toString().trim().replaceAll("#", "").length() > 0) {
public void onClick(View v) { String tagToInsert = tag_add.getText().toString().trim().replaceAll("#", "");
if (tag_add.getText() != null && tag_add.getText().toString().trim().replaceAll("\\#", "").length() > 0) { boolean isPresent = new TagsCacheDAO(TagCacheActivity.this, db).isPresent(tagToInsert);
String tagToInsert = tag_add.getText().toString().trim().replaceAll("\\#", ""); if (isPresent)
boolean isPresent = new TagsCacheDAO(TagCacheActivity.this, db).isPresent(tagToInsert); Toasty.warning(TagCacheActivity.this, getString(R.string.tags_already_stored), Toast.LENGTH_LONG).show();
if (isPresent) else {
Toasty.warning(TagCacheActivity.this, getString(R.string.tags_already_stored), Toast.LENGTH_LONG).show(); new TagsCacheDAO(TagCacheActivity.this, db).insert(tagToInsert);
else { int position = tags.size();
new TagsCacheDAO(TagCacheActivity.this, db).insert(tagToInsert); tags.add(tagToInsert);
int position = tags.size(); Toasty.success(TagCacheActivity.this, getString(R.string.tags_stored), Toast.LENGTH_LONG).show();
tags.add(tagToInsert); tag_add.setText("");
Toasty.success(TagCacheActivity.this, getString(R.string.tags_stored), Toast.LENGTH_LONG).show(); tagsEditAdapter.notifyItemInserted(position);
tag_add.setText("");
tagsEditAdapter.notifyItemInserted(position);
}
} }
} }
}); });
setTitle(R.string.manage_tags); setTitle(R.string.manage_tags);
AsyncTask.execute(new Runnable() { AsyncTask.execute(() -> {
@Override
public void run() {
List<String> tagsTemp = new TagsCacheDAO(TagCacheActivity.this, db).getAll(); List<String> tagsTemp = new TagsCacheDAO(TagCacheActivity.this, db).getAll();
if (tagsTemp != null) if (tagsTemp != null)
tags = tagsTemp; tags = tagsTemp;
if (tags != null) { if (tags != null) {
tagsEditAdapter = new TagsEditAdapter(tags); tagsEditAdapter = new TagsEditAdapter(tags);
tag_list.setAdapter(tagsEditAdapter); tag_list.setAdapter(tagsEditAdapter);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(TagCacheActivity.this); LinearLayoutManager mLayoutManager = new LinearLayoutManager(TagCacheActivity.this);
tag_list.setLayoutManager(mLayoutManager); tag_list.setLayoutManager(mLayoutManager);
}
} }
}); });

View File

@ -134,7 +134,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.TimeZone; import java.util.Random;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -330,7 +330,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
final String[] newContent = {null}; final String[] newContent = {null};
final int[] searchLength = {searchDeep}; final int[] searchLength = {searchDeep};
TextWatcher textw = null; TextWatcher textw = null;
TextWatcher finalTextw = textw;
textw = new TextWatcher() { textw = new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -348,7 +348,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
status.setQuickReplyContent(s.toString()); status.setQuickReplyContent(s.toString());
} }
if (autocomplete) { if (autocomplete) {
toot_content.removeTextChangedListener(finalTextw); toot_content.removeTextChangedListener(this);
Thread thread = new Thread() { Thread thread = new Thread() {
@Override @Override
public void run() { public void run() {
@ -436,11 +436,8 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
if (s.toString().length() == 0) if (s.toString().length() == 0)
currentCursorPosition[0] = 0; currentCursorPosition[0] = 0;
//Only check last 15 characters before cursor position to avoid lags //Only check last 15 characters before cursor position to avoid lags
if (currentCursorPosition[0] < searchDeep) { //Less than 15 characters are written before the cursor position //Less than 15 characters are written before the cursor position
searchLength[0] = currentCursorPosition[0]; searchLength[0] = Math.min(currentCursorPosition[0], searchDeep);
} else {
searchLength[0] = searchDeep;
}
int totalChar = countLength(social, toot_content, toot_cw_content); int totalChar = countLength(social, toot_content, toot_cw_content);
@ -894,12 +891,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
if (s.toString().length() == 0) if (s.toString().length() == 0)
currentCursorPosition = 0; currentCursorPosition = 0;
//Only check last 15 characters before cursor position to avoid lags //Only check last 15 characters before cursor position to avoid lags
int searchLength; int searchLength = Math.min(currentCursorPosition, searchDeep);
if (currentCursorPosition < searchDeep) { //Less than 15 characters are written before the cursor position
searchLength = currentCursorPosition;
} else {
searchLength = searchDeep;
}
int totalChar = countLength(wysiwyg, toot_cw_content); int totalChar = countLength(wysiwyg, toot_cw_content);
toot_space_left.setText(String.valueOf(totalChar)); toot_space_left.setText(String.valueOf(totalChar));
if (currentCursorPosition - (searchLength - 1) < 0 || currentCursorPosition == 0 || currentCursorPosition > s.toString().length()) if (currentCursorPosition - (searchLength - 1) < 0 || currentCursorPosition == 0 || currentCursorPosition > s.toString().length())
@ -1018,6 +1010,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
if (tootReply.getAccount() != null && tootReply.getAccount().getMoved_to_account() != null) { if (tootReply.getAccount() != null && tootReply.getAccount().getMoved_to_account() != null) {
warning_message.setVisibility(View.VISIBLE); warning_message.setVisibility(View.VISIBLE);
} }
assert tootReply.getAccount() != null;
new RetrieveRelationshipAsyncTask(TootActivity.this, tootReply.getAccount().getId(), TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new RetrieveRelationshipAsyncTask(TootActivity.this, tootReply.getAccount().getId(), TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
if (scheduledstatus != null) if (scheduledstatus != null)
@ -1329,15 +1322,18 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
final ImageView imageView = new ImageView(TootActivity.this); final ImageView imageView = new ImageView(TootActivity.this);
imageView.setId(Integer.parseInt(attachment.getId())); Random rand = new Random();
int n = rand.nextInt(10000000);
imageView.setId(n);
attachment.setViewId(n);
if (social == UpdateAccountInfoAsyncTask.SOCIAL.GNU || social == UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) { if (social == UpdateAccountInfoAsyncTask.SOCIAL.GNU || social == UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) {
if (successfullyUploadedFiles != null && successfullyUploadedFiles.size() > 0) { if (successfullyUploadedFiles != null && successfullyUploadedFiles.size() > 0) {
Iterator it = filesMap.entrySet().iterator(); Iterator<Map.Entry<String, Uri>> it = filesMap.entrySet().iterator();
Uri fileName = null; Uri fileName = null;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, Uri> pair = it.next();
fileName = (Uri) pair.getValue(); fileName = pair.getValue();
it.remove(); it.remove();
} }
if (fileName != null) { if (fileName != null) {
@ -1373,11 +1369,11 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
imageView.setImageBitmap(resource); imageView.setImageBitmap(resource);
if (displayWYSIWYG()) { if (displayWYSIWYG()) {
url_for_media = finalUrl; url_for_media = finalUrl;
Iterator it = filesMap.entrySet().iterator(); Iterator<Map.Entry<String, Uri>> it = filesMap.entrySet().iterator();
String fileName = null; String fileName = null;
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, Uri> pair = it.next();
fileName = (String) pair.getKey(); fileName = pair.getKey();
it.remove(); it.remove();
} }
if (fileName != null && fileName.contains("fedilabins_")) { if (fileName != null && fileName.contains("fedilabins_")) {
@ -2080,9 +2076,8 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
dialog.dismiss(); dialog.dismiss();
}); });
builderSingle1.setPositiveButton(R.string.server_schedule, (dialog, which) -> { builderSingle1.setPositiveButton(R.string.server_schedule, (dialog, which) -> {
int offset = TimeZone.getDefault().getRawOffset(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
calendar.add(Calendar.MILLISECOND, -offset); String date = sdf.format(calendar.getTime());
final String date = Helper.dateToString(new Date(calendar.getTimeInMillis()));
serverSchedule(date); serverSchedule(date);
}); });
builderSingle1.show(); builderSingle1.show();
@ -2367,7 +2362,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
//Text for report //Text for report
final EditText input = popup_media_description.findViewById(R.id.media_description); final EditText input = popup_media_description.findViewById(R.id.media_description);
input.setFilters(new InputFilter[]{new InputFilter.LengthFilter(420)}); input.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1500)});
final ImageView media_picture = popup_media_description.findViewById(R.id.media_picture); final ImageView media_picture = popup_media_description.findViewById(R.id.media_picture);
Glide.with(TootActivity.this) Glide.with(TootActivity.this)
.asBitmap() .asBitmap()
@ -2418,7 +2413,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
dialog.setPositiveButton(R.string.yes, (dialog12, which) -> { dialog.setPositiveButton(R.string.yes, (dialog12, which) -> {
View namebar = findViewById(viewId); View namebar = findViewById(viewId);
for (Attachment attachment : attachments) { for (Attachment attachment : attachments) {
if (Integer.parseInt(attachment.getId()) == viewId) { if (attachment.getViewId() == viewId) {
attachments.remove(attachment); attachments.remove(attachment);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
boolean show_media_urls = sharedpreferences.getBoolean(Helper.SET_MEDIA_URLS, false); boolean show_media_urls = sharedpreferences.getBoolean(Helper.SET_MEDIA_URLS, false);
@ -3176,10 +3171,12 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
toRemove.clear(); toRemove.clear();
} }
String content = status.getContent(); String content = status.getContent();
Pattern mentionLink = Pattern.compile("(<\\s?a\\s?href=\"https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[/\\w._-]*)\"\\s?[^.]*<\\s?/\\s?a\\s?>)"); if (content != null) {
Matcher matcher = mentionLink.matcher(content); Pattern mentionLink = Pattern.compile("(<\\s?a\\s?href=\"https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[/\\w._-]*)\"\\s?[^.]*<\\s?/\\s?a\\s?>)");
if (matcher.find()) { Matcher matcher = mentionLink.matcher(content);
content = matcher.replaceAll("$3@$2"); if (matcher.find()) {
content = matcher.replaceAll("$3@$2");
}
} }
if (removed) { if (removed) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
@ -3220,9 +3217,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
} }
}); });
imageView.setTag(attachment.getId()); imageView.setTag(attachment.getId());
imageView.setOnClickListener(view -> { imageView.setOnClickListener(view -> imageView.setOnClickListener(view1 -> showAddDescription(attachment)));
imageView.setOnClickListener(view1 -> showAddDescription(attachment));
});
imageView.setOnLongClickListener(view -> { imageView.setOnLongClickListener(view -> {
showRemove(imageView.getId()); showRemove(imageView.getId());
return false; return false;
@ -3245,7 +3240,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
toot_cw_content.setText(""); toot_cw_content.setText("");
toot_cw_content.setVisibility(View.GONE); toot_cw_content.setVisibility(View.GONE);
} }
if( status.getVisibility() == null) { if (status.getVisibility() == null) {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
String defaultVisibility = account.isLocked() ? "private" : "public"; String defaultVisibility = account.isLocked() ? "private" : "public";
String settingsVisibility = sharedpreferences.getString(Helper.SET_TOOT_VISIBILITY + "@" + account.getAcct() + "@" + account.getInstance(), defaultVisibility); String settingsVisibility = sharedpreferences.getString(Helper.SET_TOOT_VISIBILITY + "@" + account.getAcct() + "@" + account.getInstance(), defaultVisibility);
@ -3352,12 +3347,7 @@ public class TootActivity extends BaseActivity implements UploadStatusDelegate,
ownerTootVisibility = 1; ownerTootVisibility = 1;
break; break;
} }
int tootVisibility; int tootVisibility = Math.min(ownerTootVisibility, initialTootVisibility);
if (ownerTootVisibility >= initialTootVisibility) {
tootVisibility = initialTootVisibility;
} else {
tootVisibility = ownerTootVisibility;
}
switch (tootVisibility) { switch (tootVisibility) {
case 4: case 4:
visibility = "public"; visibility = "public";

View File

@ -126,9 +126,7 @@ public class WebviewConnectActivity extends BaseActivity {
clearCookies(WebviewConnectActivity.this); clearCookies(WebviewConnectActivity.this);
webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setJavaScriptEnabled(true);
String user_agent = sharedpreferences.getString(Helper.SET_CUSTOM_USER_AGENT, Helper.USER_AGENT); String user_agent = sharedpreferences.getString(Helper.SET_CUSTOM_USER_AGENT, Helper.USER_AGENT);
if (user_agent != null) { webView.getSettings().setUserAgentString(user_agent);
webView.getSettings().setUserAgentString(user_agent);
}
if (android.os.Build.VERSION.SDK_INT >= 21) { if (android.os.Build.VERSION.SDK_INT >= 21) {
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true); CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
} else { } else {

View File

@ -79,9 +79,6 @@ public class WhoToFollowActivity extends BaseActivity implements OnRetrieveWhoTo
case Helper.THEME_LIGHT: case Helper.THEME_LIGHT:
setTheme(R.style.AppTheme_NoActionBar_Fedilab); setTheme(R.style.AppTheme_NoActionBar_Fedilab);
break; break;
case Helper.THEME_DARK:
setTheme(R.style.AppThemeDark_NoActionBar);
break;
case Helper.THEME_BLACK: case Helper.THEME_BLACK:
setTheme(R.style.AppThemeBlack_NoActionBar); setTheme(R.style.AppThemeBlack_NoActionBar);
break; break;
@ -146,51 +143,41 @@ public class WhoToFollowActivity extends BaseActivity implements OnRetrieveWhoTo
} }
Button follow_accounts_select = findViewById(R.id.follow_accounts_select); Button follow_accounts_select = findViewById(R.id.follow_accounts_select);
follow_accounts_select.setOnClickListener(new View.OnClickListener() { follow_accounts_select.setOnClickListener(v -> {
@Override if (follow_accounts_select.getText().equals(getString(R.string.select_all))) {
public void onClick(View v) { follow_accounts_select.setText(R.string.unselect_all);
if (follow_accounts_select.getText().equals(getString(R.string.select_all))) { } else {
follow_accounts_select.setText(R.string.unselect_all); follow_accounts_select.setText(R.string.select_all);
for (TrunkAccount trunkAccount : trunkAccounts) {
trunkAccount.setChecked(true);
}
whoToFollowAccountsAdapter.notifyDataSetChanged();
} else {
follow_accounts_select.setText(R.string.select_all);
for (TrunkAccount trunkAccount : trunkAccounts) {
trunkAccount.setChecked(false);
}
whoToFollowAccountsAdapter.notifyDataSetChanged();
}
} }
for (TrunkAccount trunkAccount : trunkAccounts) {
trunkAccount.setChecked(false);
}
whoToFollowAccountsAdapter.notifyDataSetChanged();
}); });
Button follow_accounts = findViewById(R.id.follow_accounts); Button follow_accounts = findViewById(R.id.follow_accounts);
follow_accounts.setOnClickListener(new View.OnClickListener() { follow_accounts.setOnClickListener(v -> {
@Override follow_accounts.setEnabled(false);
public void onClick(View v) { follow_accounts_select.setEnabled(false);
follow_accounts.setEnabled(false); progess_action.setVisibility(View.VISIBLE);
follow_accounts_select.setEnabled(false); toFollowdId = new ArrayList<>();
progess_action.setVisibility(View.VISIBLE); for (TrunkAccount trunkAccount : trunkAccounts) {
toFollowdId = new ArrayList<>(); if (trunkAccount.isChecked()) {
for (TrunkAccount trunkAccount : trunkAccounts) { toFollowdId.add(trunkAccount.getAcct());
if (trunkAccount.isChecked()) {
toFollowdId.add(trunkAccount.getAcct());
}
} }
if (toFollowdId.size() > 0) { }
Account account = new Account(); if (toFollowdId.size() > 0) {
String[] val = toFollowdId.get(0).split("@"); Account account = new Account();
progess_action.setText(getString(R.string.follow_trunk, toFollowdId.get(0))); String[] val = toFollowdId.get(0).split("@");
if (val.length > 1) { progess_action.setText(getString(R.string.follow_trunk, toFollowdId.get(0)));
account.setAcct(val[0]); if (val.length > 1) {
account.setInstance(val[1]); account.setAcct(val[0]);
new PostActionAsyncTask(WhoToFollowActivity.this, null, account, API.StatusAction.FOLLOW, WhoToFollowActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); account.setInstance(val[1]);
} else { new PostActionAsyncTask(WhoToFollowActivity.this, null, account, API.StatusAction.FOLLOW, WhoToFollowActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Toasty.error(WhoToFollowActivity.this, getString(R.string.toast_impossible_to_follow), Toast.LENGTH_LONG).show(); } else {
follow_accounts.setEnabled(true); Toasty.error(WhoToFollowActivity.this, getString(R.string.toast_impossible_to_follow), Toast.LENGTH_LONG).show();
follow_accounts_select.setEnabled(true); follow_accounts.setEnabled(true);
progess_action.setVisibility(View.GONE); follow_accounts_select.setEnabled(true);
} progess_action.setVisibility(View.GONE);
} }
} }
}); });
@ -199,13 +186,11 @@ public class WhoToFollowActivity extends BaseActivity implements OnRetrieveWhoTo
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { if (item.getItemId() == android.R.id.home) {
case android.R.id.home: finish();
finish(); return true;
return true;
default:
return super.onOptionsItemSelected(item);
} }
return super.onOptionsItemSelected(item);
} }
@Override @Override
@ -237,6 +222,7 @@ public class WhoToFollowActivity extends BaseActivity implements OnRetrieveWhoTo
new ManageListsAsyncTask(WhoToFollowActivity.this, ManageListsAsyncTask.action.CREATE_LIST, null, null, null, item, WhoToFollowActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new ManageListsAsyncTask(WhoToFollowActivity.this, ManageListsAsyncTask.action.CREATE_LIST, null, null, null, item, WhoToFollowActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else { } else {
Account account = new Account(); Account account = new Account();
assert followedId != null;
String[] val = toFollowdId.get(followedId.size()).split("@"); String[] val = toFollowdId.get(followedId.size()).split("@");
progess_action.setText(getString(R.string.follow_trunk, toFollowdId.get(followedId.size()))); progess_action.setText(getString(R.string.follow_trunk, toFollowdId.get(followedId.size())));
if (val.length > 1) { if (val.length > 1) {
@ -253,7 +239,6 @@ public class WhoToFollowActivity extends BaseActivity implements OnRetrieveWhoTo
List<app.fedilab.android.client.Entities.List> lists = apiResponse.getLists(); List<app.fedilab.android.client.Entities.List> lists = apiResponse.getLists();
if (lists != null && lists.size() > 0 && actionType == ManageListsAsyncTask.action.CREATE_LIST) { if (lists != null && lists.size() > 0 && actionType == ManageListsAsyncTask.action.CREATE_LIST) {
String[] accountsId = followedId.toArray(new String[0]);
progess_action.setText(R.string.add_account_list_trunk); progess_action.setText(R.string.add_account_list_trunk);
listId = lists.get(0).getId(); listId = lists.get(0).getId();
listTitle = lists.get(0).getTitle(); listTitle = lists.get(0).getTitle();
@ -264,18 +249,14 @@ public class WhoToFollowActivity extends BaseActivity implements OnRetrieveWhoTo
if (accountListId.size() >= followedId.size() - 1) { if (accountListId.size() >= followedId.size() - 1) {
progess_action.setText(R.string.account_added_list_trunk); progess_action.setText(R.string.account_added_list_trunk);
Handler handler = new Handler(); Handler handler = new Handler();
handler.postDelayed(new Runnable() { handler.postDelayed(() -> {
@Override Intent intent = new Intent(WhoToFollowActivity.this, ListActivity.class);
public void run() { Bundle b = new Bundle();
Intent intent = new Intent(WhoToFollowActivity.this, ListActivity.class); b.putString("id", listId);
Bundle b = new Bundle(); b.putString("title", listTitle);
b.putString("id", listId); intent.putExtras(b);
b.putString("title", listTitle); startActivity(intent);
intent.putExtras(b); finish();
startActivity(intent);
finish();
}
}, 1000); }, 1000);
} else { } else {

View File

@ -35,9 +35,7 @@ import app.fedilab.android.interfaces.OnRetrieveContextInterface;
public class RetrieveContextAsyncTask extends AsyncTask<Void, Void, Void> { public class RetrieveContextAsyncTask extends AsyncTask<Void, Void, Void> {
private String statusId; private String statusId;
private app.fedilab.android.client.Entities.Context statusContext;
private OnRetrieveContextInterface listener; private OnRetrieveContextInterface listener;
private Error error;
private WeakReference<Context> contextReference; private WeakReference<Context> contextReference;
private boolean expanded; private boolean expanded;
private boolean directtimeline; private boolean directtimeline;
@ -55,6 +53,8 @@ public class RetrieveContextAsyncTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) { protected Void doInBackground(Void... params) {
apiResponse = new APIResponse(); apiResponse = new APIResponse();
apiResponse.setTargetedId(this.statusId); apiResponse.setTargetedId(this.statusId);
app.fedilab.android.client.Entities.Context statusContext;
Error error;
if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.GNU && MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) { if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.GNU && MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) {
API api = new API(this.contextReference.get()); API api = new API(this.contextReference.get());
statusContext = api.getStatusContext(statusId); statusContext = api.getStatusContext(statusId);
@ -63,7 +63,6 @@ public class RetrieveContextAsyncTask extends AsyncTask<Void, Void, Void> {
statusContext = api.getStatusContext(statusContext.getAncestors().get(0).getId()); statusContext = api.getStatusContext(statusContext.getAncestors().get(0).getId());
} }
error = api.getError(); error = api.getError();
apiResponse.setError(error);
} else { } else {
GNUAPI gnuapi = new GNUAPI(this.contextReference.get()); GNUAPI gnuapi = new GNUAPI(this.contextReference.get());
statusContext = gnuapi.getStatusContext(statusId, directtimeline); statusContext = gnuapi.getStatusContext(statusId, directtimeline);
@ -72,8 +71,8 @@ public class RetrieveContextAsyncTask extends AsyncTask<Void, Void, Void> {
statusContext = gnuapi.getStatusContext(statusContext.getAncestors().get(0).getId(), directtimeline); statusContext = gnuapi.getStatusContext(statusContext.getAncestors().get(0).getId(), directtimeline);
} }
error = gnuapi.getError(); error = gnuapi.getError();
apiResponse.setError(error);
} }
apiResponse.setError(error);
apiResponse.setContext(statusContext); apiResponse.setContext(statusContext);
return null; return null;
} }

View File

@ -25,13 +25,11 @@ import java.util.List;
import app.fedilab.android.activities.MainActivity; import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.client.API; import app.fedilab.android.client.API;
import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.APIResponse;
import app.fedilab.android.client.Entities.Account;
import app.fedilab.android.client.Entities.ManageTimelines; import app.fedilab.android.client.Entities.ManageTimelines;
import app.fedilab.android.client.Entities.Peertube; import app.fedilab.android.client.Entities.Peertube;
import app.fedilab.android.client.Entities.RemoteInstance; import app.fedilab.android.client.Entities.RemoteInstance;
import app.fedilab.android.client.Entities.Results; import app.fedilab.android.client.Entities.Results;
import app.fedilab.android.client.Entities.RetrieveFeedsParam; import app.fedilab.android.client.Entities.RetrieveFeedsParam;
import app.fedilab.android.client.Entities.Status;
import app.fedilab.android.client.GNUAPI; import app.fedilab.android.client.GNUAPI;
import app.fedilab.android.client.PeertubeAPI; import app.fedilab.android.client.PeertubeAPI;
import app.fedilab.android.helper.FilterToots; import app.fedilab.android.helper.FilterToots;
@ -369,13 +367,9 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<app.fedilab.android.client.Entities.Status> statuses = new StatusCacheDAO(contextReference.get(), db).getAllStatus(StatusCacheDAO.BOOKMARK_CACHE); List<app.fedilab.android.client.Entities.Status> statuses = new StatusCacheDAO(contextReference.get(), db).getAllStatus(StatusCacheDAO.BOOKMARK_CACHE);
if (statuses != null) { if (statuses != null) {
for (app.fedilab.android.client.Entities.Status status : statuses) { for (app.fedilab.android.client.Entities.Status status : statuses) {
app.fedilab.android.client.Entities.Status.fillSpan(contextReference, status); app.fedilab.android.client.Entities.Status.fillSpan(contextReference, status);
app.fedilab.android.client.Entities.Status.makeEmojiPoll(contextReference, status.getReblog() != null ? status.getReblog().getPoll() : status.getPoll());
Account.makeAccountNameEmoji(contextReference, status.getReblog() != null ? status.getReblog().getAccount() : status.getAccount());
if( status.getPoll() != null) {
app.fedilab.android.client.Entities.Status.makeEmojiPoll(contextReference, status.getPoll());
}
} }
} else { } else {
statuses = new ArrayList<>(); statuses = new ArrayList<>();
@ -393,6 +387,9 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
statuses = new StatusCacheDAO(contextReference.get(), db).getStatusFromID(StatusCacheDAO.ARCHIVE_CACHE, filterToots, max_id); statuses = new StatusCacheDAO(contextReference.get(), db).getStatusFromID(StatusCacheDAO.ARCHIVE_CACHE, filterToots, max_id);
if (statuses != null && statuses.size() > 0) { if (statuses != null && statuses.size() > 0) {
for (app.fedilab.android.client.Entities.Status status : statuses) {
app.fedilab.android.client.Entities.Status.fillSpan(contextReference, status);
}
apiResponse.setStatuses(statuses); apiResponse.setStatuses(statuses);
apiResponse.setSince_id(statuses.get(0).getId()); apiResponse.setSince_id(statuses.get(0).getId());
apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId()); apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId());
@ -423,10 +420,6 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
peertubeAPI = new PeertubeAPI(this.contextReference.get()); peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getLocalTL(max_id); apiResponse = peertubeAPI.getLocalTL(max_id);
break; break;
case PMYVIDEOS:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getLocalTL(max_id);
break;
case PF_HOME: case PF_HOME:
api = new API(this.contextReference.get()); api = new API(this.contextReference.get());
apiResponse = api.getHomeTimeline(max_id); apiResponse = api.getHomeTimeline(max_id);
@ -510,7 +503,6 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
POVERVIEW, POVERVIEW,
PTRENDING, PTRENDING,
PRECENTLYADDED, PRECENTLYADDED,
PMYVIDEOS,
PLOCAL, PLOCAL,
CHANNEL, CHANNEL,
MYVIDEOS, MYVIDEOS,

View File

@ -57,6 +57,11 @@ public class RetrieveNotificationsCacheAsyncTask extends AsyncTask<Void, Void, V
apiResponse = new APIResponse(); apiResponse = new APIResponse();
apiResponse.setNotifications(notifications); apiResponse.setNotifications(notifications);
if (notifications != null && notifications.size() > 0) { if (notifications != null && notifications.size() > 0) {
for (Notification notification : notifications) {
if (notification.getStatus() != null) {
app.fedilab.android.client.Entities.Status.fillSpan(contextReference, notification.getStatus());
}
}
apiResponse.setMax_id(notifications.get(notifications.size() - 1).getId()); apiResponse.setMax_id(notifications.get(notifications.size() - 1).getId());
} }
return null; return null;

File diff suppressed because it is too large Load Diff

View File

@ -78,7 +78,6 @@ public class APIResponse {
private Context context = null; private Context context = null;
private List<PixelFedStory> pixelFedStories = null; private List<PixelFedStory> pixelFedStories = null;
private List<PixelFedStoryItem> pixelFedStoryItems = null; private List<PixelFedStoryItem> pixelFedStoryItems = null;
private PixelFedStory pixelFedStory = null;
private List<Trends> trends = null; private List<Trends> trends = null;
private List<IdentityProof> identityProofs = null; private List<IdentityProof> identityProofs = null;

View File

@ -47,7 +47,6 @@ import com.bumptech.glide.request.transition.Transition;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
@ -200,63 +199,6 @@ public class Account implements Parcelable {
this.invited_by_account_id = in.readString(); this.invited_by_account_id = in.readString();
} }
public static void makeAccountNameEmoji(final WeakReference<Context> contextWeakReference, Account account) {
Context context = contextWeakReference.get();
if ((context instanceof Activity && ((Activity) context).isFinishing()) || account == null || account.getDisplay_name() == null)
return;
account.setDisplayNameSpan(new SpannableString(account.getDisplay_name()));
SpannableString displayNameSpan = account.getDisplayNameSpan();
if (displayNameSpan == null)
return;
final List<Emojis> emojis = account.getEmojis();
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean disableAnimatedEmoji = sharedpreferences.getBoolean(Helper.SET_DISABLE_ANIMATED_EMOJI, false);
if (emojis != null && emojis.size() > 0) {
final int[] i = {0};
for (final Emojis emoji : emojis) {
try {
Glide.with(context)
.asDrawable()
.load(disableAnimatedEmoji ? emoji.getStatic_url() : emoji.getUrl())
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
final String targetedEmoji = ":" + emoji.getShortcode() + ":";
if (displayNameSpan.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = displayNameSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if (resource != null && endPosition <= displayNameSpan.toString().length() && endPosition >= startPosition) {
try {
resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
ImageSpan imageSpan = new ImageSpan(resource);
displayNameSpan.setSpan(
imageSpan, startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
} catch (Exception ignored) {
}
return;
}
}
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override @Override
public int describeContents() { public int describeContents() {
@ -534,6 +476,9 @@ public class Account implements Parcelable {
} }
public SpannableString getDisplayNameSpan() { public SpannableString getDisplayNameSpan() {
if (this.displayNameSpan == null) {
displayNameSpan = new SpannableString(display_name);
}
return displayNameSpan; return displayNameSpan;
} }
@ -745,15 +690,14 @@ public class Account implements Parcelable {
return spannableString; return spannableString;
} }
public void makeEmojisAccountProfile(final Context context, final OnRetrieveEmojiAccountInterface listener, Account account) { public void fillProfileAccount(final Context context, final OnRetrieveEmojiAccountInterface listener, Account account) {
if (context instanceof Activity && ((Activity) context).isFinishing()) if (context instanceof Activity && ((Activity) context).isFinishing())
return; return;
if (fields == null) if (fields == null)
fields = new LinkedHashMap<>(); fields = new LinkedHashMap<>();
if (fieldsSpan == null) if (fieldsSpan == null)
fieldsSpan = new LinkedHashMap<>(); fieldsSpan = new LinkedHashMap<>();
if (account.getDisplay_name() != null) displayNameSpan = account.getDisplayNameSpan();
displayNameSpan = new SpannableString(account.getDisplay_name());
ArrayList<Account> accountsMentionUnknown = new ArrayList<>(); ArrayList<Account> accountsMentionUnknown = new ArrayList<>();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

View File

@ -37,6 +37,7 @@ public class Attachment implements Parcelable {
} }
}; };
private String id; private String id;
private int viewId;
private String type; private String type;
private String url; private String url;
private String remote_url; private String remote_url;
@ -50,8 +51,17 @@ public class Attachment implements Parcelable {
} }
public int getViewId() {
return viewId;
}
public void setViewId(int viewId) {
this.viewId = viewId;
}
protected Attachment(Parcel in) { protected Attachment(Parcel in) {
this.id = in.readString(); this.id = in.readString();
this.viewId = in.readInt();
this.type = in.readString(); this.type = in.readString();
this.url = in.readString(); this.url = in.readString();
this.remote_url = in.readString(); this.remote_url = in.readString();
@ -142,6 +152,7 @@ public class Attachment implements Parcelable {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id); dest.writeString(this.id);
dest.writeInt(this.viewId);
dest.writeString(this.type); dest.writeString(this.type);
dest.writeString(this.url); dest.writeString(this.url);
dest.writeString(this.remote_url); dest.writeString(this.remote_url);

View File

@ -74,6 +74,9 @@ public class PollOptions implements Parcelable {
} }
public SpannableString getTitleSpan() { public SpannableString getTitleSpan() {
if (titleSpan == null) {
titleSpan = new SpannableString(title);
}
return titleSpan; return titleSpan;
} }

View File

@ -52,11 +52,7 @@ import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition; import com.bumptech.glide.request.transition.Transition;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@ -88,7 +84,6 @@ import app.fedilab.android.helper.CustomQuoteSpan;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.LongClickableSpan; import app.fedilab.android.helper.LongClickableSpan;
import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.helper.ThemeHelper;
import app.fedilab.android.interfaces.OnRetrieveEmojiInterface;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static android.content.Context.MODE_PRIVATE; import static android.content.Context.MODE_PRIVATE;
@ -267,7 +262,6 @@ public class Status implements Parcelable {
public static void fillSpan(WeakReference<Context> contextWeakReference, Status status) { public static void fillSpan(WeakReference<Context> contextWeakReference, Status status) {
Status.transform(contextWeakReference, status); Status.transform(contextWeakReference, status);
Status.makeEmojis(contextWeakReference, status);
Status.makeImage(contextWeakReference, status); Status.makeImage(contextWeakReference, status);
} }
@ -502,11 +496,11 @@ public class Status implements Parcelable {
} }
} }
SpannableString spannableStringT; SpannableStringBuilder spannableStringT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
spannableStringT = new SpannableString(Html.fromHtml(spannableString.toString().replaceAll("[\\s]{2}", "&nbsp;&nbsp;"), Html.FROM_HTML_MODE_LEGACY)); spannableStringT = new SpannableStringBuilder(Html.fromHtml(spannableString.toString().replaceAll("[\\s]{2}", "&nbsp;&nbsp;"), Html.FROM_HTML_MODE_LEGACY));
else else
spannableStringT = new SpannableString(Html.fromHtml(spannableString.toString().replaceAll("[\\s]{2}", "&nbsp;&nbsp;"))); spannableStringT = new SpannableStringBuilder(Html.fromHtml(spannableString.toString().replaceAll("[\\s]{2}", "&nbsp;&nbsp;")));
replaceQuoteSpans(context, spannableStringT); replaceQuoteSpans(context, spannableStringT);
URLSpan[] spans = spannableStringT.getSpans(0, spannableStringT.length(), URLSpan.class); URLSpan[] spans = spannableStringT.getSpans(0, spannableStringT.length(), URLSpan.class);
for (URLSpan span : spans) { for (URLSpan span : spans) {
@ -557,7 +551,7 @@ public class Status implements Parcelable {
Iterator<Map.Entry<String, Account>> it = accountsMentionUnknown.entrySet().iterator(); Iterator<Map.Entry<String, Account>> it = accountsMentionUnknown.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry<String, Account> pair = it.next(); Map.Entry<String, Account> pair = it.next();
String key = pair.getKey(); String key = pair.getKey();
Account account = pair.getValue(); Account account = pair.getValue();
String targetedAccount = "@" + account.getAcct(); String targetedAccount = "@" + account.getAcct();
if (spannableStringT.toString().toLowerCase().contains(targetedAccount.toLowerCase())) { if (spannableStringT.toString().toLowerCase().contains(targetedAccount.toLowerCase())) {
@ -571,7 +565,7 @@ public class Status implements Parcelable {
if (ssb.length() >= endPosition) { if (ssb.length() >= endPosition) {
ssb.replace(startPosition, endPosition, key); ssb.replace(startPosition, endPosition, key);
} }
spannableStringT = SpannableString.valueOf(ssb); spannableStringT = SpannableStringBuilder.valueOf(ssb);
endPosition = startPosition + key.length(); endPosition = startPosition + key.length();
} }
//Accounts can be mentioned several times so we have to loop //Accounts can be mentioned several times so we have to loop
@ -622,7 +616,7 @@ public class Status implements Parcelable {
if (ssb.length() >= endPosition) { if (ssb.length() >= endPosition) {
ssb.replace(startPosition, endPosition, key); ssb.replace(startPosition, endPosition, key);
} }
spannableStringT = SpannableString.valueOf(ssb); spannableStringT = SpannableStringBuilder.valueOf(ssb);
endPosition = startPosition + key.length(); endPosition = startPosition + key.length();
} }
if (endPosition <= spannableStringT.toString().length() && endPosition >= startPosition) { if (endPosition <= spannableStringT.toString().length() && endPosition >= startPosition) {
@ -841,7 +835,17 @@ public class Status implements Parcelable {
} }
} }
return spannableStringT;
Pattern carriagePattern = Pattern.compile("(\\n)+$");
matcher = carriagePattern.matcher(spannableStringT);
while (matcher.find()) {
int matchStart = matcher.start();
int matchEnd = matcher.end();
if (matchStart >= 0 && matchEnd <= spannableStringT.toString().length() && matchEnd >= matchStart) {
spannableStringT.delete(matchStart, matchEnd);
}
}
return SpannableString.valueOf(spannableStringT);
} }
public static void transformTranslation(Context context, Status status) { public static void transformTranslation(Context context, Status status) {
@ -895,148 +899,6 @@ public class Status implements Parcelable {
status.setContentSpanTranslated(contentSpanTranslated); status.setContentSpanTranslated(contentSpanTranslated);
} }
private static void makeEmojis(final WeakReference<Context> contextWeakReference, Status status) {
Context context = contextWeakReference.get();
if (context instanceof Activity && ((Activity) context).isFinishing())
return;
if (status.getReblog() != null && status.getReblog().getEmojis() == null)
return;
if (status.getReblog() == null && status.getEmojis() == null)
return;
final List<Emojis> emojis = status.getReblog() != null ? status.getReblog().getEmojis() : status.getEmojis();
SpannableString contentSpan = status.getContentSpan();
SpannableString contentSpanCW = status.getContentSpanCW();
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean disableAnimatedEmoji = sharedpreferences.getBoolean(Helper.SET_DISABLE_ANIMATED_EMOJI, false);
if (emojis != null && emojis.size() > 0) {
final int[] i = {0};
for (final Emojis emoji : emojis) {
Glide.with(context)
.asDrawable()
.load(disableAnimatedEmoji ? emoji.getStatic_url() : emoji.getUrl())
.listener(new RequestListener<Drawable>() {
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
return false;
}
})
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
final String targetedEmoji = ":" + emoji.getShortcode() + ":";
if (contentSpan != null && contentSpan.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = contentSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if (resource != null && endPosition <= contentSpan.toString().length() && endPosition >= startPosition) {
ImageSpan imageSpan;
try {
resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
imageSpan = new ImageSpan(resource);
contentSpan.setSpan(
imageSpan, startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
} catch (Exception ignored) {
}
}
}
}
if (contentSpanCW != null && contentSpanCW.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = contentSpanCW.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if (endPosition <= contentSpanCW.toString().length() && endPosition >= startPosition) {
ImageSpan imageSpan;
resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
imageSpan = new ImageSpan(resource);
contentSpanCW.setSpan(
imageSpan, startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
}
}
public static void makeEmojiPoll(final WeakReference<Context> contextWeakReference, Poll poll) {
Context context = contextWeakReference.get();
if ((context instanceof Activity && ((Activity) context).isFinishing()) || poll == null || poll.getOptionsList() == null)
return;
final List<Emojis> emojis = poll.getEmojis();
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean disableAnimatedEmoji = sharedpreferences.getBoolean(Helper.SET_DISABLE_ANIMATED_EMOJI, false);
int inc = 0;
for (PollOptions pollOption : poll.getOptionsList()) {
inc++;
SpannableString titleSpan = new SpannableString(pollOption.getTitle());
if (emojis != null && emojis.size() > 0) {
final int[] i = {0};
for (final Emojis emoji : emojis) {
Glide.with(context)
.asDrawable()
.load(disableAnimatedEmoji ? emoji.getStatic_url() : emoji.getUrl())
.listener(new RequestListener<Drawable>() {
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
return false;
}
})
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
final String targetedEmoji = ":" + emoji.getShortcode() + ":";
if (titleSpan.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = titleSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if (endPosition <= titleSpan.toString().length() && endPosition >= startPosition) {
ImageSpan imageSpan;
resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
imageSpan = new ImageSpan(resource);
titleSpan.setSpan(
imageSpan, startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
pollOption.setTitleSpan(titleSpan);
}
}
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
}
}
}
private static void makeImage(final WeakReference<Context> contextWeakReference, Status status) { private static void makeImage(final WeakReference<Context> contextWeakReference, Status status) {
Context context = contextWeakReference.get(); Context context = contextWeakReference.get();
@ -1056,17 +918,6 @@ public class Status implements Parcelable {
Glide.with(context) Glide.with(context)
.asBitmap() .asBitmap()
.load(imgURL) .load(imgURL)
.listener(new RequestListener<Bitmap>() {
@Override
public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
return false;
}
})
.into(new CustomTarget<Bitmap>() { .into(new CustomTarget<Bitmap>() {
@Override @Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) { public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
@ -1101,79 +952,6 @@ public class Status implements Parcelable {
} }
public static void makeEmojisTranslation(final Context context, final OnRetrieveEmojiInterface listener, Status status) {
if (context instanceof Activity && ((Activity) context).isFinishing())
return;
SpannableString spannableStringTranslated = null;
if (status.getContentTranslated() != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated(), Html.FROM_HTML_MODE_LEGACY));
else
spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated()));
}
final List<Emojis> emojis = status.getReblog() != null ? status.getReblog().getEmojis() : status.getEmojis();
if (emojis != null && emojis.size() > 0) {
final int[] i = {0};
for (final Emojis emoji : emojis) {
final SpannableString finalSpannableStringTranslated = spannableStringTranslated;
Glide.with(context)
.asBitmap()
.load(emoji.getUrl())
.listener(new RequestListener<Bitmap>() {
@Override
public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
i[0]++;
if (i[0] == (emojis.size())) {
if (finalSpannableStringTranslated != null)
status.setContentSpanTranslated(finalSpannableStringTranslated);
listener.onRetrieveEmoji(status, true);
}
return false;
}
})
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
final String targetedEmoji = ":" + emoji.getShortcode() + ":";
if (finalSpannableStringTranslated != null && finalSpannableStringTranslated.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = finalSpannableStringTranslated.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if (endPosition <= finalSpannableStringTranslated.toString().length() && endPosition >= startPosition)
finalSpannableStringTranslated.setSpan(
new ImageSpan(context,
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(20, context),
(int) Helper.convertDpToPixel(20, context), false)), startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
i[0]++;
if (i[0] == (emojis.size())) {
if (finalSpannableStringTranslated != null)
status.setContentSpanTranslated(finalSpannableStringTranslated);
status.setEmojiTranslateFound(true);
listener.onRetrieveEmoji(status, true);
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
}
}
private static void replaceQuoteSpans(Context context, Spannable spannable) { private static void replaceQuoteSpans(Context context, Spannable spannable) {
QuoteSpan[] quoteSpans = spannable.getSpans(0, spannable.length(), QuoteSpan.class); QuoteSpan[] quoteSpans = spannable.getSpans(0, spannable.length(), QuoteSpan.class);
for (QuoteSpan quoteSpan : quoteSpans) { for (QuoteSpan quoteSpan : quoteSpans) {

View File

@ -212,14 +212,24 @@ public class GNUAPI {
return statuses; return statuses;
} }
/** /**
* Parse json response for unique status * Parse json response for unique status
* *
* @param resobj JSONObject * @param resobj JSONObject
* @return Status * @return Status
*/ */
@SuppressWarnings("InfiniteRecursion")
private static Status parseStatuses(Context context, JSONObject resobj) { private static Status parseStatuses(Context context, JSONObject resobj) {
return parseStatuses(context, resobj, true);
}
/**
* Parse json response for unique status
*
* @param resobj JSONObject
* @return Status
*/
private static Status parseStatuses(Context context, JSONObject resobj, boolean recursive) {
Status status = new Status(); Status status = new Status();
try { try {
status.setId(resobj.get("id").toString()); status.setId(resobj.get("id").toString());
@ -337,7 +347,9 @@ public class GNUAPI {
status.setMuted(false); status.setMuted(false);
status.setPinned(false); status.setPinned(false);
try { try {
status.setReblog(parseStatuses(context, resobj.getJSONObject("retweeted_status"))); if (recursive) {
status.setReblog(parseStatuses(context, resobj.getJSONObject("retweeted_status"), false));
}
} catch (Exception ignored) { } catch (Exception ignored) {
status.setReblog(null); status.setReblog(null);
} }
@ -1476,24 +1488,20 @@ public class GNUAPI {
case FAVOURITE: case FAVOURITE:
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU) { if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU) {
action = "/favorites/create.json"; action = "/favorites/create.json";
params = new HashMap<>();
params.put("id", targetedId);
} else { } else {
action = "/friendica/activity/like.json"; action = "/friendica/activity/like.json";
params = new HashMap<>();
params.put("id", targetedId);
} }
params = new HashMap<>();
params.put("id", targetedId);
break; break;
case UNFAVOURITE: case UNFAVOURITE:
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU) { if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU) {
action = "/favorites/destroy.json"; action = "/favorites/destroy.json";
params = new HashMap<>();
params.put("id", targetedId);
} else { } else {
action = "/friendica/activity/unlike.json"; action = "/friendica/activity/unlike.json";
params = new HashMap<>();
params.put("id", targetedId);
} }
params = new HashMap<>();
params.put("id", targetedId);
break; break;
case REBLOG: case REBLOG:
action = String.format("/statuses/retweet/%s.json", targetedId); action = String.format("/statuses/retweet/%s.json", targetedId);

View File

@ -11,6 +11,8 @@ import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule; import com.bumptech.glide.module.AppGlideModule;
import org.jetbrains.annotations.NotNull;
import java.io.InputStream; import java.io.InputStream;
/** /**
@ -27,7 +29,7 @@ public final class TLSLibraryGlideModule extends AppGlideModule {
} }
@Override @Override
public void applyOptions(Context context, GlideBuilder builder) { public void applyOptions(@NotNull Context context, @NotNull GlideBuilder builder) {
} }
} }

View File

@ -147,10 +147,10 @@ public class HttpsConnection {
Map<String, Object> params = new LinkedHashMap<>(); Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) { if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = paramaters.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
params.put(pair.getKey().toString(), pair.getValue()); params.put(pair.getKey(), pair.getValue());
it.remove(); it.remove();
} }
} }
@ -236,7 +236,7 @@ public class HttpsConnection {
httpsURLConnection.setInstanceFollowRedirects(false); httpsURLConnection.setInstanceFollowRedirects(false);
httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory(this.instance)); httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory(this.instance));
httpsURLConnection.setRequestMethod("HEAD"); httpsURLConnection.setRequestMethod("HEAD");
if (httpsURLConnection.getResponseCode() == 301) { if (httpsURLConnection.getResponseCode() == 301 || httpsURLConnection.getResponseCode() == 302) {
Map<String, List<String>> map = httpsURLConnection.getHeaderFields(); Map<String, List<String>> map = httpsURLConnection.getHeaderFields();
for (Map.Entry<String, List<String>> entry : map.entrySet()) { for (Map.Entry<String, List<String>> entry : map.entrySet()) {
if (entry.toString().toLowerCase().startsWith("location")) { if (entry.toString().toLowerCase().startsWith("location")) {
@ -362,25 +362,25 @@ public class HttpsConnection {
public String post(String urlConnection, int timeout, HashMap<String, String> paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { public String post(String urlConnection, int timeout, HashMap<String, String> paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator<Map.Entry<String, String>> it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
params.put(pair.getKey(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
if (urlConnection.startsWith("https://")) { if (urlConnection.startsWith("https://")) {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
else else
@ -429,25 +429,6 @@ public class HttpsConnection {
httpsURLConnection.getInputStream().close(); httpsURLConnection.getInputStream().close();
return response; return response;
} else { } else {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpURLConnection = (HttpURLConnection) url.openConnection(proxy); httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
else else
@ -499,10 +480,12 @@ public class HttpsConnection {
String postJson(String urlConnection, int timeout, JsonObject jsonObject, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { String postJson(String urlConnection, int timeout, JsonObject jsonObject, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
URL url = new URL(urlConnection);
byte[] postDataBytes;
postDataBytes = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
if (urlConnection.startsWith("https://")) { if (urlConnection.startsWith("https://")) {
URL url = new URL(urlConnection);
byte[] postDataBytes;
postDataBytes = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
else else
@ -553,9 +536,6 @@ public class HttpsConnection {
httpsURLConnection.getInputStream().close(); httpsURLConnection.getInputStream().close();
return response; return response;
} else { } else {
URL url = new URL(urlConnection);
byte[] postDataBytes = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpURLConnection = (HttpURLConnection) url.openConnection(proxy); httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
else else
@ -812,9 +792,15 @@ public class HttpsConnection {
public InputStream getPicture(final String downloadUrl) { public InputStream getPicture(final String downloadUrl) {
URL url;
try {
url = new URL(downloadUrl);
} catch (MalformedURLException e) {
return null;
}
if (downloadUrl.startsWith("https://")) { if (downloadUrl.startsWith("https://")) {
try { try {
URL url = new URL(downloadUrl);
if (proxy != null) if (proxy != null)
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
else else
@ -823,7 +809,7 @@ public class HttpsConnection {
httpsURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpsURLConnection.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = httpsURLConnection.getResponseCode(); int responseCode = httpsURLConnection.getResponseCode();
// always check HTTP response code first // always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) { if (responseCode >= 200 && responseCode < 400) {
// opens input stream from the HTTP connection // opens input stream from the HTTP connection
return httpsURLConnection.getInputStream(); return httpsURLConnection.getInputStream();
} }
@ -835,10 +821,8 @@ public class HttpsConnection {
httpsURLConnection.getInputStream().close(); httpsURLConnection.getInputStream().close();
} catch (Exception ignored) { } catch (Exception ignored) {
} }
return null;
} else { } else {
try { try {
URL url = new URL(downloadUrl);
if (proxy != null) if (proxy != null)
httpURLConnection = (HttpURLConnection) url.openConnection(proxy); httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
else else
@ -846,7 +830,7 @@ public class HttpsConnection {
httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = httpURLConnection.getResponseCode(); int responseCode = httpURLConnection.getResponseCode();
// always check HTTP response code first // always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) { if (responseCode >= 200 && responseCode < 400) {
// opens input stream from the HTTP connection // opens input stream from the HTTP connection
return httpURLConnection.getInputStream(); return httpURLConnection.getInputStream();
} }
@ -858,8 +842,8 @@ public class HttpsConnection {
httpURLConnection.getInputStream().close(); httpURLConnection.getInputStream().close();
} catch (Exception ignored) { } catch (Exception ignored) {
} }
return null;
} }
return null;
} }
private void uploadMedia(String urlConnection, InputStream avatar, InputStream header, String filename) { private void uploadMedia(String urlConnection, InputStream avatar, InputStream header, String filename) {
@ -923,27 +907,27 @@ public class HttpsConnection {
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
public String patch(String urlConnection, int timeout, HashMap<String, String> paramaters, InputStream avatar, String avatarName, InputStream header, String headerName, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { public String patch(String urlConnection, int timeout, HashMap<String, String> paramaters, InputStream avatar, String avatarName, InputStream header, String headerName, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator<Map.Entry<String, String>> it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
params.put(pair.getKey(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = (postData.toString()).getBytes(StandardCharsets.UTF_8);
if (urlConnection.startsWith("https://")) { if (urlConnection.startsWith("https://")) {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = (postData.toString()).getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
else else
@ -1006,25 +990,6 @@ public class HttpsConnection {
httpsURLConnection.getInputStream().close(); httpsURLConnection.getInputStream().close();
return response; return response;
} else { } else {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = (postData.toString()).getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); httpURLConnection = (HttpsURLConnection) url.openConnection(proxy);
else else
@ -1088,26 +1053,27 @@ public class HttpsConnection {
} }
public String put(String urlConnection, int timeout, HashMap<String, String> paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { public String put(String urlConnection, int timeout, HashMap<String, String> paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
if (urlConnection.startsWith("https://")) {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator<Map.Entry<String, String>> it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
params.put(pair.getKey(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
if (urlConnection.startsWith("https://")) {
if (proxy != null) if (proxy != null)
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
else else
@ -1157,25 +1123,6 @@ public class HttpsConnection {
httpsURLConnection.getInputStream().close(); httpsURLConnection.getInputStream().close();
return response; return response;
} else { } else {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpURLConnection = (HttpURLConnection) url.openConnection(proxy); httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
else else
@ -1228,26 +1175,27 @@ public class HttpsConnection {
} }
public int delete(String urlConnection, int timeout, HashMap<String, String> paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { public int delete(String urlConnection, int timeout, HashMap<String, String> paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
if (urlConnection.startsWith("https://")) {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator<Map.Entry<String, String>> it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
params.put(pair.getKey(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
if (urlConnection.startsWith("https://")) {
if (proxy != null) if (proxy != null)
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
else else
@ -1292,25 +1240,6 @@ public class HttpsConnection {
throw new HttpsConnectionException(responseCode, error); throw new HttpsConnectionException(responseCode, error);
} }
} else { } else {
URL url = new URL(urlConnection);
Map<String, Object> params = new LinkedHashMap<>();
if (paramaters != null) {
Iterator it = paramaters.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
params.put(pair.getKey().toString(), pair.getValue());
it.remove();
}
}
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());
}
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
if (proxy != null) if (proxy != null)
httpURLConnection = (HttpURLConnection) url.openConnection(proxy); httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
else else

View File

@ -40,7 +40,7 @@ import static android.content.Context.MODE_PRIVATE;
* Created by Thomas on 03/10/2019 * Created by Thomas on 03/10/2019
* Adapter for accounts and live notifications * Adapter for accounts and live notifications
*/ */
public class AccountLiveAdapter extends RecyclerView.Adapter { public class AccountLiveAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<Account> accounts; private List<Account> accounts;

View File

@ -47,6 +47,8 @@ import app.fedilab.android.helper.Helper;
import app.fedilab.android.interfaces.OnPostActionInterface; import app.fedilab.android.interfaces.OnPostActionInterface;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
* Created by Thomas on 03/09/2017. * Created by Thomas on 03/09/2017.
@ -125,6 +127,7 @@ public class AccountSearchDevAdapter extends BaseAdapter implements OnPostAction
} }
} else { } else {
holder.account_dn.setText(account.getDisplay_name()); holder.account_dn.setText(account.getDisplay_name());
makeEmojis(context, holder.account_dn, account.getDisplayNameSpan(), account.getEmojis());
holder.account_un.setText(account.getAcct()); holder.account_un.setText(account.getAcct());
holder.account_follow.hide(); holder.account_follow.hide();
} }

View File

@ -36,12 +36,14 @@ import app.fedilab.android.client.Entities.AccountAdmin;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.interfaces.OnRetrieveEmojiAccountInterface; import app.fedilab.android.interfaces.OnRetrieveEmojiAccountInterface;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
* Created by Thomas on 19/06/2019. * Created by Thomas on 19/06/2019.
* Adapter for account admins * Adapter for account admins
*/ */
public class AccountsAdminListAdapter extends RecyclerView.Adapter implements OnRetrieveEmojiAccountInterface { public class AccountsAdminListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnRetrieveEmojiAccountInterface {
private List<AccountAdmin> accountAdmins; private List<AccountAdmin> accountAdmins;
private Context context; private Context context;
@ -74,8 +76,11 @@ public class AccountsAdminListAdapter extends RecyclerView.Adapter implements On
else if (account.getDisplay_name() != null) { else if (account.getDisplay_name() != null) {
holder.account_dn.setText(account.getDisplay_name().replace("@", "")); holder.account_dn.setText(account.getDisplay_name().replace("@", ""));
} }
} else } else {
holder.account_dn.setText(account.getDisplayNameSpan(), TextView.BufferType.SPANNABLE); holder.account_dn.setText(account.getDisplayNameSpan(), TextView.BufferType.SPANNABLE);
makeEmojis(context, holder.account_dn, account.getDisplayNameSpan(), account.getEmojis());
}
if (account.getDisplayNameSpan() == null || account.getDisplayNameSpan().toString().trim().equals("")) { if (account.getDisplayNameSpan() == null || account.getDisplayNameSpan().toString().trim().equals("")) {
if (account.getDisplay_name() != null && !account.getDisplay_name().trim().equals("")) if (account.getDisplay_name() != null && !account.getDisplay_name().trim().equals(""))

View File

@ -50,12 +50,14 @@ import app.fedilab.android.helper.Helper;
import app.fedilab.android.interfaces.OnPostActionInterface; import app.fedilab.android.interfaces.OnPostActionInterface;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
* Created by Thomas on 07/05/2017. * Created by Thomas on 07/05/2017.
* Adapter for accounts asking a follow request * Adapter for accounts asking a follow request
*/ */
public class AccountsFollowRequestAdapter extends RecyclerView.Adapter implements OnPostActionInterface { public class AccountsFollowRequestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface {
private List<Account> accounts; private List<Account> accounts;
private Context context; private Context context;
@ -88,6 +90,7 @@ public class AccountsFollowRequestAdapter extends RecyclerView.Adapter implement
holder.btn_reject.setVisibility(View.GONE); holder.btn_reject.setVisibility(View.GONE);
} }
holder.account_dn.setText(account.getDisplay_name()); holder.account_dn.setText(account.getDisplay_name());
makeEmojis(context, holder.account_dn, account.getDisplayNameSpan(), account.getEmojis());
holder.account_un.setText(account.getAcct()); holder.account_un.setText(account.getAcct());
//Profile picture //Profile picture
Glide.with(holder.account_pp.getContext()) Glide.with(holder.account_pp.getContext())

View File

@ -45,12 +45,14 @@ import app.fedilab.android.helper.Helper;
import app.fedilab.android.interfaces.OnListActionInterface; import app.fedilab.android.interfaces.OnListActionInterface;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
* Created by Thomas on 15/12/2017. * Created by Thomas on 15/12/2017.
* Adapter for accounts in lists * Adapter for accounts in lists
*/ */
public class AccountsInAListAdapter extends RecyclerView.Adapter implements OnListActionInterface { public class AccountsInAListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnListActionInterface {
private List<Account> accounts; private List<Account> accounts;
private Context context; private Context context;
@ -90,6 +92,7 @@ public class AccountsInAListAdapter extends RecyclerView.Adapter implements OnLi
holder.account_un.setText(account.getDisplay_name()); holder.account_un.setText(account.getDisplay_name());
makeEmojis(context, holder.account_un, account.getDisplayNameSpan(), account.getEmojis());
holder.account_ac.setText(account.getAcct()); holder.account_ac.setText(account.getAcct());
if (account.getDisplay_name().equals(account.getAcct())) if (account.getDisplay_name().equals(account.getAcct()))
holder.account_ac.setVisibility(View.GONE); holder.account_ac.setVisibility(View.GONE);

View File

@ -60,24 +60,38 @@ import app.fedilab.android.sqlite.InstancesDAO;
import app.fedilab.android.sqlite.Sqlite; import app.fedilab.android.sqlite.Sqlite;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
* Created by Thomas on 27/04/2017. * Created by Thomas on 27/04/2017.
* Adapter for accounts * Adapter for accounts
*/ */
public class AccountsListAdapter extends RecyclerView.Adapter implements OnPostActionInterface, OnRetrieveEmojiAccountInterface { public class AccountsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface, OnRetrieveEmojiAccountInterface {
private List<Account> accounts; private List<Account> accounts;
private RetrieveAccountsAsyncTask.Type action; private RetrieveAccountsAsyncTask.Type action;
private Context context; private Context context;
private AccountsListAdapter accountsListAdapter; private AccountsListAdapter accountsListAdapter;
private String targetedId; private String targetedId;
private boolean crossAction;
public AccountsListAdapter(RetrieveAccountsAsyncTask.Type action, String targetedId, boolean crossAction, List<Account> accounts) {
this.accounts = accounts;
this.action = action;
this.accountsListAdapter = this;
this.targetedId = targetedId;
this.crossAction = crossAction;
}
public AccountsListAdapter(RetrieveAccountsAsyncTask.Type action, String targetedId, List<Account> accounts) { public AccountsListAdapter(RetrieveAccountsAsyncTask.Type action, String targetedId, List<Account> accounts) {
this.accounts = accounts; this.accounts = accounts;
this.action = action; this.action = action;
this.accountsListAdapter = this; this.accountsListAdapter = this;
this.targetedId = targetedId; this.targetedId = targetedId;
crossAction = false;
} }
@ -172,8 +186,10 @@ public class AccountsListAdapter extends RecyclerView.Adapter implements OnPostA
holder.account_dn.setText(account.getDisplay_name()); holder.account_dn.setText(account.getDisplay_name());
else else
holder.account_dn.setText(account.getUsername().replace("@", "")); holder.account_dn.setText(account.getUsername().replace("@", ""));
} else } else {
holder.account_dn.setText(account.getDisplayNameSpan(), TextView.BufferType.SPANNABLE); holder.account_dn.setText(account.getDisplayNameSpan(), TextView.BufferType.SPANNABLE);
makeEmojis(context, holder.account_dn, account.getDisplayNameSpan(), account.getEmojis());
}
holder.account_un.setText(String.format("@%s", account.getUsername())); holder.account_un.setText(String.format("@%s", account.getUsername()));
holder.account_ac.setText(account.getAcct()); holder.account_ac.setText(account.getAcct());
if (account.getUsername().equals(account.getAcct())) if (account.getUsername().equals(account.getAcct()))
@ -239,7 +255,7 @@ public class AccountsListAdapter extends RecyclerView.Adapter implements OnPostA
}); });
if (action != RetrieveAccountsAsyncTask.Type.GROUPS) { if (action != RetrieveAccountsAsyncTask.Type.GROUPS) {
holder.account_pp.setOnClickListener(v -> { holder.account_pp.setOnClickListener(v -> {
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE || action != RetrieveAccountsAsyncTask.Type.CHANNELS) { if (!crossAction && (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE || action != RetrieveAccountsAsyncTask.Type.CHANNELS)) {
//Avoid to reopen details about the current account //Avoid to reopen details about the current account
if (targetedId == null || !targetedId.equals(account.getId())) { if (targetedId == null || !targetedId.equals(account.getId())) {
Intent intent = new Intent(context, ShowAccountActivity.class); Intent intent = new Intent(context, ShowAccountActivity.class);

View File

@ -15,6 +15,7 @@ package app.fedilab.android.drawers;
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -30,6 +31,7 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.ActivityOptionsCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
@ -58,13 +60,14 @@ import app.fedilab.android.sqlite.StatusCacheDAO;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static android.content.Context.MODE_PRIVATE; import static android.content.Context.MODE_PRIVATE;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
* Created by Thomas on 14/01/2019. * Created by Thomas on 14/01/2019.
* Adapter for art drawer * Adapter for art drawer
*/ */
public class ArtListAdapter extends RecyclerView.Adapter implements OnPostActionInterface, OnRetrieveEmojiInterface, OnRetrieveRepliesInterface { public class ArtListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface, OnRetrieveEmojiInterface, OnRetrieveRepliesInterface {
private static final int DISPLAYED_STATUS = 1; private static final int DISPLAYED_STATUS = 1;
private final int HIDDEN_STATUS = 0; private final int HIDDEN_STATUS = 0;
@ -176,7 +179,16 @@ public class ArtListAdapter extends RecyclerView.Adapter implements OnPostAction
b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark));
b.putInt("position", 1); b.putInt("position", 1);
intent.putExtras(b); intent.putExtras(b);
context.startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, holder.art_media, status.getMedia_attachments().get(0).getUrl());
// start the new activity
context.startActivity(intent, options.toBundle());
} else {
// start the new activity
context.startActivity(intent);
}
}); });
holder.art_author.setOnClickListener(v -> { holder.art_author.setOnClickListener(v -> {
Intent intent = new Intent(context, ShowConversationActivity.class); Intent intent = new Intent(context, ShowConversationActivity.class);
@ -186,9 +198,10 @@ public class ArtListAdapter extends RecyclerView.Adapter implements OnPostAction
context.startActivity(intent); context.startActivity(intent);
}); });
if (status.getAccount().getDisplayNameSpan() != null && status.getAccount().getDisplayNameSpan().toString().trim().length() > 0) if (status.getAccount().getDisplayNameSpan() != null && status.getAccount().getDisplayNameSpan().toString().trim().length() > 0) {
holder.art_username.setText(status.getAccount().getDisplayNameSpan(), TextView.BufferType.SPANNABLE); holder.art_username.setText(status.getAccount().getDisplayNameSpan(), TextView.BufferType.SPANNABLE);
else makeEmojis(context, holder.art_username, status.getAccount().getDisplayNameSpan(), status.getAccount().getEmojis());
} else
holder.art_username.setText(status.getAccount().getUsername()); holder.art_username.setText(status.getAccount().getUsername());
holder.art_acct.setText(String.format("@%s", status.getAccount().getAcct())); holder.art_acct.setText(String.format("@%s", status.getAccount().getAcct()));

View File

@ -88,7 +88,9 @@ public class CustomEmojiAdapter extends BaseAdapter {
@Override @Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) { public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
emoji.setDrawable(resource); emoji.setDrawable(resource);
imageView.setImageDrawable(emoji.getDrawable()); if (imageView != null && emoji.getDrawable() != null) {
imageView.setImageDrawable(emoji.getDrawable());
}
} }
@Override @Override

View File

@ -43,7 +43,7 @@ import es.dmoral.toasty.Toasty;
* Created by Thomas on 26/09/2018. * Created by Thomas on 26/09/2018.
* Adapter for domains * Adapter for domains
*/ */
public class DomainsListAdapter extends RecyclerView.Adapter implements OnRetrieveDomainsInterface { public class DomainsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnRetrieveDomainsInterface {
private List<String> domains; private List<String> domains;
private Context context; private Context context;

View File

@ -35,7 +35,7 @@ import app.fedilab.android.helper.Helper;
* Created by Thomas on 19/12/2019. * Created by Thomas on 19/12/2019.
* Adapter for identity proofs * Adapter for identity proofs
*/ */
public class IdentityProofsAdapter extends RecyclerView.Adapter { public class IdentityProofsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<IdentityProof> identityProofs; private List<IdentityProof> identityProofs;

View File

@ -14,6 +14,7 @@ package app.fedilab.android.drawers;
* You should have received a copy of the GNU General Public License along with Fedilab; if not, * You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
@ -23,6 +24,7 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.ActivityOptionsCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
@ -43,7 +45,7 @@ import app.fedilab.android.client.Entities.Status;
* Adapter to display media related to status * Adapter to display media related to status
*/ */
public class ImageAdapter extends RecyclerView.Adapter { public class ImageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<Status> statuses; private List<Status> statuses;
@ -86,7 +88,15 @@ public class ImageAdapter extends RecyclerView.Adapter {
b.putInt("position", (viewHolder.getAdapterPosition() + 1)); b.putInt("position", (viewHolder.getAdapterPosition() + 1));
b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark));
intent.putExtras(b); intent.putExtras(b);
context.startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, holder.imageView, attachmentsTmp.get((viewHolder.getAdapterPosition())).getUrl());
// start the new activity
context.startActivity(intent, options.toBundle());
} else {
// start the new activity
context.startActivity(intent);
}
}); });
holder.imageView.setOnLongClickListener(v -> { holder.imageView.setOnLongClickListener(v -> {
Intent intent = new Intent(context, ShowConversationActivity.class); Intent intent = new Intent(context, ShowConversationActivity.class);

View File

@ -37,7 +37,7 @@ import app.fedilab.android.helper.Helper;
* Adapter to display instances * Adapter to display instances
*/ */
public class InstancePeertubeRegAdapter extends RecyclerView.Adapter { public class InstancePeertubeRegAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<InstanceReg> instanceRegs; private List<InstanceReg> instanceRegs;
private LayoutInflater layoutInflater; private LayoutInflater layoutInflater;

View File

@ -43,7 +43,7 @@ import app.fedilab.android.helper.Helper;
* Adapter to display instances * Adapter to display instances
*/ */
public class InstanceRegAdapter extends RecyclerView.Adapter { public class InstanceRegAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<InstanceReg> instanceRegs; private List<InstanceReg> instanceRegs;
private LayoutInflater layoutInflater; private LayoutInflater layoutInflater;

View File

@ -30,7 +30,10 @@ import android.os.Bundle;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.Handler; import android.os.Handler;
import android.text.Html; import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -53,6 +56,7 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.graphics.drawable.DrawableCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -70,6 +74,8 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import app.fedilab.android.R; import app.fedilab.android.R;
import app.fedilab.android.activities.AccountReportActivity; import app.fedilab.android.activities.AccountReportActivity;
@ -111,6 +117,7 @@ import es.dmoral.toasty.Toasty;
import static android.content.Context.MODE_PRIVATE; import static android.content.Context.MODE_PRIVATE;
import static app.fedilab.android.activities.BaseMainActivity.social; import static app.fedilab.android.activities.BaseMainActivity.social;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
@ -118,7 +125,7 @@ import static app.fedilab.android.activities.BaseMainActivity.social;
* Adapter for Status * Adapter for Status
*/ */
public class NotificationsListAdapter extends RecyclerView.Adapter implements OnPostActionInterface, OnPostNotificationsActionInterface, OnRetrieveEmojiInterface, OnRetrieveEmojiAccountInterface, OnPollInterface, OnRetrieveImageInterface { public class NotificationsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface, OnPostNotificationsActionInterface, OnRetrieveEmojiInterface, OnRetrieveEmojiAccountInterface, OnPollInterface, OnRetrieveImageInterface {
private final Object lock = new Object(); private final Object lock = new Object();
private Context context; private Context context;
@ -261,7 +268,7 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
else else
typeString = String.format("@%s %s", notification.getAccount().getUsername(), context.getString(R.string.notif_mention)); typeString = String.format("@%s %s", notification.getAccount().getUsername(), context.getString(R.string.notif_mention));
imgH = ContextCompat.getDrawable(context, R.drawable.ic_chat_bubble_outline); imgH = ContextCompat.getDrawable(context, R.drawable.ic_chat_bubble_outline);
if (notification.getStatus().getVisibility().equals("direct")) { if (notification.getStatus() != null && notification.getStatus().getVisibility().equals("direct")) {
holder.main_container_trans.setVisibility(View.GONE); holder.main_container_trans.setVisibility(View.GONE);
} else { } else {
holder.main_container_trans.setVisibility(View.VISIBLE); holder.main_container_trans.setVisibility(View.VISIBLE);
@ -322,8 +329,10 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
if (notification.getAccount().getDisplayNameSpan() == null) { if (notification.getAccount().getDisplayNameSpan() == null) {
holder.notification_type.setText(typeString); holder.notification_type.setText(typeString);
notification.getAccount().setStored_displayname(notification.getAccount().getDisplay_name()); notification.getAccount().setStored_displayname(notification.getAccount().getDisplay_name());
} else } else {
holder.notification_type.setText(notification.getAccount().getDisplayNameSpan(), TextView.BufferType.SPANNABLE); holder.notification_type.setText(typeString, TextView.BufferType.SPANNABLE);
makeEmojis(context, holder.notification_type, notification.getAccount().getDisplayNameSpan(), notification.getAccount().getEmojis());
}
if (imgH != null) { if (imgH != null) {
DrawableCompat.setTint(imgH, ContextCompat.getColor(context, R.color.cyanea_accent)); DrawableCompat.setTint(imgH, ContextCompat.getColor(context, R.color.cyanea_accent));
@ -376,6 +385,7 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
holder.status_privacy.setContentDescription(context.getString(R.string.toot_visibility_tilte) + ": " + v); holder.status_privacy.setContentDescription(context.getString(R.string.toot_visibility_tilte) + ": " + v);
}); });
holder.notification_status_content.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE); holder.notification_status_content.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE);
makeEmojis(context, holder.notification_status_content, status.getContentSpan(), status.getEmojis());
holder.status_spoiler.setText(status.getContentSpanCW(), TextView.BufferType.SPANNABLE); holder.status_spoiler.setText(status.getContentSpanCW(), TextView.BufferType.SPANNABLE);
holder.status_spoiler.setMovementMethod(LinkMovementMethod.getInstance()); holder.status_spoiler.setMovementMethod(LinkMovementMethod.getInstance());
holder.notification_status_content.setMovementMethod(LinkMovementMethod.getInstance()); holder.notification_status_content.setMovementMethod(LinkMovementMethod.getInstance());
@ -539,8 +549,9 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
TextView poll_item_percent = item.findViewById(R.id.poll_item_percent); TextView poll_item_percent = item.findViewById(R.id.poll_item_percent);
TextView poll_item_text = item.findViewById(R.id.poll_item_text); TextView poll_item_text = item.findViewById(R.id.poll_item_text);
ProgressBar poll_item_value = item.findViewById(R.id.poll_item_value); ProgressBar poll_item_value = item.findViewById(R.id.poll_item_value);
poll_item_percent.setText(String.format("%s %%", String.valueOf((int) value))); poll_item_percent.setText(String.format("%s %%", (int) value));
poll_item_text.setText(pollOption.getTitle(), TextView.BufferType.SPANNABLE); poll_item_text.setText(pollOption.getTitle(), TextView.BufferType.SPANNABLE);
makeEmojis(context, poll_item_text, pollOption.getTitleSpan(), poll.getEmojis());
poll_item_value.setProgress((int) value); poll_item_value.setProgress((int) value);
holder.rated.addView(item); holder.rated.addView(item);
if (pollOption.getVotes_count() == greaterValue) { if (pollOption.getVotes_count() == greaterValue) {
@ -564,6 +575,7 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
for (PollOptions pollOption : poll.getOptionsList()) { for (PollOptions pollOption : poll.getOptionsList()) {
CheckBox cb = new CheckBox(context); CheckBox cb = new CheckBox(context);
cb.setText(pollOption.getTitle()); cb.setText(pollOption.getTitle());
makeEmojis(context, cb, pollOption.getTitleSpan(), poll.getEmojis());
holder.multiple_choice.addView(cb); holder.multiple_choice.addView(cb);
} }
holder.multiple_choice.setVisibility(View.VISIBLE); holder.multiple_choice.setVisibility(View.VISIBLE);
@ -573,6 +585,7 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
for (PollOptions pollOption : poll.getOptionsList()) { for (PollOptions pollOption : poll.getOptionsList()) {
RadioButton rb = new RadioButton(context); RadioButton rb = new RadioButton(context);
rb.setText(pollOption.getTitle()); rb.setText(pollOption.getTitle());
makeEmojis(context, rb, pollOption.getTitleSpan(), poll.getEmojis());
holder.radio_group.addView(rb); holder.radio_group.addView(rb);
} }
holder.single_choice.setVisibility(View.VISIBLE); holder.single_choice.setVisibility(View.VISIBLE);
@ -742,7 +755,27 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
holder.notification_delete.setOnClickListener(v -> displayConfirmationNotificationDialog(notification)); holder.notification_delete.setOnClickListener(v -> displayConfirmationNotificationDialog(notification));
holder.notification_account_username.setVisibility(View.GONE);
if (notification.getAccount() != null) {
SpannableString wordtoSpan = new SpannableString("@" + notification.getAccount().getAcct());
Pattern hashAcct = Pattern.compile("(@" + notification.getAccount().getAcct() + ")");
int theme_text_header_2_line = prefs.getInt("theme_text_header_2_line", -1);
if (theme_text_header_2_line == -1) {
theme_text_header_2_line = ThemeHelper.getAttColor(context, R.attr.textHeader);
}
Matcher matcherAcct = hashAcct.matcher(wordtoSpan);
while (matcherAcct.find()) {
int matchStart = matcherAcct.start(1);
int matchEnd = matcherAcct.end();
if (wordtoSpan.length() >= matchEnd && matchStart < matchEnd) {
wordtoSpan.setSpan(new ForegroundColorSpan(theme_text_header_2_line), matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
holder.notification_account_username.setText(wordtoSpan);
}
final String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); final String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
final View attached = holder.status_more; final View attached = holder.status_more;
@ -1046,13 +1079,12 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
* @param notification Notification * @param notification Notification
*/ */
private void displayConfirmationNotificationDialog(final Notification notification) { private void displayConfirmationNotificationDialog(final Notification notification) {
final ArrayList seletedItems = new ArrayList(); final ArrayList<Integer> seletedItems = new ArrayList<>();
AlertDialog dialog = new AlertDialog.Builder(context, style) AlertDialog dialog = new AlertDialog.Builder(context, style)
.setTitle(R.string.delete_notification_ask) .setTitle(R.string.delete_notification_ask)
.setMultiChoiceItems(new String[]{context.getString(R.string.delete_notification_ask_all)}, null, (dialog1, indexSelected, isChecked) -> { .setMultiChoiceItems(new String[]{context.getString(R.string.delete_notification_ask_all)}, null, (dialog1, indexSelected, isChecked) -> {
if (isChecked) { if (isChecked) {
//noinspection unchecked
seletedItems.add(indexSelected); seletedItems.add(indexSelected);
} else { } else {
if (seletedItems.contains(indexSelected)) if (seletedItems.contains(indexSelected))
@ -1186,7 +1218,15 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
b.putInt("position", finalPosition); b.putInt("position", finalPosition);
b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark));
intent.putExtras(b); intent.putExtras(b);
context.startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, imageView, notification.getStatus().getMedia_attachments().get(finalPosition - 1).getUrl());
// start the new activity
context.startActivity(intent, options.toBundle());
} else {
// start the new activity
context.startActivity(intent);
}
}); });
i++; i++;
position++; position++;

View File

@ -55,7 +55,7 @@ import app.fedilab.android.interfaces.OnListActionInterface;
* Created by Thomas on 06/10/2018. * Created by Thomas on 06/10/2018.
* Adapter for peertube * Adapter for peertube
*/ */
public class PeertubeAdapter extends RecyclerView.Adapter implements OnListActionInterface { public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnListActionInterface {
private List<Peertube> peertubes; private List<Peertube> peertubes;
private Context context; private Context context;

View File

@ -48,7 +48,7 @@ import app.fedilab.android.helper.Helper;
* Adapter for Peertube notifications * Adapter for Peertube notifications
*/ */
public class PeertubeNotificationsListAdapter extends RecyclerView.Adapter { public class PeertubeNotificationsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<PeertubeNotification> notifications; private List<PeertubeNotification> notifications;

View File

@ -47,6 +47,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.cardview.widget.CardView; import androidx.cardview.widget.CardView;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityOptionsCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -120,7 +121,7 @@ import static app.fedilab.android.activities.BaseMainActivity.social;
* Created by Thomas on 14/01/2019. * Created by Thomas on 14/01/2019.
* Adapter for pixelfed drawer * Adapter for pixelfed drawer
*/ */
public class PixelfedListAdapter extends RecyclerView.Adapter implements OnPostActionInterface, OnRetrieveEmojiInterface, OnPostStatusActionInterface, OnRetrieveSearchInterface, OnRetrieveSearcAccountshInterface, OnRetrieveContextInterface, OnRetrieveFeedsInterface { public class PixelfedListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface, OnRetrieveEmojiInterface, OnPostStatusActionInterface, OnRetrieveSearchInterface, OnRetrieveSearcAccountshInterface, OnRetrieveContextInterface, OnRetrieveFeedsInterface {
private static final int DISPLAYED_STATUS = 1; private static final int DISPLAYED_STATUS = 1;
private final int HIDDEN_STATUS = 0; private final int HIDDEN_STATUS = 0;
@ -399,7 +400,15 @@ public class PixelfedListAdapter extends RecyclerView.Adapter implements OnPostA
b.putInt("position", 1); b.putInt("position", 1);
b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark));
intent.putExtras(b); intent.putExtras(b);
context.startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, holder.art_media, status.getMedia_attachments().get(0).getUrl());
// start the new activity
context.startActivity(intent, options.toBundle());
} else {
// start the new activity
context.startActivity(intent);
}
}); });
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
@ -511,12 +520,7 @@ public class PixelfedListAdapter extends RecyclerView.Adapter implements OnPostA
ownerTootVisibility = 1; ownerTootVisibility = 1;
break; break;
} }
int tootVisibility; int tootVisibility = Math.min(ownerTootVisibility, initialTootVisibility);
if (ownerTootVisibility >= initialTootVisibility) {
tootVisibility = initialTootVisibility;
} else {
tootVisibility = ownerTootVisibility;
}
switch (tootVisibility) { switch (tootVisibility) {
case 4: case 4:
visibility = "public"; visibility = "public";
@ -1063,7 +1067,7 @@ public class PixelfedListAdapter extends RecyclerView.Adapter implements OnPostA
status.setTranslationShown(true); status.setTranslationShown(true);
status.setContentTranslated(translate.getTranslatedContent()); status.setContentTranslated(translate.getTranslatedContent());
Status.transformTranslation(context, status); Status.transformTranslation(context, status);
Status.makeEmojisTranslation(context, PixelfedListAdapter.this, status); //makeEmojis(context, view, status.getContentSpan(), status.getReblog()!=null?status.getReblog().getEmojis():status.getEmojis());
notifyStatusChanged(status); notifyStatusChanged(status);
} else { } else {
Toasty.error(context, context.getString(R.string.toast_error_translate), Toast.LENGTH_LONG).show(); Toasty.error(context, context.getString(R.string.toast_error_translate), Toast.LENGTH_LONG).show();

View File

@ -28,6 +28,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView; import androidx.cardview.widget.CardView;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -56,7 +57,7 @@ import app.fedilab.android.helper.Helper;
* Created by Thomas on 02/11/2019. * Created by Thomas on 02/11/2019.
* Adapter for pixelfed stories drawer * Adapter for pixelfed stories drawer
*/ */
public class PixelfedStoriesListAdapter extends RecyclerView.Adapter { public class PixelfedStoriesListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int DISPLAYED_STATUS = 1; private static final int DISPLAYED_STATUS = 1;
private Context context; private Context context;
@ -136,7 +137,15 @@ public class PixelfedStoriesListAdapter extends RecyclerView.Adapter {
b.putInt("position", 1); b.putInt("position", 1);
b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark));
intent.putExtras(b); intent.putExtras(b);
context.startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, holder.art_media, attachments.get(0).getUrl());
// start the new activity
context.startActivity(intent, options.toBundle());
} else {
// start the new activity
context.startActivity(intent);
}
}); });

View File

@ -46,7 +46,7 @@ import app.fedilab.android.interfaces.OnPostActionInterface;
* Created by Thomas on 10/03/2020. * Created by Thomas on 10/03/2020.
* Adapter for reactions on messages * Adapter for reactions on messages
*/ */
public class ReactionAdapter extends RecyclerView.Adapter implements OnPostActionInterface { public class ReactionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface {
private List<Reaction> reactions; private List<Reaction> reactions;
private RetrieveFeedsAsyncTask.Type type; private RetrieveFeedsAsyncTask.Type type;

View File

@ -41,7 +41,7 @@ import app.fedilab.android.interfaces.OnRetrieveEmojiAccountInterface;
* Created by Thomas on 19/06/2019. * Created by Thomas on 19/06/2019.
* Adapter for reports * Adapter for reports
*/ */
public class ReportsListAdapter extends RecyclerView.Adapter implements OnRetrieveEmojiAccountInterface { public class ReportsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnRetrieveEmojiAccountInterface {
private List<Report> reports; private List<Report> reports;
private Context context; private Context context;

View File

@ -151,20 +151,21 @@ public class ScheduledTootsListAdapter extends BaseAdapter implements OnPostActi
Helper.changeDrawableColor(context, R.drawable.ic_mail_outline, R.color.action_light); Helper.changeDrawableColor(context, R.drawable.ic_mail_outline, R.color.action_light);
} }
switch (status.getVisibility()) { if (status.getVisibility() != null)
case "public": switch (status.getVisibility()) {
holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_public); case "public":
break; holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_public);
case "unlisted": break;
holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_lock_open); case "unlisted":
break; holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_lock_open);
case "private": break;
holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_lock_outline); case "private":
break; holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_lock_outline);
case "direct": break;
holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_mail_outline); case "direct":
break; holder.scheduled_toot_privacy.setImageResource(R.drawable.ic_mail_outline);
} break;
}
final SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); final SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
int style; int style;
if (theme == Helper.THEME_DARK) { if (theme == Helper.THEME_DARK) {
@ -374,7 +375,7 @@ public class ScheduledTootsListAdapter extends BaseAdapter implements OnPostActi
holder.scheduled_toot_container.setOnClickListener(v -> { holder.scheduled_toot_container.setOnClickListener(v -> {
Intent intentToot = new Intent(context, TootActivity.class); Intent intentToot = new Intent(context, TootActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
if (storedStatus.getStatus().getSpoiler_text().equals("null")) if (storedStatus.getStatus().getSpoiler_text() != null && storedStatus.getStatus().getSpoiler_text().equals("null"))
storedStatus.getStatus().setSpoiler_text(""); storedStatus.getStatus().setSpoiler_text("");
b.putParcelable("storedStatus", storedStatus); b.putParcelable("storedStatus", storedStatus);
intentToot.putExtras(b); intentToot.putExtras(b);

View File

@ -36,6 +36,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityOptionsCompat;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.target.CustomTarget;
@ -109,7 +110,15 @@ public class SliderAdapter extends SliderViewAdapter<SliderAdapter.SliderAdapter
b.putInt("position", (position + 1)); b.putInt("position", (position + 1));
b.putInt("bgcolor", contextWeakReference.get().getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", contextWeakReference.get().getResources().getColor(R.color.cyanea_primary_dark));
intent.putExtras(b); intent.putExtras(b);
contextWeakReference.get().startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) contextWeakReference.get(), viewHolder.imageViewBackground, attachments.get((position)).getUrl());
// start the new activity
contextWeakReference.get().startActivity(intent, options.toBundle());
} else {
// start the new activity
contextWeakReference.get().startActivity(intent);
}
}); });
} else { } else {
viewHolder.imageViewBackground.setOnClickListener(v -> showAddDescription(attachments.get(position))); viewHolder.imageViewBackground.setOnClickListener(v -> showAddDescription(attachments.get(position)));
@ -141,7 +150,7 @@ public class SliderAdapter extends SliderViewAdapter<SliderAdapter.SliderAdapter
//Text for report //Text for report
final EditText input = popup_media_description.findViewById(R.id.media_description); final EditText input = popup_media_description.findViewById(R.id.media_description);
input.setFilters(new InputFilter[]{new InputFilter.LengthFilter(420)}); input.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1500)});
final ImageView media_picture = popup_media_description.findViewById(R.id.media_picture); final ImageView media_picture = popup_media_description.findViewById(R.id.media_picture);
Glide.with(contextWeakReference.get()) Glide.with(contextWeakReference.get())
.asBitmap() .asBitmap()

View File

@ -51,8 +51,6 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
@ -78,6 +76,7 @@ import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.appcompat.widget.TooltipCompat; import androidx.appcompat.widget.TooltipCompat;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
@ -182,7 +181,6 @@ import app.fedilab.android.sqlite.StatusStoredDAO;
import app.fedilab.android.sqlite.TempMuteDAO; import app.fedilab.android.sqlite.TempMuteDAO;
import app.fedilab.android.sqlite.TimelineCacheDAO; import app.fedilab.android.sqlite.TimelineCacheDAO;
import app.fedilab.android.sqlite.TimelinesDAO; import app.fedilab.android.sqlite.TimelinesDAO;
import app.fedilab.android.webview.CustomWebview;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import jp.wasabeef.glide.transformations.BlurTransformation; import jp.wasabeef.glide.transformations.BlurTransformation;
@ -191,13 +189,15 @@ import static android.content.Context.MODE_PRIVATE;
import static app.fedilab.android.activities.BaseMainActivity.mPageReferenceMap; import static app.fedilab.android.activities.BaseMainActivity.mPageReferenceMap;
import static app.fedilab.android.activities.BaseMainActivity.mutedAccount; import static app.fedilab.android.activities.BaseMainActivity.mutedAccount;
import static app.fedilab.android.activities.BaseMainActivity.social; import static app.fedilab.android.activities.BaseMainActivity.social;
import static app.fedilab.android.asynctasks.RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE_FILTERED;
import static app.fedilab.android.helper.Helper.makeEmojis;
/** /**
* Created by Thomas on 24/04/2017. * Created by Thomas on 24/04/2017.
* Adapter for Status * Adapter for Status
*/ */
public class StatusListAdapter extends RecyclerView.Adapter implements OnPostActionInterface, OnRetrieveFeedsInterface, OnRetrieveImageInterface, OnRetrieveEmojiInterface, OnRetrieveRepliesInterface, OnRetrieveCardInterface, OnPollInterface, OnRefreshCachedStatusInterface, OnRetrieveSearcAccountshInterface, OnRetrieveSearchInterface, OnPostStatusActionInterface, OnRetrieveRelationshipQuickReplyInterface, OnSyncBookmarksInterface { public class StatusListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface, OnRetrieveFeedsInterface, OnRetrieveImageInterface, OnRetrieveEmojiInterface, OnRetrieveRepliesInterface, OnRetrieveCardInterface, OnPollInterface, OnRefreshCachedStatusInterface, OnRetrieveSearcAccountshInterface, OnRetrieveSearchInterface, OnPostStatusActionInterface, OnRetrieveRelationshipQuickReplyInterface, OnSyncBookmarksInterface {
public static final int DISPLAYED_STATUS = 1; public static final int DISPLAYED_STATUS = 1;
public static final int COMPACT_STATUS = 3; public static final int COMPACT_STATUS = 3;
@ -755,8 +755,10 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
TextView poll_item_percent = item.findViewById(R.id.poll_item_percent); TextView poll_item_percent = item.findViewById(R.id.poll_item_percent);
TextView poll_item_text = item.findViewById(R.id.poll_item_text); TextView poll_item_text = item.findViewById(R.id.poll_item_text);
ProgressBar poll_item_value = item.findViewById(R.id.poll_item_value); ProgressBar poll_item_value = item.findViewById(R.id.poll_item_value);
poll_item_percent.setText(String.format("%s %%", String.valueOf((int) value))); poll_item_percent.setText(String.format("%s %%", (int) value));
poll_item_text.setText(pollOption.getTitle(), TextView.BufferType.SPANNABLE); poll_item_text.setText(pollOption.getTitleSpan(), TextView.BufferType.SPANNABLE);
poll_item_text.setText(pollOption.getTitle());
makeEmojis(context, poll_item_text, pollOption.getTitleSpan(), poll.getEmojis());
poll_item_value.setProgress((int) value); poll_item_value.setProgress((int) value);
holder.rated.addView(item); holder.rated.addView(item);
if (pollOption.getVotes_count() == greaterValue) { if (pollOption.getVotes_count() == greaterValue) {
@ -780,11 +782,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
(holder.multiple_choice).removeAllViews(); (holder.multiple_choice).removeAllViews();
for (PollOptions pollOption : poll.getOptionsList()) { for (PollOptions pollOption : poll.getOptionsList()) {
CheckBox cb = new CheckBox(context); CheckBox cb = new CheckBox(context);
if (pollOption.getTitleSpan() != null) { cb.setText(pollOption.getTitle());
cb.setText(pollOption.getTitleSpan(), TextView.BufferType.SPANNABLE); makeEmojis(context, cb, pollOption.getTitleSpan(), poll.getEmojis());
} else {
cb.setText(pollOption.getTitle());
}
holder.multiple_choice.addView(cb); holder.multiple_choice.addView(cb);
} }
@ -795,11 +794,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
(holder.radio_group).removeAllViews(); (holder.radio_group).removeAllViews();
for (PollOptions pollOption : poll.getOptionsList()) { for (PollOptions pollOption : poll.getOptionsList()) {
RadioButton rb = new RadioButton(context); RadioButton rb = new RadioButton(context);
if (pollOption.getTitleSpan() != null) { rb.setText(pollOption.getTitle());
rb.setText(pollOption.getTitleSpan(), TextView.BufferType.SPANNABLE); makeEmojis(context, rb, pollOption.getTitleSpan(), poll.getEmojis());
} else {
rb.setText(pollOption.getTitle());
}
holder.radio_group.addView(rb); holder.radio_group.addView(rb);
} }
holder.single_choice.setVisibility(View.VISIBLE); holder.single_choice.setVisibility(View.VISIBLE);
@ -983,15 +979,10 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
holder.status_spoiler.setTextSize(TypedValue.COMPLEX_UNIT_SP, (float) (14 * textSizePercent) / 100); holder.status_spoiler.setTextSize(TypedValue.COMPLEX_UNIT_SP, (float) (14 * textSizePercent) / 100);
switch (translator) { if (translator == Helper.TRANS_YANDEX) {
case Helper.TRANS_NONE: holder.yandex_translate.setVisibility(View.VISIBLE);
holder.yandex_translate.setVisibility(View.GONE); } else {
break; holder.yandex_translate.setVisibility(View.GONE);
case Helper.TRANS_YANDEX:
holder.yandex_translate.setVisibility(View.VISIBLE);
break;
default:
holder.yandex_translate.setVisibility(View.GONE);
} }
//Manages theme for icon colors //Manages theme for icon colors
@ -1229,7 +1220,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
TooltipCompat.setTooltipText(holder.custom_feature_translate, context.getString(R.string.translate)); TooltipCompat.setTooltipText(holder.custom_feature_translate, context.getString(R.string.translate));
holder.custom_feature_translate.setOnClickListener(view -> { holder.custom_feature_translate.setOnClickListener(view -> {
translateToot(status); translateToot(status, holder.status_content_translated);
status.setCustomFeaturesDisplayed(false); status.setCustomFeaturesDisplayed(false);
notifyStatusChanged(status); notifyStatusChanged(status);
}); });
@ -1324,11 +1315,10 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
assert img != null; assert img != null;
img.setBounds(0, 0, (int) (20 * iconSizePercent / 100 * scale + 0.5f), (int) (15 * iconSizePercent / 100 * scale + 0.5f)); img.setBounds(0, 0, (int) (20 * iconSizePercent / 100 * scale + 0.5f), (int) (15 * iconSizePercent / 100 * scale + 0.5f));
holder.status_account_displayname.setCompoundDrawables(img, null, null, null); holder.status_account_displayname.setCompoundDrawables(img, null, null, null);
holder.status_toot_date.setCompoundDrawables(imgConversation, null, null, null);
} else { } else {
holder.status_account_displayname.setCompoundDrawables(null, null, null, null); holder.status_account_displayname.setCompoundDrawables(null, null, null, null);
holder.status_toot_date.setCompoundDrawables(imgConversation, null, null, null);
} }
holder.status_toot_date.setCompoundDrawables(imgConversation, null, null, null);
if (expand_media && status.isSensitive() || (status.getReblog() != null && status.getReblog().isSensitive())) { if (expand_media && status.isSensitive() || (status.getReblog() != null && status.getReblog().isSensitive())) {
Helper.changeDrawableColor(context, holder.hide_preview, R.color.red_1); Helper.changeDrawableColor(context, holder.hide_preview, R.color.red_1);
Helper.changeDrawableColor(context, holder.hide_preview_h, R.color.red_1); Helper.changeDrawableColor(context, holder.hide_preview_h, R.color.red_1);
@ -1408,7 +1398,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
} }
}); });
holder.status_content.setOnClickListener(v -> { holder.status_content.setOnClickListener(v -> {
if (type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && type != RetrieveFeedsAsyncTask.Type.NEWS) { if (type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && type != REMOTE_INSTANCE_FILTERED && type != RetrieveFeedsAsyncTask.Type.NEWS) {
Intent intent = new Intent(context, ShowConversationActivity.class); Intent intent = new Intent(context, ShowConversationActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
if (social == UpdateAccountInfoAsyncTask.SOCIAL.GNU || social == UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) if (social == UpdateAccountInfoAsyncTask.SOCIAL.GNU || social == UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA)
@ -1561,6 +1551,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
holder.status_content.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE); holder.status_content.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE);
holder.status_spoiler.setText(status.getContentSpanCW(), TextView.BufferType.SPANNABLE); holder.status_spoiler.setText(status.getContentSpanCW(), TextView.BufferType.SPANNABLE);
} }
makeEmojis(context, holder.status_content, status.getContentSpan(), status.getReblog() != null ? status.getReblog().getEmojis() : status.getEmojis());
holder.status_content.setMovementMethod(LongClickLinkMovementMethod.getInstance()); holder.status_content.setMovementMethod(LongClickLinkMovementMethod.getInstance());
@ -1613,10 +1604,12 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
context.startActivity(intent); context.startActivity(intent);
}); });
if (status.getReblog().getAccount().getDisplay_name().length() > 0) if (status.getReblog().getAccount().getDisplay_name().length() > 0) {
holder.status_account_displayname_owner.setText(displayNameSpan, TextView.BufferType.SPANNABLE); holder.status_account_displayname_owner.setText(displayNameSpan, TextView.BufferType.SPANNABLE);
else makeEmojis(context, holder.status_account_displayname_owner, status.getReblog().getAccount().getDisplayNameSpan(), status.getReblog().getAccount().getEmojis());
} else
holder.status_account_displayname_owner.setText(status.getReblog().getAccount().getAcct().replace("@", "")); holder.status_account_displayname_owner.setText(status.getReblog().getAccount().getAcct().replace("@", ""));
holder.status_account_displayname_owner.setVisibility(View.VISIBLE); holder.status_account_displayname_owner.setVisibility(View.VISIBLE);
if (holder.status_boosted_date != null) { if (holder.status_boosted_date != null) {
holder.status_boosted_date.setText(Helper.dateDiff(context, status.getCreated_at())); holder.status_boosted_date.setText(Helper.dateDiff(context, status.getCreated_at()));
@ -1624,10 +1617,12 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
} else { } else {
accountForUrl = status.getAccount(); accountForUrl = status.getAccount();
holder.status_account_displayname.setVisibility(View.GONE); holder.status_account_displayname.setVisibility(View.GONE);
if (displayNameSpan == null || displayNameSpan.toString().trim().length() == 0) if (displayNameSpan == null || displayNameSpan.toString().trim().length() == 0) {
holder.status_account_displayname_owner.setText(status.getAccount().getUsername().replace("@", ""), TextView.BufferType.SPANNABLE); holder.status_account_displayname_owner.setText(status.getAccount().getUsername().replace("@", ""), TextView.BufferType.SPANNABLE);
else } else {
holder.status_account_displayname_owner.setText(displayNameSpan, TextView.BufferType.SPANNABLE); holder.status_account_displayname_owner.setText(displayNameSpan, TextView.BufferType.SPANNABLE);
makeEmojis(context, holder.status_account_displayname_owner, displayNameSpan, status.getAccount().getEmojis());
}
} }
//-------- END -> Displays name & emoji in toot header //-------- END -> Displays name & emoji in toot header
@ -1704,6 +1699,9 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
holder.fetch_more.setVisibility(View.GONE); holder.fetch_more.setVisibility(View.GONE);
} }
if (type == RetrieveFeedsAsyncTask.Type.CONTEXT) {
holder.fetch_more.setVisibility(View.GONE);
}
if (status.getMentions() != null) if (status.getMentions() != null)
holder.status_mention_spoiler.setText(Helper.makeMentionsClick(context, status.getMentions()), TextView.BufferType.SPANNABLE); holder.status_mention_spoiler.setText(Helper.makeMentionsClick(context, status.getMentions()), TextView.BufferType.SPANNABLE);
@ -2144,33 +2142,17 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
if (status.getReblog() == null) { if (status.getReblog() == null) {
if (status.getWebviewURL() != null) { if (status.getWebviewURL() != null) {
String url = status.getWebviewURL().replaceAll("&amp;", "&");
try {
holder.status_cardview_webview.loadUrl(url);
} catch (Exception e) {
e.printStackTrace();
}
holder.status_cardview_webview.setVisibility(View.VISIBLE);
holder.status_cardview_video.setVisibility(View.VISIBLE); holder.status_cardview_video.setVisibility(View.VISIBLE);
holder.webview_preview.setVisibility(View.GONE); holder.webview_preview.setVisibility(View.GONE);
} else { } else {
holder.status_cardview_webview.setVisibility(View.GONE);
holder.status_cardview_video.setVisibility(View.GONE); holder.status_cardview_video.setVisibility(View.GONE);
holder.webview_preview.setVisibility(View.VISIBLE); holder.webview_preview.setVisibility(View.VISIBLE);
} }
} else { } else {
if (status.getReblog().getWebviewURL() != null) { if (status.getReblog().getWebviewURL() != null) {
String url = status.getReblog().getWebviewURL().replaceAll("&amp;", "&");
try {
holder.status_cardview_webview.loadUrl(url);
} catch (Exception e) {
e.printStackTrace();
}
holder.status_cardview_webview.setVisibility(View.VISIBLE);
holder.status_cardview_video.setVisibility(View.VISIBLE); holder.status_cardview_video.setVisibility(View.VISIBLE);
holder.webview_preview.setVisibility(View.GONE); holder.webview_preview.setVisibility(View.GONE);
} else { } else {
holder.status_cardview_webview.setVisibility(View.GONE);
holder.status_cardview_video.setVisibility(View.GONE); holder.status_cardview_video.setVisibility(View.GONE);
holder.webview_preview.setVisibility(View.VISIBLE); holder.webview_preview.setVisibility(View.VISIBLE);
} }
@ -2302,17 +2284,14 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
Helper.openBrowser(context, url); Helper.openBrowser(context, url);
}); });
} else if (card.getType().toLowerCase().equals("video") && (display_video_preview || (type == RetrieveFeedsAsyncTask.Type.CONTEXT && viewHolder.getAdapterPosition() == conversationPosition))) { } else if (card.getType().toLowerCase().equals("video") && (display_video_preview || (type == RetrieveFeedsAsyncTask.Type.CONTEXT && viewHolder.getAdapterPosition() == conversationPosition))) {
Glide.with(holder.status_cardview_image.getContext()) Glide.with(holder.status_cardview_image.getContext())
.load(card.getImage()) .load(card.getImage())
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10))) .apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(holder.webview_preview_card); .into(holder.webview_preview_card);
holder.status_cardview.setVisibility(View.GONE); holder.status_cardview.setVisibility(View.GONE);
holder.status_cardview_video.setVisibility(View.VISIBLE); holder.status_cardview_video.setVisibility(View.VISIBLE);
String user_agent = sharedpreferences.getString(Helper.SET_CUSTOM_USER_AGENT, Helper.USER_AGENT);
if (user_agent != null) {
holder.status_cardview_webview.getSettings().setUserAgentString(user_agent);
}
holder.status_cardview_webview.getSettings().setJavaScriptEnabled(true);
String html = card.getHtml(); String html = card.getHtml();
String src = card.getUrl(); String src = card.getUrl();
if (html != null) { if (html != null) {
@ -2321,12 +2300,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
src = matcher.group(1); src = matcher.group(1);
} }
final String finalSrc = src; final String finalSrc = src;
holder.status_cardview_webview.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
holder.status_cardview_video.setVisibility(View.GONE);
}
});
holder.webview_preview.setOnClickListener(v -> { holder.webview_preview.setOnClickListener(v -> {
String url = finalSrc; String url = finalSrc;
if (url != null) { if (url != null) {
@ -2344,12 +2318,27 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
} }
} }
} }
if (status.getReblog() == null) { Intent intent = new Intent(context, SlideMediaActivity.class);
status.setWebviewURL(url); Bundle b = new Bundle();
Attachment attachment = new Attachment();
attachment.setType("web");
attachment.setUrl(url);
attachment.setPreview_url(card.getImage());
ArrayList<Attachment> attachmentArrayList = new ArrayList<>();
attachmentArrayList.add(attachment);
intent.putParcelableArrayListExtra("mediaArray", attachmentArrayList);
b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark));
b.putInt("position", 1);
intent.putExtras(b);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, holder.webview_preview, attachment.getUrl());
// start the new activity
context.startActivity(intent, options.toBundle());
} else { } else {
status.getReblog().setWebviewURL(url); // start the new activity
context.startActivity(intent);
} }
notifyStatusChanged(status);
}); });
} else { } else {
holder.status_cardview.setVisibility(View.GONE); holder.status_cardview.setVisibility(View.GONE);
@ -2471,12 +2460,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
break; break;
} }
} }
int tootVisibility; int tootVisibility = Math.min(ownerTootVisibility, initialTootVisibility);
if (ownerTootVisibility >= initialTootVisibility) {
tootVisibility = initialTootVisibility;
} else {
tootVisibility = ownerTootVisibility;
}
switch (tootVisibility) { switch (tootVisibility) {
case 4: case 4:
@ -2670,6 +2654,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
CrossActions.doCrossAction(context, type, status, null, API.StatusAction.REBLOG, statusListAdapter, StatusListAdapter.this, false); CrossActions.doCrossAction(context, type, status, null, API.StatusAction.REBLOG, statusListAdapter, StatusListAdapter.this, false);
return true; return true;
}); });
if (!status.getVisibility().equals("direct")) if (!status.getVisibility().equals("direct"))
holder.status_reply.setOnLongClickListener(view -> { holder.status_reply.setOnLongClickListener(view -> {
CrossActions.doCrossReply(context, status, type, false); CrossActions.doCrossReply(context, status, type, false);
@ -2888,7 +2873,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
if (translator == Helper.TRANS_NONE) if (translator == Helper.TRANS_NONE)
Toasty.info(context, R.string.toast_error_translations_disabled, Toast.LENGTH_SHORT).show(); Toasty.info(context, R.string.toast_error_translations_disabled, Toast.LENGTH_SHORT).show();
else else
translateToot(status); translateToot(status, holder.status_content_translated);
return true; return true;
case R.id.action_report: case R.id.action_report:
builderInner = new AlertDialog.Builder(context, style); builderInner = new AlertDialog.Builder(context, style);
@ -3333,7 +3318,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
.asBitmap() .asBitmap()
.load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave) .load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave)
.thumbnail(0.1f) .thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10))) //.dontTransform()
.apply(new RequestOptions().transform(new RoundedCorners(10)))
.into(new CustomTarget<Bitmap>() { .into(new CustomTarget<Bitmap>() {
@Override @Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) { public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
@ -3352,6 +3338,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
.asBitmap() .asBitmap()
.load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave) .load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave)
.thumbnail(0.1f) .thumbnail(0.1f)
// .dontTransform()
.apply(new RequestOptions().transform(new BlurTransformation(50, 3), new RoundedCorners(10))) .apply(new RequestOptions().transform(new BlurTransformation(50, 3), new RoundedCorners(10)))
.into(new CustomTarget<Bitmap>() { .into(new CustomTarget<Bitmap>() {
@Override @Override
@ -3372,18 +3359,20 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
if (!blur) { if (!blur) {
Glide.with(imageView.getContext()) Glide.with(imageView.getContext())
.load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave) .load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave)
.dontTransform()
.thumbnail(0.1f) .thumbnail(0.1f)
// .override(640, 480) // .override(640, 480)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10))) .apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
// .transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.into(imageView); .into(imageView);
} else { } else {
Glide.with(imageView.getContext()) Glide.with(imageView.getContext())
.load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave) .load(!attachment.getType().toLowerCase().equals("audio") ? url : R.drawable.ic_audio_wave)
.thumbnail(0.1f) .thumbnail(0.1f)
.dontTransform()
// .override(640, 480) // .override(640, 480)
.apply(new RequestOptions().transform(new BlurTransformation(50, 3), new RoundedCorners(10))) .apply(new RequestOptions().transform(new CenterCrop(), new BlurTransformation(50, 3), new RoundedCorners(10)))
// .transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.into(imageView); .into(imageView);
} }
} }
@ -3408,7 +3397,16 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark)); b.putInt("bgcolor", context.getResources().getColor(R.color.cyanea_primary_dark));
b.putInt("position", finalPosition); b.putInt("position", finalPosition);
intent.putExtras(b); intent.putExtras(b);
context.startActivity(intent); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, imageView, attachment.getUrl());
// start the new activity
context.startActivity(intent, options.toBundle());
} else {
// start the new activity
context.startActivity(intent);
}
} }
} else { } else {
status.setAttachmentShown(true); status.setAttachmentShown(true);
@ -3882,11 +3880,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
@Override @Override
public void onRetrieveImage(Status status, boolean fromTranslation) { public void onRetrieveImage(Status status, boolean fromTranslation) {
if (status != null) { if (status != null) {
if (!fromTranslation) { status.setImageFound(true);
status.setImageFound(true);
} else {
status.setImageFound(true);
}
notifyStatusChanged(status); notifyStatusChanged(status);
} }
} }
@ -3908,7 +3902,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
} }
private void translateToot(Status status) { private void translateToot(Status status, TextView view) {
//Manages translations //Manages translations
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
int trans = sharedpreferences.getInt(Helper.SET_TRANSLATOR, Helper.TRANS_YANDEX); int trans = sharedpreferences.getInt(Helper.SET_TRANSLATOR, Helper.TRANS_YANDEX);
@ -3950,7 +3944,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
status.setTranslationShown(true); status.setTranslationShown(true);
status.setContentTranslated(translate.getTranslatedContent()); status.setContentTranslated(translate.getTranslatedContent());
Status.transformTranslation(context, status); Status.transformTranslation(context, status);
Status.makeEmojisTranslation(context, StatusListAdapter.this, status); makeEmojis(context, view, status.getContentSpan(), status.getReblog() != null ? status.getReblog().getEmojis() : status.getEmojis());
notifyStatusChanged(status); notifyStatusChanged(status);
} else { } else {
Toasty.error(context, context.getString(R.string.toast_error_translate), Toast.LENGTH_LONG).show(); Toasty.error(context, context.getString(R.string.toast_error_translate), Toast.LENGTH_LONG).show();
@ -4078,7 +4072,6 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
ImageView status_cardview_image; ImageView status_cardview_image;
TextView status_cardview_title, status_cardview_content, status_cardview_url; TextView status_cardview_title, status_cardview_content, status_cardview_url;
FrameLayout status_cardview_video; FrameLayout status_cardview_video;
CustomWebview status_cardview_webview;
ImageView hide_preview, hide_preview_h; ImageView hide_preview, hide_preview_h;
TextView status_toot_app; TextView status_toot_app;
RelativeLayout webview_preview; RelativeLayout webview_preview;
@ -4192,8 +4185,6 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
status_cardview_content = itemView.findViewById(R.id.status_cardview_content); status_cardview_content = itemView.findViewById(R.id.status_cardview_content);
status_cardview_url = itemView.findViewById(R.id.status_cardview_url); status_cardview_url = itemView.findViewById(R.id.status_cardview_url);
status_cardview_video = itemView.findViewById(R.id.status_cardview_video); status_cardview_video = itemView.findViewById(R.id.status_cardview_video);
status_cardview_webview = Helper.initializeWebview((Activity) context, R.id.status_cardview_webview, itemView);
status_cardview_webview.getSettings().setJavaScriptEnabled(true);
hide_preview = itemView.findViewById(R.id.hide_preview); hide_preview = itemView.findViewById(R.id.hide_preview);
hide_preview_h = itemView.findViewById(R.id.hide_preview_h); hide_preview_h = itemView.findViewById(R.id.hide_preview_h);
status_toot_app = itemView.findViewById(R.id.status_toot_app); status_toot_app = itemView.findViewById(R.id.status_toot_app);

View File

@ -35,7 +35,7 @@ import app.fedilab.android.helper.Helper;
* Created by Thomas on 19/07/2019. * Created by Thomas on 19/07/2019.
* Adapter for suggestions results * Adapter for suggestions results
*/ */
public class SuggestionsAdapter extends RecyclerView.Adapter { public class SuggestionsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<Suggestion> suggestions; private List<Suggestion> suggestions;

View File

@ -39,7 +39,7 @@ import es.dmoral.toasty.Toasty;
* Created by Thomas on 01/12/2018. * Created by Thomas on 01/12/2018.
* Adapter for tags when editing * Adapter for tags when editing
*/ */
public class TagsEditAdapter extends RecyclerView.Adapter { public class TagsEditAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private List<String> tags; private List<String> tags;

View File

@ -110,7 +110,7 @@ public class TrendsAdapter extends BaseAdapter {
uses += _th.getUses(); uses += _th.getUses();
tendency.put(_th.getDays(), _th.getUses()); tendency.put(_th.getDays(), _th.getUses());
} }
if( days > 0 ) { if (days > 0) {
people = people / days; people = people / days;
uses = uses / days; uses = uses / days;
} }

View File

@ -266,7 +266,7 @@ public class ColorSettingsFragment extends PreferenceFragmentCompat implements S
} }
List<String> array = Arrays.asList(getResources().getStringArray(R.array.settings_theme)); List<String> array = Arrays.asList(getResources().getStringArray(R.array.settings_theme));
CharSequence[] entries = array.toArray(new CharSequence[array.size()]); CharSequence[] entries = array.toArray(new CharSequence[0]);
CharSequence[] entryValues = new CharSequence[3]; CharSequence[] entryValues = new CharSequence[3];
final SharedPreferences sharedpref = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); final SharedPreferences sharedpref = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int theme = sharedpref.getInt(Helper.SET_THEME, Helper.THEME_DARK); int theme = sharedpref.getInt(Helper.SET_THEME, Helper.THEME_DARK);

View File

@ -1538,7 +1538,7 @@ public class ContentSettingsFragment extends Fragment implements OnRetrieveRemot
if (featuredTagsSet != null) { if (featuredTagsSet != null) {
tags = new ArrayList<>(featuredTagsSet); tags = new ArrayList<>(featuredTagsSet);
} }
String[] tagsString = tags.toArray(new String[tags.size()]); String[] tagsString = tags.toArray(new String[0]);
set_featured_tags.setTags(tagsString); set_featured_tags.setTags(tagsString);
set_featured_tags.setTagsListener(new TagsEditText.TagsEditListener() { set_featured_tags.setTagsListener(new TagsEditText.TagsEditListener() {

View File

@ -15,7 +15,6 @@ package app.fedilab.android.fragments;
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -31,6 +30,8 @@ import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -61,7 +62,6 @@ public class DisplayMediaFragment extends Fragment implements OnRetrieveFeedsInt
private boolean firstLoad; private boolean firstLoad;
private String targetedId; private String targetedId;
private boolean showMediaOnly, showPinned, showReply; private boolean showMediaOnly, showPinned, showReply;
private SharedPreferences sharedpreferences;
private ArrayList<Status> statuses; private ArrayList<Status> statuses;
private ImageAdapter gridAdaper; private ImageAdapter gridAdaper;
private RecyclerView gridview; private RecyclerView gridview;
@ -84,7 +84,6 @@ public class DisplayMediaFragment extends Fragment implements OnRetrieveFeedsInt
showReply = false; showReply = false;
firstLoad = true; firstLoad = true;
assert context != null; assert context != null;
sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
mainLoader = rootView.findViewById(R.id.loader); mainLoader = rootView.findViewById(R.id.loader);
nextElementLoader = rootView.findViewById(R.id.loading_next_status); nextElementLoader = rootView.findViewById(R.id.loading_next_status);
textviewNoAction = rootView.findViewById(R.id.no_action); textviewNoAction = rootView.findViewById(R.id.no_action);
@ -105,7 +104,7 @@ public class DisplayMediaFragment extends Fragment implements OnRetrieveFeedsInt
gridview.addOnScrollListener(new RecyclerView.OnScrollListener() { gridview.addOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { public void onScrolled(@NotNull RecyclerView recyclerView, int dx, int dy) {
int firstVisibleItem = gvLayout.findFirstVisibleItemPosition(); int firstVisibleItem = gvLayout.findFirstVisibleItemPosition();
if (dy > 0) { if (dy > 0) {
int visibleItemCount = gvLayout.getChildCount(); int visibleItemCount = gvLayout.getChildCount();
@ -129,12 +128,9 @@ public class DisplayMediaFragment extends Fragment implements OnRetrieveFeedsInt
if (context != null) { if (context != null) {
asyncTask = new RetrieveFeedsAsyncTask(context, RetrieveFeedsAsyncTask.Type.USER, targetedId, max_id, showMediaOnly, showPinned, showReply, DisplayMediaFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); asyncTask = new RetrieveFeedsAsyncTask(context, RetrieveFeedsAsyncTask.Type.USER, targetedId, max_id, showMediaOnly, showPinned, showReply, DisplayMediaFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else { } else {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { new Handler(Looper.getMainLooper()).postDelayed(() -> {
@Override if (context != null) {
public void run() { asyncTask = new RetrieveFeedsAsyncTask(context, RetrieveFeedsAsyncTask.Type.USER, targetedId, max_id, showMediaOnly, showPinned, showReply, DisplayMediaFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
if (context != null) {
asyncTask = new RetrieveFeedsAsyncTask(context, RetrieveFeedsAsyncTask.Type.USER, targetedId, max_id, showMediaOnly, showPinned, showReply, DisplayMediaFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
} }
}, 500); }, 500);
} }
@ -158,7 +154,7 @@ public class DisplayMediaFragment extends Fragment implements OnRetrieveFeedsInt
} }
@Override @Override
public void onAttach(Context context) { public void onAttach(@NotNull Context context) {
super.onAttach(context); super.onAttach(context);
this.context = context; this.context = context;
} }

View File

@ -40,6 +40,8 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -194,7 +196,7 @@ public class DisplayScheduledTootsFragment extends Fragment implements OnRetriev
} }
@Override @Override
public void onAttach(Context context) { public void onAttach(@NotNull Context context) {
super.onAttach(context); super.onAttach(context);
this.context = context; this.context = context;
} }
@ -224,7 +226,6 @@ public class DisplayScheduledTootsFragment extends Fragment implements OnRetriev
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
message = Html.fromHtml(context.getString(R.string.no_scheduled_boosts_indications), Html.FROM_HTML_MODE_LEGACY); message = Html.fromHtml(context.getString(R.string.no_scheduled_boosts_indications), Html.FROM_HTML_MODE_LEGACY);
else else
//noinspection deprecation
message = Html.fromHtml(context.getString(R.string.no_scheduled_boosts_indications)); message = Html.fromHtml(context.getString(R.string.no_scheduled_boosts_indications));
no_action_text_subtitle.setText(message, TextView.BufferType.SPANNABLE); no_action_text_subtitle.setText(message, TextView.BufferType.SPANNABLE);
} }

View File

@ -30,6 +30,7 @@ import android.os.Handler;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageButton; import android.widget.ImageButton;
@ -40,6 +41,8 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@ -115,6 +118,12 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
private SlidrInterface slidrInterface; private SlidrInterface slidrInterface;
private boolean swipeEnabled; private boolean swipeEnabled;
private int bgColor; private int bgColor;
private RelativeLayout media_fragment_container;
private RelativeLayout content_audio;
private PlayerView videoView;
private CustomWebview webview_video;
private FrameLayout webview_container;
private RelativeLayout videoLayout;
public MediaSliderFragment() { public MediaSliderFragment() {
} }
@ -134,7 +143,7 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
swipeEnabled = true; swipeEnabled = true;
message_ready = rootView.findViewById(R.id.message_ready); message_ready = rootView.findViewById(R.id.message_ready);
RelativeLayout content_audio = rootView.findViewById(R.id.content_audio); content_audio = rootView.findViewById(R.id.content_audio);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
@ -144,7 +153,7 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
ImageView next = rootView.findViewById(R.id.media_next); ImageView next = rootView.findViewById(R.id.media_next);
imageView = rootView.findViewById(R.id.media_picture); imageView = rootView.findViewById(R.id.media_picture);
PlayerView videoView = rootView.findViewById(R.id.media_video); videoView = rootView.findViewById(R.id.media_video);
if (theme == Helper.THEME_BLACK) { if (theme == Helper.THEME_BLACK) {
changeDrawableColor(context, prev, R.color.dark_icon); changeDrawableColor(context, prev, R.color.dark_icon);
changeDrawableColor(context, next, R.color.dark_icon); changeDrawableColor(context, next, R.color.dark_icon);
@ -182,68 +191,97 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
url = attachment.getRemote_url(); url = attachment.getRemote_url();
attachment.setType(type); attachment.setType(type);
} }
media_fragment_container = rootView.findViewById(R.id.media_fragment_container);
if (bgColor != -1) { imageView.setVisibility(View.VISIBLE);
RelativeLayout media_fragment_container = rootView.findViewById(R.id.media_fragment_container); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
media_fragment_container.setBackgroundColor(bgColor); imageView.setTransitionName(attachment.getUrl());
} }
if (Helper.isValidContextForGlide(context)) {
switch (type.toLowerCase()) { Glide.with(context)
case "image": .asBitmap()
pbar_inf.setScaleY(1f); .dontTransform()
imageView.setVisibility(View.VISIBLE); .load(preview_url).into(
pbar_inf.setIndeterminate(true); new CustomTarget<Bitmap>() {
loader.setVisibility(View.VISIBLE); @Override
if (!url.endsWith(".gif")) { public void onResourceReady(@NonNull final Bitmap resource, Transition<? super Bitmap> transition) {
Glide.with(context) //Bitmap imageCompressed = Helper.compressImageIfNeeded(resource);
.asBitmap() imageView.setImageBitmap(resource);
.load(preview_url).into( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
new CustomTarget<Bitmap>() { scheduleStartPostponedTransition(imageView);
@Override }
public void onResourceReady(@NonNull final Bitmap resource, Transition<? super Bitmap> transition) { if (bgColor != -1) {
Bitmap imageCompressed = Helper.compressImageIfNeeded(resource); media_fragment_container.setBackgroundColor(bgColor);
imageView.setImageBitmap(imageCompressed); }
Glide.with(context) if (attachment.getType().toLowerCase().compareTo("image") == 0 && !attachment.getUrl().endsWith(".gif")) {
.asBitmap() final Handler handler = new Handler();
.load(url).into( handler.postDelayed(() -> {
new CustomTarget<Bitmap>() { pbar_inf.setScaleY(1f);
@Override imageView.setVisibility(View.VISIBLE);
public void onResourceReady(@NonNull final Bitmap resource, Transition<? super Bitmap> transition) { pbar_inf.setIndeterminate(true);
loader.setVisibility(View.GONE); loader.setVisibility(View.VISIBLE);
Bitmap imageCompressed = Helper.compressImageIfNeeded(resource); if (Helper.isValidContextForGlide(context)) {
if (imageView.getScale() < 1.1) { Glide.with(context)
imageView.setImageBitmap(imageCompressed); .asBitmap()
} else { .dontTransform()
message_ready.setVisibility(View.VISIBLE); .load(url).into(
new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull final Bitmap resource, Transition<? super Bitmap> transition) {
loader.setVisibility(View.GONE);
Bitmap imageCompressed = Helper.compressImageIfNeeded(resource);
if (imageView.getScale() < 1.1) {
imageView.setImageBitmap(imageCompressed);
} else {
message_ready.setVisibility(View.VISIBLE);
}
message_ready.setOnClickListener(view -> {
imageView.setImageBitmap(imageCompressed);
message_ready.setVisibility(View.GONE);
});
} }
message_ready.setOnClickListener(view -> {
imageView.setImageBitmap(imageCompressed);
message_ready.setVisibility(View.GONE);
});
}
@Override @Override
public void onLoadCleared(@Nullable Drawable placeholder) { public void onLoadCleared(@Nullable Drawable placeholder) {
}
} }
} );
); }
}, 1000);
} else if (attachment.getType().toLowerCase().compareTo("image") == 0 && attachment.getUrl().endsWith(".gif")) {
loader.setVisibility(View.GONE);
if (Helper.isValidContextForGlide(context)) {
Glide.with(context)
.load(url).into(imageView);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@Override scheduleStartPostponedTransition(imageView);
public void onLoadCleared(@Nullable Drawable placeholder) {
} }
} }
); }
} else {
loader.setVisibility(View.GONE); @Override
Glide.with(context) public void onLoadFailed(@Nullable Drawable errorDrawable) {
.load(url).into(imageView); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
} scheduleStartPostponedTransition(imageView);
break; }
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
}
);
}
switch (type.toLowerCase()) {
case "video": case "video":
case "gifv": case "gifv":
if (bgColor != -1) {
media_fragment_container.setBackgroundColor(bgColor);
}
pbar_inf.setIndeterminate(false); pbar_inf.setIndeterminate(false);
pbar_inf.setScaleY(3f); pbar_inf.setScaleY(3f);
try { try {
@ -272,19 +310,23 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
player.setRepeatMode(Player.REPEAT_MODE_ONE); player.setRepeatMode(Player.REPEAT_MODE_ONE);
videoView.setPlayer(player); videoView.setPlayer(player);
loader.setVisibility(View.GONE); loader.setVisibility(View.GONE);
imageView.setVisibility(View.GONE);
player.prepare(videoSource); player.prepare(videoSource);
player.setPlayWhenReady(true); player.setPlayWhenReady(true);
break; break;
case "web": case "web":
if (bgColor != -1) {
media_fragment_container.setBackgroundColor(bgColor);
}
loader.setVisibility(View.GONE); loader.setVisibility(View.GONE);
CustomWebview webview_video = Helper.initializeWebview((Activity) context, R.id.webview_video, null); imageView.setVisibility(View.GONE);
webview_video = Helper.initializeWebview((Activity) context, R.id.webview_video, rootView);
webview_video.setVisibility(View.VISIBLE); webview_video.setVisibility(View.VISIBLE);
FrameLayout webview_container = rootView.findViewById(R.id.main_media_frame); webview_container = rootView.findViewById(R.id.main_media_frame);
final ViewGroup videoLayout = rootView.findViewById(R.id.videoLayout); videoLayout = rootView.findViewById(R.id.videoLayout);
MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient((Activity) context, webview_video, webview_container, videoLayout); MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient((Activity) context, webview_video, webview_container, videoLayout);
mastalabWebChromeClient.setOnToggledFullscreen(fullscreen -> { mastalabWebChromeClient.setOnToggledFullscreen(fullscreen -> {
if (fullscreen) { if (fullscreen) {
videoLayout.setVisibility(View.VISIBLE); videoLayout.setVisibility(View.VISIBLE);
WindowManager.LayoutParams attrs = ((Activity) context).getWindow().getAttributes(); WindowManager.LayoutParams attrs = ((Activity) context).getWindow().getAttributes();
@ -312,7 +354,11 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
webview_video.loadUrl(attachment.getUrl()); webview_video.loadUrl(attachment.getUrl());
break; break;
case "audio": case "audio":
if (bgColor != -1) {
media_fragment_container.setBackgroundColor(bgColor);
}
loader.setVisibility(View.GONE); loader.setVisibility(View.GONE);
imageView.setVisibility(View.GONE);
content_audio.setVisibility(View.VISIBLE); content_audio.setVisibility(View.VISIBLE);
int color = getResources().getColor(R.color.mastodonC1); int color = getResources().getColor(R.color.mastodonC1);
visualizerView = new GLAudioVisualizationView.Builder(context) visualizerView = new GLAudioVisualizationView.Builder(context)
@ -386,7 +432,6 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
stopTimer(); stopTimer();
} }
@ -458,6 +503,9 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
if (playeraudio != null) { if (playeraudio != null) {
playeraudio.pause(); playeraudio.pause();
} }
if (webview_video != null) {
webview_video.onPause();
}
try { try {
visualizerView.onPause(); visualizerView.onPause();
} catch (Exception ignored) { } catch (Exception ignored) {
@ -478,6 +526,9 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
} }
} catch (Exception ignored) { } catch (Exception ignored) {
} }
if (webview_video != null) {
webview_video.destroy();
}
if (timer != null) { if (timer != null) {
timer.cancel(); timer.cancel();
timer = null; timer = null;
@ -504,6 +555,9 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
visualizerView.onResume(); visualizerView.onResume();
} catch (Exception ignored) { } catch (Exception ignored) {
} }
if (webview_video != null) {
webview_video.onResume();
}
if (slidrInterface == null && rootView != null) { if (slidrInterface == null && rootView != null) {
slidrInterface = Slidr.replace(rootView.findViewById(R.id.media_fragment_container), new SlidrConfig.Builder().sensitivity(1f) slidrInterface = Slidr.replace(rootView.findViewById(R.id.media_fragment_container), new SlidrConfig.Builder().sensitivity(1f)
.scrimColor(Color.BLACK) .scrimColor(Color.BLACK)
@ -521,7 +575,30 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
@Override @Override
public void onSlideChange(float percent) { public void onSlideChange(float percent) {
((SlideMediaActivity) context).setFullscreen(true); if (percent < 0.80 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (imageView != null) {
imageView.setVisibility(View.VISIBLE);
}
if (content_audio != null) {
content_audio.setVisibility(View.GONE);
}
if (videoView != null) {
videoView.setVisibility(View.GONE);
}
if (webview_video != null) {
webview_video.setVisibility(View.GONE);
webview_video.destroy();
}
if (webview_container != null) {
webview_container.setVisibility(View.GONE);
}
if (videoLayout != null) {
videoLayout.setVisibility(View.GONE);
}
ActivityCompat.finishAfterTransition((AppCompatActivity) context);
}
} }
@Override @Override
@ -538,6 +615,17 @@ public class MediaSliderFragment extends Fragment implements MediaPlayer.OnCompl
} }
} }
private void scheduleStartPostponedTransition(final ImageView imageView) {
imageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
imageView.getViewTreeObserver().removeOnPreDrawListener(this);
ActivityCompat.startPostponedEnterTransition((Activity) context);
return true;
}
});
}
private void enableSliding(boolean enable) { private void enableSliding(boolean enable) {
if (enable && !swipeEnabled) { if (enable && !swipeEnabled) {
slidrInterface.unlock(); slidrInterface.unlock();

View File

@ -28,6 +28,8 @@ import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import org.jetbrains.annotations.NotNull;
import java.util.Objects; import java.util.Objects;
import app.fedilab.android.R; import app.fedilab.android.R;
@ -105,6 +107,7 @@ public class TabLayoutTootsFragment extends Fragment {
this.mNumOfTabs = NumOfTabs; this.mNumOfTabs = NumOfTabs;
} }
@NotNull
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
switch (position) { switch (position) {

View File

@ -125,7 +125,7 @@ public class CrossActions {
} }
public static void doCrossAction(final Context context, RetrieveFeedsAsyncTask.Type type, final Status status, final Account targetedAccount, final API.StatusAction doAction, final RecyclerView.Adapter baseAdapter, final OnPostActionInterface onPostActionInterface, boolean limitedToOwner) { public static void doCrossAction(final Context context, RetrieveFeedsAsyncTask.Type type, final Status status, final Account targetedAccount, final API.StatusAction doAction, final RecyclerView.Adapter<RecyclerView.ViewHolder> baseAdapter, final OnPostActionInterface onPostActionInterface, boolean limitedToOwner) {
List<Account> accounts = connectedAccounts(context, status, limitedToOwner); List<Account> accounts = connectedAccounts(context, status, limitedToOwner);
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
boolean undoAction = (doAction == API.StatusAction.UNPIN || doAction == API.StatusAction.UNREBLOG || doAction == API.StatusAction.UNFAVOURITE); boolean undoAction = (doAction == API.StatusAction.UNPIN || doAction == API.StatusAction.UNREBLOG || doAction == API.StatusAction.UNFAVOURITE);
@ -784,7 +784,7 @@ public class CrossActions {
* @param action int * @param action int
* @param status Status * @param status Status
*/ */
private static void displayConfirmationDialog(final Context context, final API.StatusAction action, final Status status, final RecyclerView.Adapter baseAdapter, final OnPostActionInterface onPostActionInterface) { private static void displayConfirmationDialog(final Context context, final API.StatusAction action, final Status status, final RecyclerView.Adapter<RecyclerView.ViewHolder> baseAdapter, final OnPostActionInterface onPostActionInterface) {
String title = null; String title = null;
if (action == API.StatusAction.FAVOURITE) { if (action == API.StatusAction.FAVOURITE) {
@ -855,7 +855,7 @@ public class CrossActions {
* @param action int * @param action int
* @param status Status * @param status Status
*/ */
private static void displayConfirmationDialogCrossAction(final Context context, Account currentAccount, final API.StatusAction action, final Status status, final OnPostActionInterface onPostActionInterface, final RecyclerView.Adapter baseAdapter) { private static void displayConfirmationDialogCrossAction(final Context context, Account currentAccount, final API.StatusAction action, final Status status, final OnPostActionInterface onPostActionInterface, final RecyclerView.Adapter<RecyclerView.ViewHolder> baseAdapter) {
String title = null; String title = null;
if (action == API.StatusAction.FAVOURITE) { if (action == API.StatusAction.FAVOURITE) {
@ -950,7 +950,7 @@ public class CrossActions {
* *
* @param status Status * @param status Status
*/ */
private static void pinAction(Context context, Status status, RecyclerView.Adapter baseAdapter, OnPostActionInterface onPostActionInterface) { private static void pinAction(Context context, Status status, RecyclerView.Adapter<RecyclerView.ViewHolder> baseAdapter, OnPostActionInterface onPostActionInterface) {
if (status.isPinned()) { if (status.isPinned()) {
new PostActionAsyncTask(context, API.StatusAction.UNPIN, status.getId(), onPostActionInterface).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new PostActionAsyncTask(context, API.StatusAction.UNPIN, status.getId(), onPostActionInterface).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

View File

@ -46,6 +46,7 @@ public class FullScreenMediaController extends MediaController {
this.context = context; this.context = context;
} }
@SuppressWarnings("unused")
public FullScreenMediaController(Context context, Peertube peertube) { public FullScreenMediaController(Context context, Peertube peertube) {
super(context); super(context);
this.peertube = peertube; this.peertube = peertube;
@ -80,12 +81,7 @@ public class FullScreenMediaController extends MediaController {
paramsButton.gravity = Gravity.START; paramsButton.gravity = Gravity.START;
paramsButton.rightMargin = 80; paramsButton.rightMargin = 80;
paramsButton.topMargin = 22; paramsButton.topMargin = 22;
resolution.setOnClickListener(new OnClickListener() { resolution.setOnClickListener(v -> ((PeertubeActivity) getContext()).displayResolution());
@Override
public void onClick(View v) {
((PeertubeActivity) getContext()).displayResolution();
}
});
addView(resolution, paramsButton); addView(resolution, paramsButton);
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) { if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
@ -97,21 +93,19 @@ public class FullScreenMediaController extends MediaController {
} }
//add listener to image button to handle full screen and exit full screen events //add listener to image button to handle full screen and exit full screen events
fullScreen.setOnClickListener(new OnClickListener() { fullScreen.setOnClickListener(v -> {
@Override
public void onClick(View v) {
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) { if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
((PeertubeActivity) getContext()).setFullscreen(fullscreen.OFF); ((PeertubeActivity) getContext()).setFullscreen(fullscreen.OFF);
} else { } else {
((PeertubeActivity) getContext()).setFullscreen(fullscreen.ON); ((PeertubeActivity) getContext()).setFullscreen(fullscreen.ON);
}
((PeertubeActivity) getContext()).change();
changeIcon();
} }
((PeertubeActivity) getContext()).change();
changeIcon();
}); });
} }
@SuppressWarnings("unused")
public void setResolutionVal(String resolutionVal) { public void setResolutionVal(String resolutionVal) {
this.resolutionVal = resolutionVal; this.resolutionVal = resolutionVal;
if (resolution != null) if (resolution != null)

View File

@ -56,11 +56,13 @@ import android.provider.DocumentsContract;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.provider.OpenableColumns; import android.provider.OpenableColumns;
import android.text.Html; import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.ClickableSpan; import android.text.style.ClickableSpan;
import android.text.style.ImageSpan;
import android.text.style.URLSpan; import android.text.style.URLSpan;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
@ -82,6 +84,7 @@ import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -89,6 +92,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.browser.customtabs.CustomTabsIntent; import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
@ -262,6 +266,8 @@ public class Helper {
public static final String REDIRECT_CONTENT = "urn:ietf:wg:oauth:2.0:oob"; public static final String REDIRECT_CONTENT = "urn:ietf:wg:oauth:2.0:oob";
public static final String REDIRECT_CONTENT_WEB = "mastalab://backtomastalab"; public static final String REDIRECT_CONTENT_WEB = "mastalab://backtomastalab";
public static final int EXTERNAL_STORAGE_REQUEST_CODE = 84; public static final int EXTERNAL_STORAGE_REQUEST_CODE = 84;
public static final int EXTERNAL_STORAGE_REQUEST_CODE_MEDIA_SAVE = 85;
public static final int EXTERNAL_STORAGE_REQUEST_CODE_MEDIA_SHARE = 86;
//Thekinrar's API: https://instances.social/api/doc/ //Thekinrar's API: https://instances.social/api/doc/
public static final String THEKINRAR_SECRET_TOKEN = "jGj9gW3z9ptyIpB8CMGhAlTlslcemMV6AgoiImfw3vPP98birAJTHOWiu5ZWfCkLvcaLsFZw9e3Pb7TIwkbIyrj3z6S7r2oE6uy6EFHvls3YtapP8QKNZ980p9RfzTb4"; public static final String THEKINRAR_SECRET_TOKEN = "jGj9gW3z9ptyIpB8CMGhAlTlslcemMV6AgoiImfw3vPP98birAJTHOWiu5ZWfCkLvcaLsFZw9e3Pb7TIwkbIyrj3z6S7r2oE6uy6EFHvls3YtapP8QKNZ980p9RfzTb4";
@ -1639,12 +1645,7 @@ public class Helper {
public static <K, V> Map<K, V> sortByValue(Map<K, V> map) { public static <K, V> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Object>() { Collections.sort(list, (Comparator<Object>) (o2, o1) -> ((Comparable<V>) ((Map.Entry<K, V>) (o1)).getValue()).compareTo(((Map.Entry<K, V>) (o2)).getValue()));
@SuppressWarnings("unchecked")
public int compare(Object o2, Object o1) {
return ((Comparable<V>) ((Map.Entry<K, V>) (o1)).getValue()).compareTo(((Map.Entry<K, V>) (o2)).getValue());
}
});
Map<K, V> result = new LinkedHashMap<>(); Map<K, V> result = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : list) { for (Map.Entry<K, V> entry : list) {
@ -1970,7 +1971,8 @@ public class Helper {
activity.startActivity(myIntent); activity.startActivity(myIntent);
activity.finish(); //User is logged out to get a new token activity.finish(); //User is logged out to get a new token
} else { } else {
Account.makeAccountNameEmoji(new WeakReference<>(activity), account);
makeEmojis(activity, username, account.getDisplayNameSpan(), account.getEmojis());
username.setText(String.format("@%s", account.getUsername() + "@" + account.getInstance())); username.setText(String.format("@%s", account.getUsername() + "@" + account.getInstance()));
displayedName.setText(account.getDisplayNameSpan(), TextView.BufferType.SPANNABLE); displayedName.setText(account.getDisplayNameSpan(), TextView.BufferType.SPANNABLE);
loadGiF(activity, account, profilePicture); loadGiF(activity, account, profilePicture);
@ -2078,7 +2080,9 @@ public class Helper {
*/ */
public static SpannableString clickableElementsDescription(final Context context, String fullContent) { public static SpannableString clickableElementsDescription(final Context context, String fullContent) {
if (fullContent == null) {
return new SpannableString("");
}
SpannableString spannableString; SpannableString spannableString;
SpannableString spannableStringT = new SpannableString(fullContent); SpannableString spannableStringT = new SpannableString(fullContent);
Pattern aLink = Pattern.compile("(<\\s?a\\s?href=\"https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[/\\w._-]*)\"\\s?[^.]*<\\s?/\\s?a\\s?>)"); Pattern aLink = Pattern.compile("(<\\s?a\\s?href=\"https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[/\\w._-]*)\"\\s?[^.]*<\\s?/\\s?a\\s?>)");
@ -2654,7 +2658,8 @@ public class Helper {
public static List<String> restoreArrayFromString(String serializedArray) { public static List<String> restoreArrayFromString(String serializedArray) {
Gson gson = new Gson(); Gson gson = new Gson();
try { try {
Type listType = new TypeToken<ArrayList<String>>() {}.getType(); Type listType = new TypeToken<ArrayList<String>>() {
}.getType();
return gson.fromJson(serializedArray, listType); return gson.fromJson(serializedArray, listType);
} catch (Exception e) { } catch (Exception e) {
return null; return null;
@ -4200,12 +4205,12 @@ public class Helper {
fw.append(','); fw.append(',');
fw.append("COMMENT"); fw.append("COMMENT");
fw.append('\n'); fw.append('\n');
Iterator it = domainBlocked.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = domainBlocked.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
fw.append((String) pair.getKey()); fw.append(pair.getKey());
fw.append(','); fw.append(',');
fw.append((String) pair.getValue()); fw.append(pair.getValue());
fw.append('\n'); fw.append('\n');
it.remove(); it.remove();
} }
@ -4254,16 +4259,16 @@ public class Helper {
linearLayout_main.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout_main.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
linearLayout_main.setOrientation(LinearLayout.VERTICAL); linearLayout_main.setOrientation(LinearLayout.VERTICAL);
Iterator it = instances.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = instances.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next(); Map.Entry<String, String> pair = it.next();
View item = inflater.inflate(R.layout.muted_instance_popup, new LinearLayout(context), false); View item = inflater.inflate(R.layout.muted_instance_popup, new LinearLayout(context), false);
CheckBox checkBox = item.findViewById(R.id.popup_domain); CheckBox checkBox = item.findViewById(R.id.popup_domain);
checkBox.setText(pair.getKey().toString().trim()); checkBox.setText(pair.getKey().trim());
item.findViewById(R.id.popup_comment).setVisibility(View.GONE); item.findViewById(R.id.popup_comment).setVisibility(View.GONE);
if (pair.getValue() != null) { if (pair.getValue() != null) {
TextView textView = item.findViewById(R.id.comment_text); TextView textView = item.findViewById(R.id.comment_text);
textView.setText(pair.getValue().toString()); textView.setText(pair.getValue());
textView.setVisibility(View.VISIBLE); textView.setVisibility(View.VISIBLE);
} }
linearLayout_main.addView(item); linearLayout_main.addView(item);
@ -4284,15 +4289,15 @@ public class Helper {
if (domainBlocked.size() > 0) { if (domainBlocked.size() > 0) {
new Thread() { new Thread() {
public void run() { public void run() {
Iterator it1 = domainBlocked.entrySet().iterator(); Iterator<Map.Entry<String, String>> it1 = domainBlocked.entrySet().iterator();
while (it1.hasNext()) { while (it1.hasNext()) {
Map.Entry pair = (Map.Entry) it1.next(); Map.Entry<String, String> pair = it1.next();
try { try {
sleep(200); sleep(200);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
new PostActionAsyncTask(context, API.StatusAction.BLOCK_DOMAIN, pair.getKey().toString().trim(), ((MutedInstanceActivity) context)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new PostActionAsyncTask(context, API.StatusAction.BLOCK_DOMAIN, pair.getKey().trim(), ((MutedInstanceActivity) context)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
it1.remove(); it1.remove();
} }
} }
@ -4399,6 +4404,62 @@ public class Helper {
return null; return null;
} }
public static void makeEmojis(Context context, View customTextView, SpannableString contentSpan, List<Emojis> emojis) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean disableAnimatedEmoji = sharedpreferences.getBoolean(Helper.SET_DISABLE_ANIMATED_EMOJI, false);
if (emojis != null && emojis.size() > 0) {
for (final Emojis emoji : emojis) {
Glide.with(context)
.asDrawable()
.load(disableAnimatedEmoji ? emoji.getStatic_url() : emoji.getUrl())
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
final String targetedEmoji = ":" + emoji.getShortcode() + ":";
if (contentSpan != null && contentSpan.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = contentSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if (endPosition <= contentSpan.toString().length() && endPosition >= startPosition) {
ImageSpan imageSpan;
try {
resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
imageSpan = new ImageSpan(resource);
contentSpan.setSpan(
imageSpan, startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
if (customTextView instanceof CustomTextView) {
((CustomTextView) customTextView).setText(contentSpan, TextView.BufferType.SPANNABLE);
} else if (customTextView instanceof RadioButton) {
((RadioButton) customTextView).setText(contentSpan, TextView.BufferType.SPANNABLE);
} else if (customTextView instanceof CheckBox) {
((CheckBox) customTextView).setText(contentSpan, TextView.BufferType.SPANNABLE);
} else if (customTextView instanceof AppCompatTextView) {
((AppCompatTextView) customTextView).setText(contentSpan, TextView.BufferType.SPANNABLE);
} else if (customTextView instanceof TextView) {
((TextView) customTextView).setText(contentSpan, TextView.BufferType.SPANNABLE);
}
} catch (Exception ignored) {
}
}
}
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
}
}
//Event Type //Event Type
public enum EventStreaming { public enum EventStreaming {
UPDATE, UPDATE,
@ -4407,6 +4468,7 @@ public class Helper {
NONE NONE
} }
public enum NotifType { public enum NotifType {
FOLLLOW, FOLLLOW,
MENTION, MENTION,
@ -4418,7 +4480,6 @@ public class Helper {
TOOT TOOT
} }
public static class CacheTask extends AsyncTask<Void, Void, Void> { public static class CacheTask extends AsyncTask<Void, Void, Void> {
private float cacheSize; private float cacheSize;
private WeakReference<Context> contextReference; private WeakReference<Context> contextReference;
@ -4505,4 +4566,6 @@ public class Helper {
.show(); .show();
} }
} }
} }

View File

@ -14,7 +14,6 @@ import android.widget.TextView;
//https://stackoverflow.com/a/20435892 //https://stackoverflow.com/a/20435892
public class LongClickLinkMovementMethod extends LinkMovementMethod { public class LongClickLinkMovementMethod extends LinkMovementMethod {
private static int LONG_CLICK_TIME = 1000;
private static LongClickLinkMovementMethod sInstance; private static LongClickLinkMovementMethod sInstance;
private Handler mLongClickHandler; private Handler mLongClickHandler;
private boolean mIsLongPressed = false; private boolean mIsLongPressed = false;
@ -68,13 +67,11 @@ public class LongClickLinkMovementMethod extends LinkMovementMethod {
Selection.setSelection(buffer, Selection.setSelection(buffer,
buffer.getSpanStart(link[0]), buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0])); buffer.getSpanEnd(link[0]));
mLongClickHandler.postDelayed(new Runnable() { int LONG_CLICK_TIME = 1000;
@Override mLongClickHandler.postDelayed(() -> {
public void run() { link[0].onLongClick(widget);
link[0].onLongClick(widget); mIsLongPressed = true;
mIsLongPressed = true; widget.invalidate();
widget.invalidate();
}
}, LONG_CLICK_TIME); }, LONG_CLICK_TIME);
} }
return true; return true;

View File

@ -5,6 +5,7 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Paint; import android.graphics.Paint;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.KeyEvent; import android.view.KeyEvent;
@ -14,7 +15,6 @@ import android.view.inputmethod.InputConnection;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.DimenRes; import androidx.annotation.DimenRes;
import androidx.annotation.Px; import androidx.annotation.Px;
import androidx.core.os.BuildCompat;
import androidx.core.view.inputmethod.EditorInfoCompat; import androidx.core.view.inputmethod.EditorInfoCompat;
import androidx.core.view.inputmethod.InputConnectionCompat; import androidx.core.view.inputmethod.InputConnectionCompat;
import androidx.core.view.inputmethod.InputContentInfoCompat; import androidx.core.view.inputmethod.InputContentInfoCompat;
@ -39,7 +39,7 @@ public class MastalabAutoCompleteTextView extends androidx.appcompat.widget.AppC
int flags, Bundle opts) { int flags, Bundle opts) {
// read and display inputContentInfo asynchronously // read and display inputContentInfo asynchronously
if (BuildCompat.isAtLeastNMR1() && (flags & if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && (flags &
InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) { InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
try { try {
inputContentInfo.requestPermission(); inputContentInfo.requestPermission();
@ -118,10 +118,12 @@ public class MastalabAutoCompleteTextView extends androidx.appcompat.widget.AppC
this.keyBoardInputCallbackListener = keyBoardInputCallbackListener; this.keyBoardInputCallbackListener = keyBoardInputCallbackListener;
} }
@SuppressWarnings("unused")
public String[] getImgTypeString() { public String[] getImgTypeString() {
return imgTypeString; return imgTypeString;
} }
@SuppressWarnings("unused")
public void setImgTypeString(String[] imgTypeString) { public void setImgTypeString(String[] imgTypeString) {
this.imgTypeString = imgTypeString; this.imgTypeString = imgTypeString;
} }

View File

@ -2,7 +2,6 @@ package app.fedilab.android.helper;
import android.app.Activity; import android.app.Activity;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.Gravity; import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -48,7 +47,8 @@ public class MenuFloating extends com.oguzdev.circularfloatingactionmenu.library
/** /**
* Attaches it to the content view with specified LayoutParams. * Attaches it to the content view with specified LayoutParams.
* *
* @param layoutParams * @param view View
* @param layoutParams ViewGroup.LayoutParams
*/ */
public void attach(View view, ViewGroup.LayoutParams layoutParams) { public void attach(View view, ViewGroup.LayoutParams layoutParams) {
if (this.getParent() != null) if (this.getParent() != null)
@ -57,11 +57,7 @@ public class MenuFloating extends com.oguzdev.circularfloatingactionmenu.library
} }
private void setBackgroundResource(Drawable drawable) { private void setBackgroundResource(Drawable drawable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(drawable);
setBackground(drawable);
} else {
setBackgroundDrawable(drawable);
}
} }
/** /**
@ -85,7 +81,7 @@ public class MenuFloating extends com.oguzdev.circularfloatingactionmenu.library
// Default MenuFloating settings // Default MenuFloating settings
int size = activity.getResources().getDimensionPixelSize(R.dimen.action_button_size); int size = activity.getResources().getDimensionPixelSize(R.dimen.action_button_size);
int margin = activity.getResources().getDimensionPixelSize(R.dimen.action_button_margin); int margin = activity.getResources().getDimensionPixelSize(R.dimen.action_button_margin);
FloatingActionButton.LayoutParams layoutParams = new LayoutParams(size, size, Gravity.BOTTOM | Gravity.RIGHT); FloatingActionButton.LayoutParams layoutParams = new LayoutParams(size, size, Gravity.BOTTOM | Gravity.END);
layoutParams.setMargins(margin, margin, margin, margin); layoutParams.setMargins(margin, margin, margin, margin);
setLayoutParams(layoutParams); setLayoutParams(layoutParams);
setTheme(FloatingActionButton.THEME_LIGHT); setTheme(FloatingActionButton.THEME_LIGHT);
@ -112,9 +108,6 @@ public class MenuFloating extends com.oguzdev.circularfloatingactionmenu.library
return this; return this;
} }
public Builder setBackgroundDrawable(int drawableId) {
return setBackgroundDrawable(activity.getResources().getDrawable(drawableId));
}
public Builder setPosition(int position) { public Builder setPosition(int position) {
this.position = position; this.position = position;

View File

@ -65,6 +65,7 @@ public class ScheduledBoostsSyncJob extends Job {
return jobId; return jobId;
} }
@SuppressWarnings("UnusedReturnValue")
public static int scheduleUpdate(Context context, int tootStoredId, long timestampScheduling) { public static int scheduleUpdate(Context context, int tootStoredId, long timestampScheduling) {
long startMs = (timestampScheduling - new Date().getTime()); long startMs = (timestampScheduling - new Date().getTime());

View File

@ -0,0 +1,39 @@
package app.fedilab.android.services;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of Fedilab
*
* 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.
*
* Fedilab 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 Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class UpgradeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if( intent.getAction() != null && intent.getAction().compareTo(Intent.ACTION_MY_PACKAGE_REPLACED) == 0) {
Intent streamingServiceIntent = new Intent(context, LiveNotificationDelayedService.class);
streamingServiceIntent.putExtra("stop", true);
try {
context.startService(streamingServiceIntent);
} catch (Exception ignored) {}
streamingServiceIntent = new Intent(context, LiveNotificationService.class);
streamingServiceIntent.putExtra("stop", true);
try {
context.startService(streamingServiceIntent);
} catch (Exception ignored) {}
}
}
}

View File

@ -27,6 +27,7 @@
<TextView <TextView
android:id="@+id/media_description" android:id="@+id/media_description"
android:textIsSelectable="true"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom" android:layout_gravity="center_horizontal|bottom"

View File

@ -18,13 +18,14 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="10dp"> android:padding="10dp">
<TextView <TextView
android:labelFor="@+id/add_phrase"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/filter_keyword" /> android:text="@string/filter_keyword" />
@ -41,7 +42,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="text" android:inputType="text"
android:singleLine="true" /> android:singleLine="true"
android:importantForAutofill="no" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -151,8 +153,7 @@
android:id="@+id/filter_expire" android:id="@+id/filter_expire"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="30dp" android:layout_marginStart="30dp" />
android:layout_marginLeft="30dp" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@ -69,6 +69,7 @@
<TextView <TextView
android:id="@+id/notification_account_username" android:id="@+id/notification_account_username"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_marginStart="5dp"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<TextView <TextView

View File

@ -555,11 +555,6 @@
</RelativeLayout> </RelativeLayout>
<app.fedilab.android.webview.CustomWebview
android:id="@+id/status_cardview_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout

View File

@ -479,12 +479,6 @@
android:contentDescription="@string/play_video" android:contentDescription="@string/play_video"
android:src="@drawable/ic_play_arrow" /> android:src="@drawable/ic_play_arrow" />
</RelativeLayout> </RelativeLayout>
<app.fedilab.android.webview.CustomWebview
android:id="@+id/status_cardview_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout

View File

@ -431,11 +431,6 @@
android:src="@drawable/ic_play_arrow" /> android:src="@drawable/ic_play_arrow" />
</RelativeLayout> </RelativeLayout>
<app.fedilab.android.webview.CustomWebview
android:id="@+id/status_cardview_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout

View File

@ -412,12 +412,6 @@
android:src="@drawable/ic_play_arrow" /> android:src="@drawable/ic_play_arrow" />
</RelativeLayout> </RelativeLayout>
<app.fedilab.android.webview.CustomWebview
android:id="@+id/status_cardview_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout

View File

@ -39,6 +39,7 @@
</RelativeLayout> </RelativeLayout>
<FrameLayout <FrameLayout
android:id="@+id/main_media_frame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_centerInParent="true"> android:layout_centerInParent="true">
@ -49,6 +50,12 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:visibility="gone" /> android:visibility="gone" />
</FrameLayout> </FrameLayout>
<RelativeLayout
android:id="@+id/videoLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:visibility="gone" />
<FrameLayout <FrameLayout
android:id="@+id/media_picture_container" android:id="@+id/media_picture_container"

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeBounds/>
<changeImageTransform/>
</transitionSet>

File diff suppressed because it is too large Load Diff

View File

@ -61,67 +61,67 @@
<string name="translate">অনুবাদ</string> <string name="translate">অনুবাদ</string>
<string name="please_wait">অনুগ্রহ করে, এই কাজের জন্য কয়েক সেকেন্ড অপেক্ষা করো।</string> <string name="please_wait">অনুগ্রহ করে, এই কাজের জন্য কয়েক সেকেন্ড অপেক্ষা করো।</string>
<!--- Menu --> <!--- Menu -->
<string name="home_menu">Home</string> <string name="home_menu">মূল পাতা</string>
<string name="local_menu">Local timeline</string> <string name="local_menu">স্থানীয় সময়রেখা</string>
<string name="global_menu">Federated timeline</string> <string name="global_menu">যুক্তবিশ্বের সময়রেখা</string>
<string name="neutral_menu_title">Options</string> <string name="neutral_menu_title">অপশন</string>
<string name="favorites_menu">Favourites</string> <string name="favorites_menu">পছন্দ</string>
<string name="communication_menu_title">Communication</string> <string name="communication_menu_title">যোগাযোগ</string>
<string name="muted_menu">Muted users</string> <string name="muted_menu">নিঃশব্দকৃত ব্যবহারকারী</string>
<string name="blocked_menu">Blocked users</string> <string name="blocked_menu">অবরুদ্ধ ব্যবহারকারী</string>
<string name="notifications">Notifications</string> <string name="notifications">বিজ্ঞপ্তি</string>
<string name="follow_request">Follow requests</string> <string name="follow_request">অনুসরণের অনুরোধ মানো</string>
<string name="settings">Settings</string> <string name="settings">সেটিংস</string>
<string name="delete_account_title">Delete an account</string> <string name="delete_account_title">অ্যাকাউন্ট মুছে ফেলো</string>
<string name="delete_account_message" formatted="false">Delete the account %1$s from the application?</string> <string name="delete_account_message" formatted="false">%1$s অ্যাকাউন্টটি মুছে ফেলো অ্যাপ্লিকেশন থেকে?</string>
<string name="send_email">Send an email</string> <string name="send_email">একটি ইমেইল পাঠাও</string>
<string name="click_to_change">Tap on the path to change it</string> <string name="click_to_change">এটি পরিবর্তন করার জন্য পথে ক্লিক করুন</string>
<string name="failed">Failed!</string> <string name="failed">ব্যর্থ!</string>
<string name="scheduled_toots">Scheduled toots</string> <string name="scheduled_toots">সময় নির্ধারিত টুটগুলি</string>
<string name="disclaimer_full">Information below may reflect the user\'s profile incompletely.</string> <string name="disclaimer_full">নিচের তথ্যগুলো ব্যবহারকারীর প্রোফাইলকে অসম্পূর্ণভাবে প্রতিবিম্বিত করতে পারে।</string>
<string name="insert_emoji">Insert emoji</string> <string name="insert_emoji">ইমোজি ঢোকাও</string>
<string name="no_emoji">The app did not collect custom emojis for the moment.</string> <string name="no_emoji">অ্যাপটি এই মুহুর্তের জন্য কাস্টম ইমোজিগুলি সংগ্রহ করতে পারেনি।</string>
<string name="live_notif">Live notifications</string> <string name="live_notif">লাইভ বিজ্ঞপ্তিগুলি</string>
<string name="logout_confirmation">Are you sure you want to logout?</string> <string name="logout_confirmation">Are you sure you want to logout?</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string> <string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<!-- Status --> <!-- Status -->
<string name="no_status">No toot to display</string> <string name="no_status">প্রদর্শনের জন্য কোনো টুট নেই</string>
<string name="no_stories">No stories to display</string> <string name="no_stories">No stories to display</string>
<string name="stories">Stories</string> <string name="stories">Stories</string>
<string name="reblog_by">Boosted by %1$s</string> <string name="reblog_by">%1$s দ্বারা সমর্থিত</string>
<string name="favourite_add">Add this toot to your favourites?</string> <string name="favourite_add">এই টুটটি তোমার পছন্দগুলোর সাথে যুক্ত করবে?</string>
<string name="favourite_remove">Remove this toot from your favourites?</string> <string name="favourite_remove">তোমার পছন্দগুলো থেকে এই টুট সরাবে?</string>
<string name="reblog_add">Boost this toot?</string> <string name="reblog_add">এই টুটটি সমর্থন করবে?</string>
<string name="reblog_remove">Unboost this toot?</string> <string name="reblog_remove">এই টুটটি অসমর্থন করবে?</string>
<string name="pin_add">Pin this toot?</string> <string name="pin_add">এই টুটটি পিন করবে?</string>
<string name="pin_remove">Unpin this toot?</string> <string name="pin_remove">এই টুটটি আনপিন করবে?</string>
<string name="more_action_1">Mute</string> <string name="more_action_1">নিঃশব্দ</string>
<string name="more_action_2">Block</string> <string name="more_action_2">অবরুদ্ধ</string>
<string name="more_action_3">Report</string> <string name="more_action_3">নিন্দা</string>
<string name="more_action_4">Remove</string> <string name="more_action_4">সরাও</string>
<string name="more_action_5">Copy</string> <string name="more_action_5">অনুলিপি</string>
<string name="more_action_6">Share</string> <string name="more_action_6">শেয়ার</string>
<string name="more_action_7">Mention</string> <string name="more_action_7">উল্লেখ</string>
<string name="more_action_8">Timed mute</string> <string name="more_action_8">নির্দিষ্ট সময়ের জন্য নিঃশব্দ</string>
<string name="more_action_9">Delete &amp; re-draft</string> <string name="more_action_9">মুছে &amp; পুনরায় খসড়া</string>
<string-array name="more_action_confirm"> <string-array name="more_action_confirm">
<item>Mute this account?</item> <item>এই অ্যাকাউন্ট নিঃশব্দ করবে?</item>
<item>Block this account?</item> <item>এই অ্যাকাউন্ট অবরুদ্ধ করবে?</item>
<item>Report this toot?</item> <item>এই টুটটি নিন্দা করবে?</item>
<item>Block this domain?</item> <item>এই ডোমেইন অবরুদ্ধ করবে?</item>
<item>Unmute this account?</item> <item>Unmute this account?</item>
<item>Unblock this account?</item> <item>Unblock this account?</item>
</string-array> </string-array>
<string-array name="action_notification"> <string-array name="action_notification">
<item>Notify</item> <item>বিজ্ঞপ্তি দিবে</item>
<item>Silent</item> <item>নিঃশব্দ থাকবে</item>
</string-array> </string-array>
<string-array name="more_action_owner_confirm"> <string-array name="more_action_owner_confirm">
<item>Remove this toot?</item> <item>এই টুটটি মুছে ফেলবে?</item>
<item>Delete &amp; re-draft this toot?</item> <item>Delete &amp; re-draft this toot?</item>
</string-array> </string-array>
<string name="bookmarks">Bookmarks</string> <string name="bookmarks">বুকমার্ক</string>
<string name="bookmark_add">Add to bookmarks</string> <string name="bookmark_add">বুকমার্কে যোগ করো</string>
<string name="bookmark_remove">Remove bookmark</string> <string name="bookmark_remove">Remove bookmark</string>
<string name="bookmarks_empty">No bookmarks to display</string> <string name="bookmarks_empty">No bookmarks to display</string>
<string name="status_bookmarked">Status has been added to bookmarks!</string> <string name="status_bookmarked">Status has been added to bookmarks!</string>

View File

@ -872,7 +872,7 @@ Ara ja pots connectar-te al compte escrivint <b>%1$s</b> en el primer camp i fen
<string name="set_long_press_media_indication">Guarda els mèdia a mida completa pitjant les previsualitzacions durant un segon</string> <string name="set_long_press_media_indication">Guarda els mèdia a mida completa pitjant les previsualitzacions durant un segon</string>
<string name="set_display_timeline_in_list_indication">Afegeix un botó el·líptic a dalt a la dreta per llistar totes les etiquetes/instàncies/llistes</string> <string name="set_display_timeline_in_list_indication">Afegeix un botó el·líptic a dalt a la dreta per llistar totes les etiquetes/instàncies/llistes</string>
<string name="live_notif_indication">Mantenir connexió oberta a l\'API de streaming per a rebre notificacions m directe.</string> <string name="live_notif_indication">Mantenir connexió oberta a l\'API de streaming per a rebre notificacions m directe.</string>
<string name="set_enable_time_slot_indication">Dins el període definit, l\'app enviarà notificacions. Pots revertir (p. e. silenciar) aquest període amb el spinner adequat.</string> <string name="set_enable_time_slot_indication">Dins el període definit, l\'app enviarà notificacions. Pots revertir (p. e. silenciar) aquest període amb l\'opció pertinent.</string>
<string name="set_display_fedilab_features_button_indication">Mostrar un botó de Fedilab sota la imatge de perfil. És una drecera per accedir a funcions de l\'app.</string> <string name="set_display_fedilab_features_button_indication">Mostrar un botó de Fedilab sota la imatge de perfil. És una drecera per accedir a funcions de l\'app.</string>
<string name="set_quick_reply_indication">Permet de respondre directament dins les pissarres sota les infos d\'estat</string> <string name="set_quick_reply_indication">Permet de respondre directament dins les pissarres sota les infos d\'estat</string>
<string name="set_fit_preview_indication">Les previsualitzacions de les pissarres no es retallaran</string> <string name="set_fit_preview_indication">Les previsualitzacions de les pissarres no es retallaran</string>

View File

@ -110,7 +110,7 @@
<item>このトゥートを報告しますか?</item> <item>このトゥートを報告しますか?</item>
<item>このドメインをブロックしますか?</item> <item>このドメインをブロックしますか?</item>
<item>このアカウントのミュートを解除しますか?</item> <item>このアカウントのミュートを解除しますか?</item>
<item>Unblock this account?</item> <item>このアカウントのブロックを解除しますか?</item>
</string-array> </string-array>
<string-array name="action_notification"> <string-array name="action_notification">
<item>通知</item> <item>通知</item>
@ -984,9 +984,9 @@
<string name="set_nitter">TwitterをNitterに置き換える</string> <string name="set_nitter">TwitterをNitterに置き換える</string>
<string name="set_nitter_indication">Nitterはプライバシーに重点を置いたオープンソースのTwitter代替フロントエンドです。</string> <string name="set_nitter_indication">Nitterはプライバシーに重点を置いたオープンソースのTwitter代替フロントエンドです。</string>
<string name="set_nitter_host">カスタムホストを入力してください。空欄にするとnitter.netが使用されます。</string> <string name="set_nitter_host">カスタムホストを入力してください。空欄にするとnitter.netが使用されます。</string>
<string name="set_bibliogram">Replace Instagram with Bibliogram</string> <string name="set_bibliogram">InstagramをBibliogramに置き換える</string>
<string name="set_bibliogram_indication">Bibliogram is an open source alternative Instagram front-end focused on privacy.</string> <string name="set_bibliogram_indication">Bibliogramはプライバシーを重視したオープンソースのInstagramの代替フロントエンドです。</string>
<string name="set_bibliogram_host">Enter your custom host or leave blank for using bibliogram.art</string> <string name="set_bibliogram_host">カスタムホストを入力してください。空欄にするとbibliogram.artが使用されます。</string>
<string name="set_hide_status_bar">通知バーからFedilabを非表示にする</string> <string name="set_hide_status_bar">通知バーからFedilabを非表示にする</string>
<string name="set_hide_status_bar_indication">ステータスバー上の通知を非表示にするには、目のアイコンボタンをタップして「ステータスバーに表示する」のチェックを外します</string> <string name="set_hide_status_bar_indication">ステータスバー上の通知を非表示にするには、目のアイコンボタンをタップして「ステータスバーに表示する」のチェックを外します</string>
<string name="set_live_type_indication">通知は30秒ごとに遅延が発生します。バッテリーの持ちが改善します。</string> <string name="set_live_type_indication">通知は30秒ごとに遅延が発生します。バッテリーの持ちが改善します。</string>
@ -1105,5 +1105,5 @@
<string name="no_announcements">お知らせはありません!</string> <string name="no_announcements">お知らせはありません!</string>
<string name="add_reaction">リアクションを追加</string> <string name="add_reaction">リアクションを追加</string>
<string name="set_custom_tabs_indication">アプリ内でお気に入りのブラウザを使用します。リンクを外部アプリで開きたい場合はこのチェックを外してください。</string> <string name="set_custom_tabs_indication">アプリ内でお気に入りのブラウザを使用します。リンクを外部アプリで開きたい場合はこのチェックを外してください。</string>
<string name="set_video_cache">Video cache in MB, zero means no cache.</string> <string name="set_video_cache">MB単位での動画キャッシュ、0でキャッシュしません。</string>
</resources> </resources>

View File

@ -59,7 +59,7 @@
<string name="show_replies">Ssekned tiririt</string> <string name="show_replies">Ssekned tiririt</string>
<string name="action_open_in_web">Ldi deg iminig</string> <string name="action_open_in_web">Ldi deg iminig</string>
<string name="translate">Suqel</string> <string name="translate">Suqel</string>
<string name="please_wait">Please, wait few seconds before making this action.</string> <string name="please_wait">Ttxil, rǧu kra n tesenatin uqbel ad txedmeḍ tigawt-a.</string>
<!--- Menu --> <!--- Menu -->
<string name="home_menu">Agegdan</string> <string name="home_menu">Agegdan</string>
<string name="local_menu">Tasuddemt tadigant n yisallen</string> <string name="local_menu">Tasuddemt tadigant n yisallen</string>

View File

@ -82,12 +82,12 @@
<string name="insert_emoji">Emoji toevoegen</string> <string name="insert_emoji">Emoji toevoegen</string>
<string name="no_emoji">De app heeft nog geen lokale emojis verzameld.</string> <string name="no_emoji">De app heeft nog geen lokale emojis verzameld.</string>
<string name="live_notif">Livemeldingen</string> <string name="live_notif">Livemeldingen</string>
<string name="logout_confirmation">Are you sure you want to logout?</string> <string name="logout_confirmation">Weet je zeker dat je wilt uitloggen?</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string> <string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<!-- Status --> <!-- Status -->
<string name="no_status">Geen toot om weer te geven</string> <string name="no_status">Geen toot om weer te geven</string>
<string name="no_stories">No stories to display</string> <string name="no_stories">Geen verhalen om te laten zien</string>
<string name="stories">Stories</string> <string name="stories">Verhalen</string>
<string name="reblog_by">Geboost door %1$s</string> <string name="reblog_by">Geboost door %1$s</string>
<string name="favourite_add">Deze toot aan jouw favorieten toevoegen?</string> <string name="favourite_add">Deze toot aan jouw favorieten toevoegen?</string>
<string name="favourite_remove">Deze toot uit jouw favorieten verwijderen?</string> <string name="favourite_remove">Deze toot uit jouw favorieten verwijderen?</string>
@ -110,7 +110,7 @@
<item>Toot rapporteren?</item> <item>Toot rapporteren?</item>
<item>Dit domein blokkeren?</item> <item>Dit domein blokkeren?</item>
<item>Dit account niet langer negeren?</item> <item>Dit account niet langer negeren?</item>
<item>Unblock this account?</item> <item>Deze rekening deblokkeren?</item>
</string-array> </string-array>
<string-array name="action_notification"> <string-array name="action_notification">
<item>Melden</item> <item>Melden</item>
@ -219,7 +219,7 @@
<string name="notif_reblog">boostte jouw toot</string> <string name="notif_reblog">boostte jouw toot</string>
<string name="notif_favourite">markeerde jouw toot als favoriet</string> <string name="notif_favourite">markeerde jouw toot als favoriet</string>
<string name="notif_follow">volgt jou nu</string> <string name="notif_follow">volgt jou nu</string>
<string name="notif_follow_request">asked to follow you</string> <string name="notif_follow_request">gevraagd om u te volgen</string>
<plurals name="other_notifications"> <plurals name="other_notifications">
<item quantity="one">en één andere melding</item> <item quantity="one">en één andere melding</item>
<item quantity="other">en %d andere meldingen</item> <item quantity="other">en %d andere meldingen</item>
@ -238,7 +238,7 @@
<string name="pinned_toots">Vastgezet</string> <string name="pinned_toots">Vastgezet</string>
<!-- TOAST --> <!-- TOAST -->
<string name="client_error">Niet in staat om client-id te verkrijgen!</string> <string name="client_error">Niet in staat om client-id te verkrijgen!</string>
<string name="connect_error">Unable to connect to instance domain!</string> <string name="connect_error">Niet in staat om verbinding te maken met het instance-domein!</string>
<string name="no_internet">Geen internetverbinding!</string> <string name="no_internet">Geen internetverbinding!</string>
<string name="toast_block">Account is geblokkeerd!</string> <string name="toast_block">Account is geblokkeerd!</string>
<string name="toast_unblock">Account is gedeblokkeerd!</string> <string name="toast_unblock">Account is gedeblokkeerd!</string>
@ -361,7 +361,7 @@
<string name="action_sync">Synchroniseren</string> <string name="action_sync">Synchroniseren</string>
<string name="action_filter">Filter</string> <string name="action_filter">Filter</string>
<string name="owner_cached_toots">Jouw toots</string> <string name="owner_cached_toots">Jouw toots</string>
<string name="owner_cached_notifications">Your notifications</string> <string name="owner_cached_notifications">Uw meldingen</string>
<string name="v_public">Openbaar</string> <string name="v_public">Openbaar</string>
<string name="v_unlisted">Minder openbaar</string> <string name="v_unlisted">Minder openbaar</string>
<string name="v_private">Alleen volgers</string> <string name="v_private">Alleen volgers</string>
@ -374,8 +374,8 @@
<string name="data_backup_success">Er zijn %1$s nieuwe toots geïmporteerd</string> <string name="data_backup_success">Er zijn %1$s nieuwe toots geïmporteerd</string>
<string name="data_backup_notification_success">%1$s new notifications have been imported</string> <string name="data_backup_notification_success">%1$s new notifications have been imported</string>
<string-array name="filter_order"> <string-array name="filter_order">
<item>Dates descending</item> <item>Data aflopend</item>
<item>Dates ascending</item> <item>Data oplopend</item>
</string-array> </string-array>
<string-array name="filter_select"> <string-array name="filter_select">
<item>Nee</item> <item>Nee</item>
@ -430,7 +430,7 @@
<string name="action_lists_delete">Lijst verwijderen</string> <string name="action_lists_delete">Lijst verwijderen</string>
<string name="action_lists_update">Lijst bewerken</string> <string name="action_lists_update">Lijst bewerken</string>
<string name="action_lists_title_placeholder">Naam nieuwe lijst</string> <string name="action_lists_title_placeholder">Naam nieuwe lijst</string>
<string name="action_lists_add_user">The account was added to the list!</string> <string name="action_lists_add_user">Het account is aan de lijst toegevoegd!</string>
<string name="action_lists_empty">You don\'t have any lists yet!</string> <string name="action_lists_empty">You don\'t have any lists yet!</string>
<!-- Migration --> <!-- Migration -->
<string name="account_moved_to">%1$s is naar %2$s verhuisd</string> <string name="account_moved_to">%1$s is naar %2$s verhuisd</string>
@ -1115,10 +1115,10 @@ Je kunt beginnen met typen en er zullen namen gesuggereerd worden.\n\n
<string name="story_indication">Upload a media, it will be automatically added to your Pixelfed story.</string> <string name="story_indication">Upload a media, it will be automatically added to your Pixelfed story.</string>
<string name="added_to_story">Media successfully added to your story!</string> <string name="added_to_story">Media successfully added to your story!</string>
<string name="action_disabled">Action disabled</string> <string name="action_disabled">Action disabled</string>
<string name="action_unfollow">Unfollow</string> <string name="action_unfollow">Ontvouw</string>
<string name="error_destination_path">Something went wrong, please check your download directory in settings.</string> <string name="error_destination_path">Something went wrong, please check your download directory in settings.</string>
<string name="action_announcements">Announcements</string> <string name="action_announcements">Aankondigingen</string>
<string name="no_announcements">No announcements!</string> <string name="no_announcements">Geen mededelingen!</string>
<string name="add_reaction">Add a reaction</string> <string name="add_reaction">Add a reaction</string>
<string name="set_custom_tabs_indication">Use your favourite browser inside the app. Uncheck this feature to open links externally.</string> <string name="set_custom_tabs_indication">Use your favourite browser inside the app. Uncheck this feature to open links externally.</string>
<string name="set_video_cache">Video cache in MB, zero means no cache.</string> <string name="set_video_cache">Video cache in MB, zero means no cache.</string>

View File

@ -928,7 +928,7 @@ Yandex 有適當的隱私權政策可以在這裡找到https://yandex.ru/l
<string name="first_notification_date">第一個通知日期</string> <string name="first_notification_date">第一個通知日期</string>
<string name="last_notification_date">最後通知日期</string> <string name="last_notification_date">最後通知日期</string>
<string name="frequency">頻率</string> <string name="frequency">頻率</string>
<string name="toot_per_day">每日狀態數</string> <string name="toot_per_day">%s 每日狀態數</string>
<string name="notification_per_day">每天 %s 個通知</string> <string name="notification_per_day">每天 %s 個通知</string>
<string name="date_range">日期範圍</string> <string name="date_range">日期範圍</string>
<string name="action_groups">群組</string> <string name="action_groups">群組</string>

View File

@ -1,4 +1,4 @@
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<attr name="cardviewColor" type="color" /> <attr name="cardviewColor" type="color" />
<attr name="iconColor" type="color" /> <attr name="iconColor" type="color" />
@ -24,6 +24,10 @@
<item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Light</item> <item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Light</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="popupWindowStyle">@style/Cyanea.PopupMenu.Light</item> <item name="popupWindowStyle">@style/Cyanea.PopupMenu.Light</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
</style> </style>
<style name="Cyanea.PopupMenu.Light" parent="@style/Widget.AppCompat.PopupMenu"> <style name="Cyanea.PopupMenu.Light" parent="@style/Widget.AppCompat.PopupMenu">
<item name="android:popupBackground">@color/cyanea_primary_dark_reference</item> <item name="android:popupBackground">@color/cyanea_primary_dark_reference</item>
@ -41,6 +45,10 @@
<item name="linkColor">@color/light_link_toot</item> <item name="linkColor">@color/light_link_toot</item>
<item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Light</item> <item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Light</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
</style> </style>
<!-- BLACK theme --> <!-- BLACK theme -->
<style name="AppThemeBlack" parent="Theme.Cyanea.Dark"> <style name="AppThemeBlack" parent="Theme.Cyanea.Dark">
@ -56,6 +64,10 @@
<item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item> <item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="popupWindowStyle">@style/Cyanea.PopupMenu.black</item> <item name="popupWindowStyle">@style/Cyanea.PopupMenu.black</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
</style> </style>
<style name="Cyanea.PopupMenu.black" parent="@style/Widget.AppCompat.PopupMenu"> <style name="Cyanea.PopupMenu.black" parent="@style/Widget.AppCompat.PopupMenu">
<item name="android:popupBackground">@color/cyanea_primary_dark_reference</item> <item name="android:popupBackground">@color/cyanea_primary_dark_reference</item>
@ -73,6 +85,10 @@
<item name="linkColor">@color/black_link_toot</item> <item name="linkColor">@color/black_link_toot</item>
<item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item> <item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
</style> </style>
@ -90,6 +106,10 @@
<item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item> <item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="popupWindowStyle">@style/Cyanea.PopupMenu.Dark</item> <item name="popupWindowStyle">@style/Cyanea.PopupMenu.Dark</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
</style> </style>
<style name="Cyanea.PopupMenu.Dark" parent="@style/Widget.AppCompat.PopupMenu"> <style name="Cyanea.PopupMenu.Dark" parent="@style/Widget.AppCompat.PopupMenu">
<item name="android:popupBackground">@color/cyanea_primary_dark_reference</item> <item name="android:popupBackground">@color/cyanea_primary_dark_reference</item>
@ -107,6 +127,10 @@
<item name="linkColor">@color/dark_link_toot</item> <item name="linkColor">@color/dark_link_toot</item>
<item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item> <item name="android:popupMenuStyle">@style/Fedilab.PopupMenu.Dark</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
</style> </style>
@ -153,6 +177,12 @@
<item name="linkColor">@color/light_link_toot</item> <item name="linkColor">@color/light_link_toot</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="android:windowIsTranslucent">true</item> <item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style> </style>
<style name="TransparentDark" parent="Theme.Cyanea.Dark"> <style name="TransparentDark" parent="Theme.Cyanea.Dark">
@ -163,6 +193,12 @@
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="android:windowIsTranslucent">true</item> <item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style> </style>
<style name="TransparentBlack" parent="Theme.Cyanea.Dark"> <style name="TransparentBlack" parent="Theme.Cyanea.Dark">
@ -174,6 +210,12 @@
<item name="linkColor">@color/black_link_toot</item> <item name="linkColor">@color/black_link_toot</item>
<item name="android:itemBackground">@drawable/menu_selector</item> <item name="android:itemBackground">@drawable/menu_selector</item>
<item name="android:windowIsTranslucent">true</item> <item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
<item name="android:windowSharedElementEnterTransition" tools:ignore="NewApi">@transition/anim</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style> </style>
<style name="Fedilab.PopupMenu.Light" parent="Cyanea.PopupMenu.Light"> <style name="Fedilab.PopupMenu.Light" parent="Cyanea.PopupMenu.Light">

View File

@ -0,0 +1,16 @@
It supports:
- Mastodon, Pleroma, Pixelfed, Peertube, GNU Social, Friendica.
The app has advanced features (especially for Pleroma and Mastodon):
- Multi-accounts support
- Schedule messages from the device
- Schedule boosts
- Bookmark messages
- Follow and interact with remote instances
- Timed mute accounts
- Cross-account actions with a long press
- Translation feature
- Art timelines
- Video timelines

View File

@ -0,0 +1 @@
Fedilab is a multifunctional Android client to access the distributed Fediverse, consisting of micro blogging, photo sharing and video hosting.

View File

@ -0,0 +1,4 @@
Fixed:
- Issue with not clickable URLs
- Custom emoji in polls not displayed
- Auto-split toots feature

View File

@ -0,0 +1,18 @@
Added:
- Select text for media description
changed:
- Increase media description length to 1500 chars
- More details about accounts in notifications
- Media management in timelines
- Allow cross-account replies on followed instances
Fixed:
- Remove extra spaces at the bottom of messages
- Some issue with custom emoji
- Fix issue with "Your toots/notifications"
- Fix issue with CW and Pixelfed
- Fix some media not loaded in profiles
- Scheduled toots from server side have an incorrect date
- Incorrect feeds when checking instance admin account
- Some crashes

View File

@ -0,0 +1,19 @@
Added:
- Select text for media description
changed:
- Increase media description length to 1500 chars
- More details about accounts in notifications
- Media management in timelines
- Allow cross-account replies on followed instances
Fixed:
- Crash when adding media
- Remove extra spaces at the bottom of messages
- Some issue with custom emoji
- Fix issue with "Your toots/notifications"
- Fix issue with CW and Pixelfed
- Fix some media not loaded in profiles
- Scheduled toots from server side have an incorrect date
- Incorrect feeds when checking instance admin account
- Some crashes