Long press
This commit is contained in:
parent
1f4e88957d
commit
315f1f3dee
|
@ -37,6 +37,7 @@ import android.os.Handler;
|
|||
import android.os.Parcelable;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Patterns;
|
||||
import android.view.ActionMode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
@ -1704,6 +1705,19 @@ public abstract class BaseMainActivity extends BaseActivity
|
|||
|
||||
}
|
||||
|
||||
|
||||
public static boolean canShowActionMode = true;
|
||||
|
||||
|
||||
@Override
|
||||
public void onActionModeStarted(ActionMode mode) {
|
||||
if (!canShowActionMode) {
|
||||
mode.finish();
|
||||
}
|
||||
super.onActionModeStarted(mode);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
|
|
@ -63,6 +63,10 @@ public class LiveNotificationSettingsAccountsActivity extends BaseActivity {
|
|||
ArrayList<Account> accounts = new ArrayList<>();
|
||||
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||
List<Account> accountStreams = new AccountDAO(getApplicationContext(), db).getAllAccountCrossAction();
|
||||
if( accountStreams == null || accountStreams.size() == 0 ){
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
for (Account account : accountStreams) {
|
||||
if (account.getSocial() == null || account.getSocial().equals("MASTODON") || account.getSocial().equals("PLEROMA") || account.getSocial().equals("PIXELFED")) {
|
||||
accounts.add(account);
|
||||
|
|
|
@ -16,7 +16,10 @@ package app.fedilab.android.client.Entities;
|
|||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -38,10 +41,14 @@ import android.text.style.ImageSpan;
|
|||
import android.text.style.QuoteSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.util.Patterns;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
|
@ -70,6 +77,7 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.BaseMainActivity;
|
||||
import app.fedilab.android.activities.GroupActivity;
|
||||
import app.fedilab.android.activities.HashTagActivity;
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
|
@ -77,14 +85,20 @@ import app.fedilab.android.activities.PeertubeActivity;
|
|||
import app.fedilab.android.activities.ShowAccountActivity;
|
||||
import app.fedilab.android.asynctasks.RetrieveFeedsAsyncTask;
|
||||
import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask;
|
||||
import app.fedilab.android.fragments.TabLayoutNotificationsFragment;
|
||||
import app.fedilab.android.helper.CrossActions;
|
||||
import app.fedilab.android.helper.CustomQuoteSpan;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.LongClickLinkMovementMethod;
|
||||
import app.fedilab.android.helper.LongClickableSpan;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.interfaces.OnRetrieveEmojiInterface;
|
||||
import app.fedilab.android.interfaces.OnRetrieveImageInterface;
|
||||
import app.fedilab.android.sqlite.StatusStoredDAO;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static app.fedilab.android.activities.BaseMainActivity.mPageReferenceMap;
|
||||
import static app.fedilab.android.drawers.StatusListAdapter.COMPACT_STATUS;
|
||||
import static app.fedilab.android.drawers.StatusListAdapter.CONSOLE_STATUS;
|
||||
import static app.fedilab.android.drawers.StatusListAdapter.DISPLAYED_STATUS;
|
||||
|
@ -601,58 +615,122 @@ public class Status implements Parcelable {
|
|||
endPosition = startPosition + key.length();
|
||||
}
|
||||
if (endPosition <= spannableStringT.toString().length() && endPosition >= startPosition) {
|
||||
spannableStringT.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull View textView) {
|
||||
String finalUrl = url;
|
||||
Pattern link = Pattern.compile("https?:\\/\\/([\\da-z\\.-]+\\.[a-z\\.]{2,10})\\/(@[\\w._-]*[0-9]*)(\\/[0-9]{1,})?$");
|
||||
Matcher matcherLink = link.matcher(url);
|
||||
if (matcherLink.find() && !url.contains("medium.com")) {
|
||||
if (matcherLink.group(3) != null && matcherLink.group(3).length() > 0) { //It's a toot
|
||||
CrossActions.doCrossConversation(context, finalUrl);
|
||||
} else {//It's an account
|
||||
Account account = new Account();
|
||||
String acct = matcherLink.group(2);
|
||||
if (acct != null) {
|
||||
if (acct.startsWith("@"))
|
||||
acct = acct.substring(1);
|
||||
account.setAcct(acct);
|
||||
account.setInstance(matcherLink.group(1));
|
||||
CrossActions.doCrossProfile(context, account);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
link = Pattern.compile("(https?:\\/\\/[\\da-z\\.-]+\\.[a-z\\.]{2,10})\\/videos\\/watch\\/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$");
|
||||
matcherLink = link.matcher(url);
|
||||
if (matcherLink.find()) { //Peertubee video
|
||||
Intent intent = new Intent(context, PeertubeActivity.class);
|
||||
Bundle b = new Bundle();
|
||||
String url = matcherLink.group(1) + "/videos/watch/" + matcherLink.group(2);
|
||||
b.putString("peertubeLinkToFetch", url);
|
||||
b.putString("peertube_instance", matcherLink.group(1).replace("https://", "").replace("http://", ""));
|
||||
b.putString("video_id", matcherLink.group(2));
|
||||
intent.putExtras(b);
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
|
||||
finalUrl = "http://" + url;
|
||||
Helper.openBrowser(context, finalUrl);
|
||||
}
|
||||
|
||||
spannableStringT.setSpan(new LongClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull View textView) {
|
||||
String finalUrl = url;
|
||||
Pattern link = Pattern.compile("https?:\\/\\/([\\da-z\\.-]+\\.[a-z\\.]{2,10})\\/(@[\\w._-]*[0-9]*)(\\/[0-9]{1,})?$");
|
||||
Matcher matcherLink = link.matcher(url);
|
||||
if (matcherLink.find() && !url.contains("medium.com")) {
|
||||
if (matcherLink.group(3) != null && matcherLink.group(3).length() > 0) { //It's a toot
|
||||
CrossActions.doCrossConversation(context, finalUrl);
|
||||
} else {//It's an account
|
||||
Account account = new Account();
|
||||
String acct = matcherLink.group(2);
|
||||
if (acct != null) {
|
||||
if (acct.startsWith("@"))
|
||||
acct = acct.substring(1);
|
||||
account.setAcct(acct);
|
||||
account.setInstance(matcherLink.group(1));
|
||||
CrossActions.doCrossProfile(context, account);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setUnderlineText(false);
|
||||
ds.setColor(link_color);
|
||||
} else {
|
||||
link = Pattern.compile("(https?:\\/\\/[\\da-z\\.-]+\\.[a-z\\.]{2,10})\\/videos\\/watch\\/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$");
|
||||
matcherLink = link.matcher(url);
|
||||
if (matcherLink.find()) { //Peertubee video
|
||||
Intent intent = new Intent(context, PeertubeActivity.class);
|
||||
Bundle b = new Bundle();
|
||||
String url = matcherLink.group(1) + "/videos/watch/" + matcherLink.group(2);
|
||||
b.putString("peertubeLinkToFetch", url);
|
||||
b.putString("peertube_instance", matcherLink.group(1).replace("https://", "").replace("http://", ""));
|
||||
b.putString("video_id", matcherLink.group(2));
|
||||
intent.putExtras(b);
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
|
||||
finalUrl = "http://" + url;
|
||||
Helper.openBrowser(context, finalUrl);
|
||||
}
|
||||
},
|
||||
startPosition, endPosition,
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongClick(@NonNull View textView) {
|
||||
PopupMenu popup = new PopupMenu(context, textView);
|
||||
popup.getMenuInflater()
|
||||
.inflate(R.menu.links_popup, popup.getMenu());
|
||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_show_link:
|
||||
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
|
||||
int style;
|
||||
if (theme == Helper.THEME_DARK) {
|
||||
style = R.style.DialogDark;
|
||||
} else if (theme == Helper.THEME_BLACK) {
|
||||
style = R.style.DialogBlack;
|
||||
} else {
|
||||
style = R.style.Dialog;
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context, style);
|
||||
builder.setMessage(url);
|
||||
builder.setTitle(context.getString(R.string.display_full_link));
|
||||
builder.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
break;
|
||||
case R.id.action_share_link:
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
sendIntent.setType("text/plain");
|
||||
context.startActivity(Intent.createChooser(sendIntent, context.getString(R.string.share_with)));
|
||||
break;
|
||||
case R.id.action_copy_link:
|
||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, url);
|
||||
if (clipboard != null) {
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(PopupMenu menu) {
|
||||
BaseMainActivity.canShowActionMode = true;
|
||||
}
|
||||
});
|
||||
popup.show();
|
||||
BaseMainActivity.canShowActionMode = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setUnderlineText(false);
|
||||
ds.setColor(link_color);
|
||||
}
|
||||
},
|
||||
startPosition, endPosition,
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
it.remove();
|
||||
|
|
|
@ -152,6 +152,7 @@ import app.fedilab.android.fragments.DisplayStatusFragment;
|
|||
import app.fedilab.android.helper.CrossActions;
|
||||
import app.fedilab.android.helper.CustomTextView;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.LongClickLinkMovementMethod;
|
||||
import app.fedilab.android.helper.MastalabAutoCompleteTextView;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.interfaces.OnPollInterface;
|
||||
|
@ -1530,7 +1531,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
}
|
||||
|
||||
|
||||
holder.status_content.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
holder.status_content.setMovementMethod(LongClickLinkMovementMethod.getInstance());
|
||||
holder.status_spoiler.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
if (truncate_toots_size > 0) {
|
||||
holder.status_content.setMaxLines(truncate_toots_size);
|
||||
|
|
|
@ -831,7 +831,9 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
|
||||
|
||||
public void scrollToTop() {
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
if( mLayoutManager != null ) {
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package app.fedilab.android.helper;
|
||||
|
||||
|
||||
import android.os.Handler;
|
||||
import android.text.Layout;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.method.MovementMethod;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
//https://stackoverflow.com/a/20435892
|
||||
public class LongClickLinkMovementMethod extends LinkMovementMethod {
|
||||
|
||||
private Handler mLongClickHandler;
|
||||
private static int LONG_CLICK_TIME = 1000;
|
||||
private boolean mIsLongPressed = false;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(final TextView widget, Spannable buffer,
|
||||
MotionEvent event) {
|
||||
int action = event.getAction();
|
||||
if(action == MotionEvent.ACTION_CANCEL){
|
||||
if(mLongClickHandler!=null){
|
||||
mLongClickHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (action == MotionEvent.ACTION_UP ||
|
||||
action == MotionEvent.ACTION_DOWN) {
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
|
||||
x -= widget.getTotalPaddingLeft();
|
||||
y -= widget.getTotalPaddingTop();
|
||||
|
||||
x += widget.getScrollX();
|
||||
y += widget.getScrollY();
|
||||
|
||||
Layout layout = widget.getLayout();
|
||||
int line = layout.getLineForVertical(y);
|
||||
int off = layout.getOffsetForHorizontal(line, x);
|
||||
|
||||
final LongClickableSpan[] link = buffer.getSpans(off, off, LongClickableSpan.class);
|
||||
|
||||
if (link.length != 0) {
|
||||
if (action == MotionEvent.ACTION_UP) {
|
||||
if(mLongClickHandler!=null){
|
||||
mLongClickHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
if(!mIsLongPressed) {
|
||||
link[0].onClick(widget);
|
||||
}
|
||||
mIsLongPressed = false;
|
||||
} else {
|
||||
Selection.setSelection(buffer,
|
||||
buffer.getSpanStart(link[0]),
|
||||
buffer.getSpanEnd(link[0]));
|
||||
mLongClickHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
link[0].onLongClick(widget);
|
||||
mIsLongPressed = true;
|
||||
widget.invalidate();
|
||||
}
|
||||
},LONG_CLICK_TIME);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.onTouchEvent(widget, buffer, event);
|
||||
}
|
||||
|
||||
|
||||
public static MovementMethod getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new LongClickLinkMovementMethod();
|
||||
sInstance.mLongClickHandler = new Handler();
|
||||
}
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
private static LongClickLinkMovementMethod sInstance;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package app.fedilab.android.helper;
|
||||
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.view.View;
|
||||
|
||||
public abstract class LongClickableSpan extends ClickableSpan {
|
||||
|
||||
abstract public void onLongClick(View view);
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
>
|
||||
<item
|
||||
android:id="@+id/action_show_link"
|
||||
android:title="@string/display_full_link"
|
||||
/>
|
||||
<item
|
||||
android:id="@+id/action_share_link"
|
||||
android:title="@string/share_link"
|
||||
/>
|
||||
<item
|
||||
android:id="@+id/action_copy_link"
|
||||
android:title="@string/copy_link"
|
||||
/>
|
||||
</menu>
|
|
@ -1190,4 +1190,7 @@
|
|||
<string name="release_note_title">What\'s new in %s</string>
|
||||
<string name="follow_account_update">You can follow my account for updates</string>
|
||||
<string name="no_instance_reccord">This instance is not available on https://instances.social</string>
|
||||
<string name="display_full_link">Display full link</string>
|
||||
<string name="share_link">Share link</string>
|
||||
<string name="link_copy">The URL has been copied to the clipboard</string>
|
||||
</resources>
|
Loading…
Reference in New Issue