Clipboard management refactor, kill all tips when copy to clipboard on Tiramisu above
This commit is contained in:
1 parent
a343dbe8f8
commit
9eee6fc4af
9 files changed
+55
-136
No files matched your search
@@ -68,7 +68,6 @@ import com.hippo.network.StatusCodeException;
|
||||
import com.hippo.scene.SceneApplication;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.BitmapUtils;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.IoThreadPoolExecutor;
|
||||
import com.hippo.util.ReadableTime;
|
||||
@@ -329,7 +328,6 @@ public class EhApplication extends SceneApplication {
|
||||
super.onCreate();
|
||||
|
||||
Native.initialize();
|
||||
ClipboardUtil.initialize(this);
|
||||
GetText.initialize(this);
|
||||
StatusCodeException.initialize(this);
|
||||
Settings.initialize(this);
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
package com.hippo.ehviewer.preference
|
||||
|
||||
import android.content.*
|
||||
import android.os.Build
|
||||
import android.os.PersistableBundle
|
||||
import android.text.Html
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
@@ -29,6 +27,8 @@ import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.ui.SettingsActivity
|
||||
import com.hippo.ehviewer.ui.scene.BaseScene
|
||||
import com.hippo.preference.MessagePreference
|
||||
import com.hippo.util.addTextToClipboard
|
||||
import com.hippo.util.getClipboardManager
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import java.util.*
|
||||
@@ -81,20 +81,9 @@ class AccountPreference @JvmOverloads constructor(
|
||||
super.onPrepareDialogBuilder(builder)
|
||||
if (message != null) {
|
||||
builder.setNeutralButton(R.string.settings_eh_identity_cookies_copy) { dialog: DialogInterface?, which: Int ->
|
||||
val clipboardManager =
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
|
||||
val clipData = ClipData.newPlainText(null, message)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
clipData.apply {
|
||||
description.extras = PersistableBundle().apply {
|
||||
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
|
||||
}
|
||||
}
|
||||
clipboardManager?.setPrimaryClip(clipData)
|
||||
|
||||
// There is no need to notify user by toast since Tiramisu have its clipboard own logic
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
|
||||
context.getClipboardManager().addTextToClipboard(message, true) {
|
||||
mActivity.showTip(R.string.copied_to_clipboard, BaseScene.LENGTH_SHORT)
|
||||
}
|
||||
this@AccountPreference.onClick(dialog, which)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.scene.StageActivity;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.BitmapUtils;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.widget.DrawerView;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
@@ -259,7 +259,7 @@ public final class MainActivity extends StageActivity
|
||||
String url = intent.getData().toString();
|
||||
new EditTextDialogBuilder(this, url, "")
|
||||
.setTitle(R.string.error_cannot_parse_the_url)
|
||||
.setPositiveButton(android.R.string.copy, (dialog, which) -> ClipboardUtil.addTextToClipboard(url))
|
||||
.setPositiveButton(android.R.string.copy, (dialog, which) -> ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(this), url, false, () -> null))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -456,7 +456,7 @@ public final class MainActivity extends StageActivity
|
||||
}
|
||||
|
||||
private void checkClipboardUrlInternal() {
|
||||
String text = ClipboardUtil.getUrlFromClipboard();
|
||||
String text = ClipboardUtilKt.getUrlFromClipboard(ClipboardUtilKt.getClipboardManager(this), this);
|
||||
int hashCode = text != null ? text.hashCode() : 0;
|
||||
|
||||
if (text != null && hashCode != 0 && Settings.getClipboardTextHashCode() != hashCode) {
|
||||
|
||||
@@ -42,6 +42,8 @@ import androidx.fragment.app.FragmentActivity;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
public abstract class BaseScene extends SceneFragment {
|
||||
|
||||
public static final int LENGTH_SHORT = 0;
|
||||
@@ -106,11 +108,12 @@ public abstract class BaseScene extends SceneFragment {
|
||||
}
|
||||
}
|
||||
|
||||
public void showTip(@StringRes int id, int length) {
|
||||
public Unit showTip(@StringRes int id, int length) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof MainActivity) {
|
||||
((MainActivity) activity).showTip(id, length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean needShowLeftDrawer() {
|
||||
|
||||
@@ -38,7 +38,7 @@ import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhCookieStore;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
@@ -253,7 +253,7 @@ public class CookieSignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
|
||||
private void fillCookiesFromClipboard() {
|
||||
hideSoftInput();
|
||||
String text = ClipboardUtil.getTextFromClipboard();
|
||||
String text = ClipboardUtilKt.getTextFromClipboard(ClipboardUtilKt.getClipboardManager(getContext()), getContext());
|
||||
if (text == null) {
|
||||
showTip(R.string.from_clipboard_error, LENGTH_SHORT);
|
||||
return;
|
||||
|
||||
@@ -72,7 +72,7 @@ import com.hippo.ehviewer.client.parser.VoteCommentParser;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.text.URLImageGetter;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.ReadableTime;
|
||||
import com.hippo.util.TextUrl;
|
||||
@@ -354,8 +354,7 @@ public final class GalleryCommentsScene extends ToolbarScene
|
||||
}
|
||||
int id = menuId.get(which);
|
||||
if (id == R.id.copy) {
|
||||
ClipboardUtil.addTextToClipboard(comment.comment);
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), comment.comment, false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
} else if (id == R.id.vote_up) {
|
||||
voteComment(comment.id, 1);
|
||||
} else if (id == R.id.vote_down) {
|
||||
|
||||
@@ -103,7 +103,7 @@ import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.text.URLImageGetter;
|
||||
import com.hippo.util.AppHelper;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.util.ReadableTime;
|
||||
import com.hippo.view.ViewTransition;
|
||||
@@ -1454,11 +1454,9 @@ public class GalleryDetailScene extends ToolbarScene implements View.OnClickList
|
||||
} else if (id == R.id.add_filter) {
|
||||
showFilterTagDialog(tag);
|
||||
} else if (id == R.id.copy) {
|
||||
ClipboardUtil.addTextToClipboard(tag);
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), tag, false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
} else if (id == R.id.copy_trans) {
|
||||
ClipboardUtil.addTextToClipboard(tv.getText().toString());
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), tv.getText().toString(), false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import com.hippo.ehviewer.UrlOpener;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail;
|
||||
import com.hippo.util.ClipboardUtil;
|
||||
import com.hippo.util.ClipboardUtilKt;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
@@ -188,14 +188,11 @@ public final class GalleryInfoScene extends ToolbarScene {
|
||||
if (position == INDEX_PARENT) {
|
||||
UrlOpener.openUrl(context, mValues.get(position), true);
|
||||
} else {
|
||||
ClipboardUtil.addTextToClipboard(mValues.get(position));
|
||||
|
||||
ClipboardUtilKt.addTextToClipboard(ClipboardUtilKt.getClipboardManager(getContext()), mValues.get(position), false, () -> showTip(R.string.copied_to_clipboard, LENGTH_SHORT));
|
||||
if (position == INDEX_URL) {
|
||||
// Save it to avoid detect the gallery
|
||||
Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
|
||||
}
|
||||
|
||||
showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -15,112 +15,47 @@
|
||||
* You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.hippo.util
|
||||
|
||||
package com.hippo.util;
|
||||
import android.content.ClipData
|
||||
import android.content.ClipDescription
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.PersistableBundle
|
||||
import android.text.TextUtils
|
||||
import android.view.textclassifier.TextClassifier
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.textclassifier.TextClassifier;
|
||||
fun Context.getClipboardManager(): ClipboardManager {
|
||||
return getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
}
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class ClipboardUtil {
|
||||
private static final String TAG = "ClipboardUtil";
|
||||
@Nullable
|
||||
private static ClipboardManager clipboardManager;
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static Context sContext;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
sContext = context;
|
||||
clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (clipboardManager == null) {
|
||||
Log.e(TAG, "This device has no clipboard!");
|
||||
}
|
||||
}
|
||||
|
||||
public static void addTextToClipboard(String text) {
|
||||
if (clipboardManager != null) {
|
||||
try {
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fun ClipboardManager.addTextToClipboard(text: String?, isSensitive: Boolean, showTip: () -> Unit) {
|
||||
setPrimaryClip(ClipData.newPlainText(null, text).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && isSensitive)
|
||||
description.extras = PersistableBundle().apply {
|
||||
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
|
||||
showTip()
|
||||
}
|
||||
|
||||
public static String getTextFromClipboard() {
|
||||
if (clipboardManager != null) {
|
||||
try {
|
||||
if (!clipboardManager.hasPrimaryClip()) {
|
||||
return null;
|
||||
}
|
||||
ClipData primaryClip = clipboardManager.getPrimaryClip();
|
||||
if (primaryClip == null) {
|
||||
return null;
|
||||
}
|
||||
ClipData.Item item = primaryClip.getItemAt(0);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
String string = String.valueOf(item.coerceToText(sContext));
|
||||
if (!TextUtils.isEmpty(string)) {
|
||||
return string;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
fun ClipboardManager.getTextFromClipboard(context: Context): String? {
|
||||
val item = primaryClip?.getItemAt(0)
|
||||
val string = item?.coerceToText(context).toString()
|
||||
return if (!TextUtils.isEmpty(string)) string else null
|
||||
}
|
||||
|
||||
public static String getUrlFromClipboard() {
|
||||
if (clipboardManager != null) {
|
||||
try {
|
||||
if (!clipboardManager.hasPrimaryClip()) {
|
||||
return null;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
ClipDescription primaryClipDescription = clipboardManager.getPrimaryClipDescription();
|
||||
if (primaryClipDescription != null) {
|
||||
if (primaryClipDescription.getClassificationStatus() == ClipDescription.CLASSIFICATION_COMPLETE) {
|
||||
if (primaryClipDescription.getConfidenceScore(TextClassifier.TYPE_URL) <= 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClipData primaryClip = clipboardManager.getPrimaryClip();
|
||||
if (primaryClip == null) {
|
||||
return null;
|
||||
}
|
||||
ClipData.Item item = primaryClip.getItemAt(0);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
String string = String.valueOf(item.coerceToText(sContext));
|
||||
if (!TextUtils.isEmpty(string)) {
|
||||
return string;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
fun ClipboardManager.getUrlFromClipboard(context: Context): String? {
|
||||
if (primaryClipDescription?.classificationStatus == ClipDescription.CLASSIFICATION_COMPLETE) {
|
||||
if ((primaryClipDescription?.getConfidenceScore(TextClassifier.TYPE_URL)
|
||||
?.let { it <= 0 }) == true
|
||||
) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
val item = primaryClip?.getItemAt(0)
|
||||
val string = item?.coerceToText(context).toString()
|
||||
return if (!TextUtils.isEmpty(string)) string else null
|
||||
}
|
||||
Reference in new issue
Block a user