diff options
Diffstat (limited to 'app/src/main/java/app')
40 files changed, 547 insertions, 193 deletions
diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java index 4cadc14f2..850de4dec 100644 --- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java +++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java @@ -36,6 +36,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.content.res.Configuration; import android.database.MatrixCursor; import android.graphics.PorterDuff; import android.graphics.drawable.BitmapDrawable; @@ -214,6 +215,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt public static BaseAccount currentAccount; public static iconLauncher mLauncher = iconLauncher.BUBBLES; public static boolean headerMenuOpen; + public static int currentNightMode; Fragment currentFragment; private AppBarConfiguration mAppBarConfiguration; private ActivityMainBinding binding; @@ -1859,9 +1861,12 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt @Override protected void onDestroy() { - unregisterReceiver(broadcast_data); - unregisterReceiver(broadcast_error_message); - + try { + unregisterReceiver(broadcast_data); + unregisterReceiver(broadcast_error_message); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } if (networkStateReceiver != null) { try { unregisterReceiver(networkStateReceiver); diff --git a/app/src/main/java/app/fedilab/android/activities/AboutActivity.java b/app/src/main/java/app/fedilab/android/activities/AboutActivity.java index 2ea60818d..209351fc8 100644 --- a/app/src/main/java/app/fedilab/android/activities/AboutActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/AboutActivity.java @@ -15,12 +15,16 @@ package app.fedilab.android.activities; * see <http://www.gnu.org/licenses>. */ +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.MenuItem; import android.view.View; +import android.widget.Toast; import androidx.core.app.ActivityOptionsCompat; import androidx.lifecycle.ViewModelProvider; @@ -40,6 +44,7 @@ import app.fedilab.android.mastodon.helper.CrossActionHelper; import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.MastodonHelper; import app.fedilab.android.mastodon.viewmodel.mastodon.AccountsVM; +import es.dmoral.toasty.Toasty; public class AboutActivity extends BaseBarActivity { @@ -58,10 +63,10 @@ public class AboutActivity extends BaseBarActivity { if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } - + String version = ""; try { PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0); - String version = pInfo.versionName; + version = pInfo.versionName; binding.aboutVersion.setText(getResources().getString(R.string.about_vesrion, version)); } catch (PackageManager.NameNotFoundException ignored) { } @@ -77,6 +82,20 @@ public class AboutActivity extends BaseBarActivity { } binding.aboutSupportPaypal.setOnClickListener(v -> Helper.openBrowser(AboutActivity.this, "https://www.paypal.me/Mastalab")); + + String finalVersion = version; + binding.aboutVersionCopy.setOnClickListener(v->{ + + ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + String content = "Fedilab v" + finalVersion + " for " + (BuildConfig.DONATIONS?"FDroid":"Google"); + + ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, content); + if (clipboard != null) { + clipboard.setPrimaryClip(clip); + Toasty.info(AboutActivity.this, getString(R.string.clipboard_version), Toast.LENGTH_LONG).show(); + } + + }); if (BuildConfig.DONATIONS) { binding.aboutSupportPaypal.setVisibility(View.VISIBLE); } else { diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/BaseActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/BaseActivity.java index 963f7a338..6ab76c086 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/BaseActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/BaseActivity.java @@ -15,6 +15,8 @@ package app.fedilab.android.mastodon.activities; * see <http://www.gnu.org/licenses>. */ +import static app.fedilab.android.BaseMainActivity.currentNightMode; + import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; @@ -37,6 +39,7 @@ import org.conscrypt.Conscrypt; import java.security.Security; +import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.ThemeHelper; @@ -70,7 +73,7 @@ public class BaseActivity extends AppCompatActivity { String currentTheme = sharedpreferences.getString(getString(R.string.SET_THEME_BASE), getString(R.string.SET_DEFAULT_THEME)); //Default automatic switch - int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; + currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; if (currentTheme.equals(getString(R.string.SET_DEFAULT_THEME))) { switch (currentNightMode) { case Configuration.UI_MODE_NIGHT_NO -> { diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/BaseBarActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/BaseBarActivity.java index eb50d386e..6a1dc0fad 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/BaseBarActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/BaseBarActivity.java @@ -15,6 +15,8 @@ package app.fedilab.android.mastodon.activities; * see <http://www.gnu.org/licenses>. */ +import static app.fedilab.android.BaseMainActivity.currentNightMode; + import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; @@ -65,7 +67,7 @@ public class BaseBarActivity extends AppCompatActivity { } String currentTheme = sharedpreferences.getString(getString(R.string.SET_THEME_BASE), getString(R.string.SET_DEFAULT_THEME)); //Default automatic switch - int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; + currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; if (currentTheme.equals(getString(R.string.SET_DEFAULT_THEME))) { switch (currentNightMode) { case Configuration.UI_MODE_NIGHT_NO -> { diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/BaseTransparentActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/BaseTransparentActivity.java index 6da2715e7..28f76db53 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/BaseTransparentActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/BaseTransparentActivity.java @@ -15,6 +15,8 @@ package app.fedilab.android.mastodon.activities; * see <http://www.gnu.org/licenses>. */ +import static app.fedilab.android.BaseMainActivity.currentNightMode; + import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; @@ -65,7 +67,7 @@ public class BaseTransparentActivity extends AppCompatActivity { } String currentTheme = sharedpreferences.getString(getString(R.string.SET_THEME_BASE), getString(R.string.SET_DEFAULT_THEME)); //Default automatic switch - int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; + currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; if (currentTheme.equals(getString(R.string.SET_DEFAULT_THEME))) { switch (currentNightMode) { diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java index cf9c72f5c..6d9c24d59 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java @@ -195,8 +195,11 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana if (timer != null) { timer.cancel(); } - unregisterReceiver(imageReceiver); - + try { + unregisterReceiver(imageReceiver); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } } diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/ContextActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/ContextActivity.java index 7d9390c7e..a166587f6 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/ContextActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/ContextActivity.java @@ -113,6 +113,12 @@ public class ContextActivity extends BaseActivity implements FragmentMastodonCon } } + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.clear(); + } + private void loadLocalConversation() { Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_STATUS, focusedStatus); diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/FollowedTagActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/FollowedTagActivity.java index 79ef02284..9b75fe471 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/FollowedTagActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/FollowedTagActivity.java @@ -32,11 +32,15 @@ import androidx.recyclerview.widget.LinearLayoutManager; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.databinding.ActivityFollowedTagsBinding; import app.fedilab.android.databinding.PopupAddFollowedTagtBinding; +import app.fedilab.android.mastodon.client.entities.api.MastodonList; import app.fedilab.android.mastodon.client.entities.api.Tag; import app.fedilab.android.mastodon.client.entities.app.Timeline; import app.fedilab.android.mastodon.helper.Helper; @@ -74,6 +78,7 @@ public class FollowedTagActivity extends BaseBarActivity implements FollowedTagA .observe(FollowedTagActivity.this, tags -> { if (tags != null && tags.tags != null && tags.tags.size() > 0) { tagList = new ArrayList<>(tags.tags); + sortAsc(tagList); followedTagAdapter = new FollowedTagAdapter(tagList); followedTagAdapter.actionOnTag = this; binding.notContent.setVisibility(View.GONE); @@ -95,6 +100,8 @@ public class FollowedTagActivity extends BaseBarActivity implements FollowedTagA }); setTitle(R.string.followed_tags); invalidateOptionsMenu(); + } else { + finish(); } } }); @@ -143,6 +150,11 @@ public class FollowedTagActivity extends BaseBarActivity implements FollowedTagA dialogBuilder.setView(popupAddFollowedTagtBinding.getRoot()); popupAddFollowedTagtBinding.addTag.setFilters(new InputFilter[]{new InputFilter.LengthFilter(255)}); dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> { + String name = Objects.requireNonNull(popupAddFollowedTagtBinding.addTag.getText()).toString().trim(); + if(tagList.contains(new Tag(name))) { + Toasty.error(FollowedTagActivity.this, getString(R.string.tag_already_followed), Toasty.LENGTH_LONG).show(); + return; + } if (popupAddFollowedTagtBinding.addTag.getText() != null && popupAddFollowedTagtBinding.addTag.getText().toString().trim().length() > 0) { tagVM.follow(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, popupAddFollowedTagtBinding.addTag.getText().toString().trim()) .observe(FollowedTagActivity.this, newTag -> { @@ -159,8 +171,10 @@ public class FollowedTagActivity extends BaseBarActivity implements FollowedTagA if (newTag != null) { tagList.add(0, newTag); followedTagAdapter.notifyItemInserted(0); + sortAsc(tagList); + followedTagAdapter.notifyItemRangeChanged(0, tagList.size()); } else { - Toasty.error(FollowedTagActivity.this, getString(R.string.toast_feature_not_supported), Toasty.LENGTH_LONG).show(); + Toasty.error(FollowedTagActivity.this, getString(R.string.not_valid_tag_name), Toasty.LENGTH_LONG).show(); } }); dialog.dismiss(); @@ -175,6 +189,9 @@ public class FollowedTagActivity extends BaseBarActivity implements FollowedTagA return super.onOptionsItemSelected(item); } + private void sortAsc(List<Tag> tagList) { + Collections.sort(tagList, (obj1, obj2) -> obj1.name.compareToIgnoreCase(obj2.name)); + } @Override public boolean onCreateOptionsMenu(@NonNull Menu menu) { diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/MastodonListActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/MastodonListActivity.java index 5d9f3ac94..0be0a8ca5 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/MastodonListActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/MastodonListActivity.java @@ -143,6 +143,8 @@ public class MastodonListActivity extends BaseBarActivity implements MastodonLis }); setTitle(R.string.action_lists); invalidateOptionsMenu(); + } else { + finish(); } } }); diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/MediaActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/MediaActivity.java index ca082b023..39da17134 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/MediaActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/MediaActivity.java @@ -14,6 +14,8 @@ package app.fedilab.android.mastodon.activities; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see <http://www.gnu.org/licenses>. */ +import static android.util.Patterns.WEB_URL; + import android.Manifest; import android.app.DownloadManager; import android.content.BroadcastReceiver; @@ -21,12 +23,18 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.text.method.ScrollingMovementMethod; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -34,6 +42,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -42,11 +51,13 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.preference.PreferenceManager; import androidx.viewpager.widget.ViewPager; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.regex.Matcher; import app.fedilab.android.R; import app.fedilab.android.databinding.ActivityMediaPagerBinding; @@ -152,8 +163,8 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload }); } - binding.mediaDescription.setMovementMethod(new ScrollingMovementMethod()); - binding.mediaDescriptionTranslated.setMovementMethod(new ScrollingMovementMethod()); + binding.mediaDescription.setMovementMethod(LinkMovementMethod.getInstance()); + binding.mediaDescriptionTranslated.setMovementMethod(LinkMovementMethod.getInstance()); if (description != null && description.trim().length() > 0 && description.trim().compareTo("null") != 0) { binding.mediaDescription.setText(description); @@ -195,7 +206,7 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload } handler = new Handler(); if (description != null && description.trim().length() > 0 && description.trim().compareTo("null") != 0) { - binding.mediaDescription.setText(description); + binding.mediaDescription.setText(linkify(MediaActivity.this, description), TextView.BufferType.SPANNABLE); } binding.translate.setOnClickListener(v -> { String descriptionToTranslate = attachments.get(position).description; @@ -228,6 +239,40 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload setFullscreen(true); } + private Spannable linkify(Context context, String content) { + if(content == null) { + return new SpannableString(""); + } + Matcher matcher = WEB_URL.matcher(content); + Spannable contentSpan = new SpannableString(content); + SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context); + boolean underlineLinks = sharedpreferences.getBoolean(context.getString(R.string.SET_UNDERLINE_CLICKABLE), false); + + + while (matcher.find()) { + int matchStart = matcher.start(); + int matchEnd = matcher.end(); + String url = content.substring(matchStart, matchEnd); + if (matchStart >= 0 && matchEnd <= content.length() && matchEnd >= matchStart) { + contentSpan.setSpan(new ClickableSpan() { + @Override + public void onClick(@NonNull View textView) { + Helper.openBrowser(context, url); + } + + @Override + public void updateDrawState(@NonNull TextPaint ds) { + super.updateDrawState(ds); + if(!underlineLinks) { + ds.setUnderlineText(status != null && status.underlined); + } + } + }, matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + } + return contentSpan; + } + @Override public boolean dispatchTouchEvent(MotionEvent event) { try { @@ -337,7 +382,7 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload if (!fullscreen) { String description = attachments.get(binding.mediaViewpager.getCurrentItem()).description; if (description != null && description.trim().length() > 0 && description.trim().compareTo("null") != 0) { - binding.mediaDescription.setText(description); + binding.mediaDescription.setText(linkify(MediaActivity.this, description), TextView.BufferType.SPANNABLE); if (attachments.get(binding.mediaViewpager.getCurrentItem()).translation != null) { binding.mediaDescription.setVisibility(View.GONE); binding.mediaDescriptionTranslated.setText(attachments.get(binding.mediaViewpager.getCurrentItem()).translation); @@ -367,7 +412,11 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload @Override public void onDestroy() { - unregisterReceiver(onDownloadComplete); + try { + unregisterReceiver(onDownloadComplete); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } super.onDestroy(); } diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/ProfileActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/ProfileActivity.java index ddc779bb8..336f47c51 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/ProfileActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/ProfileActivity.java @@ -234,6 +234,12 @@ public class ProfileActivity extends BaseActivity { } } + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.clear(); + } + private void initializeView(Account account) { SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ProfileActivity.this); if (account == null) { @@ -1260,7 +1266,11 @@ public class ProfileActivity extends BaseActivity { scheduledExecutorService.shutdownNow(); scheduledExecutorService = null; } - unregisterReceiver(broadcast_data); + try { + unregisterReceiver(broadcast_data); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } super.onDestroy(); } diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/admin/AdminActionActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/admin/AdminActionActivity.java index 005af5d35..b84354b90 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/admin/AdminActionActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/admin/AdminActionActivity.java @@ -116,6 +116,8 @@ public class AdminActionActivity extends BaseBarActivity { setTitle(R.string.administration); invalidateOptionsMenu(); }); + } else { + finish(); } } }); @@ -340,7 +342,11 @@ public class AdminActionActivity extends BaseBarActivity { protected void onDestroy() { super.onDestroy(); if (mReceiver != null) { - unregisterReceiver(mReceiver); + try { + unregisterReceiver(mReceiver); + } catch (IllegalArgumentException e) { + |