From 4b537eb278b0d884ddf07defe57965dc99c19b83 Mon Sep 17 00:00:00 2001 From: GangJust <201741884@qq.com> Date: Fri, 7 Jul 2023 16:57:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86=E5=B7=B2?= =?UTF-8?q?=E7=9F=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- app/src/main/assets/update.log | 6 + app/src/main/assets/version | 2 +- .../freegang/fplus/activity/DoHomeActivity.kt | 56 ++-- .../freegang/fplus/activity/MainActivity.kt | 7 +- .../aweme/base/fragment/AmeBaseFragment.java | 2 +- .../feed/pinch/ui/PinchPlayPauseView.java | 25 ++ .../feed/pinch/ui/PinchSpeedView.java | 26 ++ .../slides/detail/SlidesDetailActivity.java | 7 - .../feed/slides/ui/SlidesPhotosViewPager.java | 20 -- .../ugc/aweme/feed/model/VideoUrlModel.java | 15 + .../component/fragment/ComponentFragment.java | 2 +- core/build.gradle | 1 + .../freegang/douyin/HCommonPageFragment.kt | 29 +- .../java/com/freegang/douyin/HMainActivity.kt | 7 +- .../com/freegang/douyin/HVerticalViewPager.kt | 280 +++++++----------- .../douyin/activity/FreedomSettingActivity.kt | 1 - .../freegang/douyin/logic/DownloadLogic.kt | 129 ++++---- .../main/java/com/freegang/view/MaskView.kt | 28 -- .../java/com/freegang/view/OverlayView.kt | 58 ++++ .../java/com/freegang/xpler/HookStatus.kt | 4 +- .../java/com/freegang/xpler/core/KtOnHook.kt | 11 +- .../main/res/layout/hook_appbar_layout.xml | 9 +- readme.md | 3 +- 24 files changed, 390 insertions(+), 342 deletions(-) create mode 100644 aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchPlayPauseView.java create mode 100644 aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchSpeedView.java delete mode 100644 aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/detail/SlidesDetailActivity.java delete mode 100644 aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/ui/SlidesPhotosViewPager.java rename aweme/src/main/java/com/{com => }/ss/android/ugc/common/component/fragment/ComponentFragment.java (64%) delete mode 100644 core/src/main/java/com/freegang/view/MaskView.kt create mode 100644 core/src/main/java/com/freegang/view/OverlayView.kt diff --git a/app/build.gradle b/app/build.gradle index c45b3ca..45b090a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "com.freegang.fplus" minSdk 24 targetSdk 33 - versionCode 34 - versionName "1.1.4" + versionCode 35 + versionName "1.1.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/assets/update.log b/app/src/main/assets/update.log index 08330db..16c9dc4 100644 --- a/app/src/main/assets/update.log +++ b/app/src/main/assets/update.log @@ -1,3 +1,9 @@ +v1.1.5 +修复下载对话框不关闭 +修复下载通知栏在UI线程下造成视频卡顿 +修复部分机型开启清爽模式后长按弹窗不响应 +修复部分其它已知问题 + v1.1.4 增加禁用双击点赞 调整清爽模式逻辑 diff --git a/app/src/main/assets/version b/app/src/main/assets/version index ca3f8e1..f4808c8 100644 --- a/app/src/main/assets/version +++ b/app/src/main/assets/version @@ -1 +1 @@ -1.1.4-34 \ No newline at end of file +1.1.5-35 \ No newline at end of file diff --git a/app/src/main/java/com/freegang/fplus/activity/DoHomeActivity.kt b/app/src/main/java/com/freegang/fplus/activity/DoHomeActivity.kt index dbf7ada..ea4e0d7 100644 --- a/app/src/main/java/com/freegang/fplus/activity/DoHomeActivity.kt +++ b/app/src/main/java/com/freegang/fplus/activity/DoHomeActivity.kt @@ -269,7 +269,7 @@ class DoHomeActivity : ComponentActivity() { ) Spacer(modifier = Modifier.padding(vertical = 2.dp)) Text( - text = "Integrated ${lspatchActive[0]} - ${lspatchActive[1]}", + text = "${lspatchActive[0]} ${lspatchActive[1]} - ${lspatchActive[2]}", style = Themes.nowTypography.body2, ) } else if (HookStatus.isExpModuleActive(this@DoHomeActivity)) { @@ -449,8 +449,8 @@ class DoHomeActivity : ComponentActivity() { ) } - //tg交流群 - /*FCard( + //tg频道 + FCard( modifier = Modifier .padding(vertical = 4.dp) .clickable( @@ -467,24 +467,24 @@ class DoHomeActivity : ComponentActivity() { content = { Icon( painter = painterResource(id = R.drawable.ic_telegram), - contentDescription = "tg交流群", + contentDescription = "Telegram频道", tint = Themes.nowColors.icon, modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.padding(horizontal = 8.dp)) Column { Text( - text = "tg交流群", + text = "Telegram频道", style = Themes.nowTypography.body1, ) Text( - text = "闲聊吹水,Bug反馈~", + text = "版本发布, Bug反馈~", style = Themes.nowTypography.overline, ) } }, ) - }*/ + } //打赏 /*FCard( @@ -554,12 +554,21 @@ class DoHomeActivity : ComponentActivity() { } private fun toBrowse() { - startActivity( - Intent( - Intent.ACTION_VIEW, - Uri.parse("https://github.com/GangJust/FreedomPlus"), + try { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://github.com/GangJust/FreedomPlus"), + ) ) - ) + return + } catch (_: Exception) { + + } + + val manager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + manager.setPrimaryClip(ClipData.newPlainText("github link", "https://github.com/GangJust/FreedomPlus")) + showToast("未安装浏览器,链接已复制!") } private fun toEmail() { @@ -570,24 +579,28 @@ class DoHomeActivity : ComponentActivity() { Uri.parse("mailto:freegang555@gmail.com"), ) ) - } catch (e: Exception) { - val manager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - manager.setPrimaryClip(ClipData.newPlainText("feedback email", "freegang555@gmail.com")) - Toast.makeText(applicationContext, "未安装邮箱类App,邮箱已复制!", Toast.LENGTH_SHORT).show() + return + } catch (_: Exception) { } + + val manager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + manager.setPrimaryClip(ClipData.newPlainText("feedback email", "freegang555@gmail.com")) + Toast.makeText(applicationContext, "未安装邮箱类App,邮箱已复制!", Toast.LENGTH_SHORT).show() } private fun joinTgGroup() { - val uri = Uri.parse("tg群链接") + val uri = Uri.parse("https://t.me/FreedomPlugin") try { val telegramIntent = Intent(Intent.ACTION_VIEW, uri) telegramIntent.setPackage("org.telegram.messenger") startActivity(telegramIntent) return - } catch (e: Exception) { - //e.printStackTrace() + } catch (_: Exception) { } - showToast("未安装telegram") + + val manager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + manager.setPrimaryClip(ClipData.newPlainText("telegram link", "https://t.me/FreedomPlugin")) + showToast("未安装telegram,链接已复制!") } private fun rewardByAlipay() { @@ -599,8 +612,7 @@ class DoHomeActivity : ComponentActivity() { ) ) return - } catch (e: Exception) { - //e.printStackTrace() + } catch (_: Exception) { } showToast("谢谢,你没有安装支付宝客户端") } diff --git a/app/src/main/java/com/freegang/fplus/activity/MainActivity.kt b/app/src/main/java/com/freegang/fplus/activity/MainActivity.kt index 641ee9d..f2c5a1a 100644 --- a/app/src/main/java/com/freegang/fplus/activity/MainActivity.kt +++ b/app/src/main/java/com/freegang/fplus/activity/MainActivity.kt @@ -90,7 +90,12 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - FreedomTheme(window = window) { + FreedomTheme( + window = window, + isImmersive = true, + isDark = false, + followSystem = false, + ) { FMessageDialog( title = "Freedom+需要以下权限才能正常运行", cancel = "取消", diff --git a/aweme/src/main/java/com/ss/android/ugc/aweme/base/fragment/AmeBaseFragment.java b/aweme/src/main/java/com/ss/android/ugc/aweme/base/fragment/AmeBaseFragment.java index eb38b32..10eb569 100644 --- a/aweme/src/main/java/com/ss/android/ugc/aweme/base/fragment/AmeBaseFragment.java +++ b/aweme/src/main/java/com/ss/android/ugc/aweme/base/fragment/AmeBaseFragment.java @@ -6,7 +6,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.com.ss.android.ugc.common.component.fragment.ComponentFragment; +import com.ss.android.ugc.common.component.fragment.ComponentFragment; public class AmeBaseFragment extends ComponentFragment { @Override diff --git a/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchPlayPauseView.java b/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchPlayPauseView.java new file mode 100644 index 0000000..35928a9 --- /dev/null +++ b/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchPlayPauseView.java @@ -0,0 +1,25 @@ +package com.ss.android.ugc.aweme.familiar.feed.pinch.ui; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + +public class PinchPlayPauseView extends AppCompatImageView { + public PinchPlayPauseView(@NonNull Context context) { + super(context); + throw new RuntimeException("sub!"); + } + + public PinchPlayPauseView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + throw new RuntimeException("sub!"); + } + + public PinchPlayPauseView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + throw new RuntimeException("sub!"); + } +} diff --git a/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchSpeedView.java b/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchSpeedView.java new file mode 100644 index 0000000..9d4b9dd --- /dev/null +++ b/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/pinch/ui/PinchSpeedView.java @@ -0,0 +1,26 @@ +package com.ss.android.ugc.aweme.familiar.feed.pinch.ui; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + +public class PinchSpeedView extends AppCompatImageView { + public PinchSpeedView(@NonNull Context context) { + super(context); + throw new RuntimeException("sub!"); + } + + public PinchSpeedView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + throw new RuntimeException("sub!"); + } + + public PinchSpeedView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + throw new RuntimeException("sub!"); + } +} + diff --git a/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/detail/SlidesDetailActivity.java b/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/detail/SlidesDetailActivity.java deleted file mode 100644 index 6d5c48d..0000000 --- a/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/detail/SlidesDetailActivity.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ss.android.ugc.aweme.familiar.feed.slides.detail; - -import com.bytedance.ies.uikit.base.AbsActivity; - -public class SlidesDetailActivity extends AbsActivity { - -} diff --git a/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/ui/SlidesPhotosViewPager.java b/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/ui/SlidesPhotosViewPager.java deleted file mode 100644 index 94c32fd..0000000 --- a/aweme/src/main/java/com/ss/android/ugc/aweme/familiar/feed/slides/ui/SlidesPhotosViewPager.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ss.android.ugc.aweme.familiar.feed.slides.ui; - -import android.content.Context; -import android.util.AttributeSet; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.viewpager.widget.ViewPager; - -public class SlidesPhotosViewPager extends ViewPager { - public SlidesPhotosViewPager(@NonNull Context context) { - super(context); - throw new RuntimeException("sub!!"); - } - - public SlidesPhotosViewPager(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - throw new RuntimeException("sub!!"); - } -} diff --git a/aweme/src/main/java/com/ss/android/ugc/aweme/feed/model/VideoUrlModel.java b/aweme/src/main/java/com/ss/android/ugc/aweme/feed/model/VideoUrlModel.java index b1895f0..ddd1503 100644 --- a/aweme/src/main/java/com/ss/android/ugc/aweme/feed/model/VideoUrlModel.java +++ b/aweme/src/main/java/com/ss/android/ugc/aweme/feed/model/VideoUrlModel.java @@ -3,6 +3,21 @@ import com.ss.android.ugc.aweme.base.model.UrlModel; public class VideoUrlModel extends UrlModel { + public float aspectRatio; + public String bitrateFormat; + public long cdnUrlExpired; + public int codecType; + public long createTime; + public double duration; + public Boolean hasDashBitrate; + public String mDashVideoId; + public String mDashVideoModelString; + public boolean mVr; + public String meta; + public String ratio; + public String ratioUri; + public String sourceId; + public VideoUrlModel() { throw new RuntimeException("sub!"); } diff --git a/aweme/src/main/java/com/com/ss/android/ugc/common/component/fragment/ComponentFragment.java b/aweme/src/main/java/com/ss/android/ugc/common/component/fragment/ComponentFragment.java similarity index 64% rename from aweme/src/main/java/com/com/ss/android/ugc/common/component/fragment/ComponentFragment.java rename to aweme/src/main/java/com/ss/android/ugc/common/component/fragment/ComponentFragment.java index 3c1b64f..64d9981 100644 --- a/aweme/src/main/java/com/com/ss/android/ugc/common/component/fragment/ComponentFragment.java +++ b/aweme/src/main/java/com/ss/android/ugc/common/component/fragment/ComponentFragment.java @@ -1,4 +1,4 @@ -package com.com.ss.android.ugc.common.component.fragment; +package com.ss.android.ugc.common.component.fragment; import com.bytedance.ies.uikit.base.AbsFragment; diff --git a/core/build.gradle b/core/build.gradle index 6c7caaa..188e847 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -73,4 +73,5 @@ dependencies { implementation project(":ktutils") implementation 'org.luckypray:DexKit:1.1.8' implementation 'com.tencent:mmkv:1.3.0' + //implementation 'com.squareup.okhttp3:okhttp:4.8.0' } \ No newline at end of file diff --git a/core/src/main/java/com/freegang/douyin/HCommonPageFragment.kt b/core/src/main/java/com/freegang/douyin/HCommonPageFragment.kt index 721386f..4890880 100644 --- a/core/src/main/java/com/freegang/douyin/HCommonPageFragment.kt +++ b/core/src/main/java/com/freegang/douyin/HCommonPageFragment.kt @@ -9,8 +9,9 @@ import android.widget.TextView import com.freegang.base.BaseHook import com.freegang.config.ConfigV1 import com.freegang.douyin.logic.SaveCommentLogic +import com.freegang.ktutils.display.KDisplayUtils import com.freegang.ktutils.view.KViewUtils -import com.freegang.ktutils.view.traverse +import com.freegang.ktutils.view.findViewsByExact import com.freegang.xpler.R import com.freegang.xpler.core.KtXposedHelpers import com.freegang.xpler.core.NoneHook @@ -32,12 +33,11 @@ class HCommonPageFragment(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook val view = KViewUtils.findViews(activity.contentView, clazz).firstOrNull() ?: return@launch - val firstOrNull = - view.children.firstOrNull() ?: view.findViewsByDesc(View::class.java, "侧边栏").firstOrNull() ?: return@launch + val firstOrNull = view.children.firstOrNull() + ?: view.findViewsByDesc(View::class.java, "侧边栏").firstOrNull() + ?: return@launch val onClickListener = KViewUtils.getOnClickListener(firstOrNull) firstOrNull.setOnClickListener { onClickListener?.onClick(it) diff --git a/core/src/main/java/com/freegang/douyin/HVerticalViewPager.kt b/core/src/main/java/com/freegang/douyin/HVerticalViewPager.kt index fbf3a5d..a38bd01 100644 --- a/core/src/main/java/com/freegang/douyin/HVerticalViewPager.kt +++ b/core/src/main/java/com/freegang/douyin/HVerticalViewPager.kt @@ -1,59 +1,83 @@ package com.freegang.douyin -import android.annotation.SuppressLint import android.app.ActivityOptions import android.content.Intent import android.view.MotionEvent import android.view.View import android.view.ViewGroup -import android.widget.FrameLayout import android.widget.TextView +import androidx.core.view.isVisible import com.freegang.base.BaseHook import com.freegang.config.ConfigV1 import com.freegang.douyin.activity.FreedomSettingActivity import com.freegang.ktutils.app.topActivity import com.freegang.ktutils.display.KDisplayUtils import com.freegang.ktutils.other.KAutomationUtils +import com.freegang.ktutils.reflect.findMethodAndInvoke import com.freegang.ktutils.view.KFastClickUtils -import com.freegang.ktutils.view.KViewUtils -import com.freegang.ktutils.view.findParentExact -import com.freegang.ktutils.view.findViewsByType import com.freegang.ktutils.view.traverse -import com.freegang.view.MaskView import com.freegang.xpler.core.argsOrEmpty +import com.freegang.xpler.core.findMethodsByReturnType import com.freegang.xpler.core.hookClass import com.freegang.xpler.core.thisView +import com.freegang.xpler.core.thisViewGroup import com.ss.android.ugc.aweme.ad.feed.VideoViewHolderRootView import com.ss.android.ugc.aweme.common.widget.VerticalViewPager +import com.ss.android.ugc.aweme.familiar.feed.pinch.ui.PinchPlayPauseView +import com.ss.android.ugc.aweme.feed.model.Aweme import com.ss.android.ugc.aweme.feed.quick.presenter.FeedDoctorFrameLayout import com.ss.android.ugc.aweme.feed.share.long_click.FrameLayoutHoldTouchListener -import com.ss.android.ugc.aweme.feed.ui.LongPressLayout import com.ss.android.ugc.aweme.feed.ui.PenetrateTouchRelativeLayout import com.ss.android.ugc.aweme.sticker.infoSticker.interact.consume.view.InteractStickerParent import de.robv.android.xposed.callbacks.XC_LoadPackage import kotlinx.coroutines.delay +import kotlin.math.abs class HVerticalViewPager(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook(lpparam) { private val config get() = ConfigV1.get() private val screenSize get() = KDisplayUtils.screenSize() + private var isLongPressFast = false + private var longPressFastRunnable: Runnable? = null + + private var downX: Float = 0f + private var downY: Float = 0f private var longPressRunnable: Runnable? = null + private var isAttentionalMode = false + + private var currentAweme: Aweme? = null + override fun onInit() { lpparam.hookClass(targetClazz) - .methodAll { + .method("getCurrentItem") { onAfter { - val first = argsOrEmpty.firstOrNull() ?: return@onAfter - if (config.isNeatMode) { - if (first is VerticalViewPager) { - toggleView(first) + runCatching { + val adapter = thisObject.findMethodAndInvoke("getAdapter") + val methods = adapter?.findMethodsByReturnType(Aweme::class.java) ?: emptyList() + val filter = methods.filter { it.parameterTypes.size == 1 && it.parameterTypes[0] == Int::class.java } + filter.run { + if (isEmpty()) return@run + val tmpAweme = first().invoke(adapter, result) as Aweme? + if (currentAweme == tmpAweme) return@run + currentAweme = tmpAweme } } } } + .methodAll { + onAfter { + val first = argsOrEmpty.firstOrNull() ?: return@onAfter + if (first !is VerticalViewPager) return@onAfter + toggleView(first) + } + } - lpparam.hookClass(LongPressLayout::class.java) - .method("onTouchEvent", MotionEvent::class.java) { + lpparam.hookClass(VideoViewHolderRootView::class.java) + .method("dispatchTouchEvent", MotionEvent::class.java) { onBefore { + if (!config.isNeatMode) return@onBefore + if (currentAweme?.isLive == true) return@onBefore + val event = args[0] as MotionEvent val obtain = MotionEvent.obtain( event.downTime, @@ -64,8 +88,16 @@ class HVerticalViewPager(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook { + downX = event.x + downY = event.y + //防止双击 if (KFastClickUtils.isFastDoubleClick(500L) && config.isDisableDoubleLike) { thisView.dispatchTouchEvent(obtain) @@ -75,6 +107,8 @@ class HVerticalViewPager(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook screenSize.width - screenSize.width / 8) { + longPressFastRunnable = Runnable { isLongPressFast = true } + handler.postDelayed(longPressFastRunnable!!, 200L) return@onBefore } @@ -82,9 +116,7 @@ class HVerticalViewPager(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook screenSize.height / 2) { longPressRunnable = Runnable { - val viewGroup = thisView.findParentExact(VideoViewHolderRootView::class.java) - viewGroup ?: return@Runnable - showOptionsMenuV1(viewGroup) + showOptionsMenuV1(thisViewGroup) thisView.dispatchTouchEvent(obtain) } handler.postDelayed(longPressRunnable!!, 300L) @@ -104,93 +134,34 @@ class HVerticalViewPager(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook { - if (longPressRunnable != null) { - handler.removeCallbacks(longPressRunnable!!) - } + MotionEvent.ACTION_MOVE -> { + if (abs(downX - event.x) < 10 && abs(downY - event.y) < 10) return@onBefore //消除误差 + longPressRunnable?.runCatching { handler.removeCallbacks(this) } } - } - } - } - } - - @Deprecated("Deprecated") - @SuppressLint("ClickableViewAccessibility") - private fun attachView(view: ViewGroup) { - val parentExact = view.findParentExact(FrameLayout::class.java) - val maskView = MaskView(view.context) - if (parentExact?.findViewsByType(MaskView::class.java)?.isEmpty() == true) { - parentExact.addView(maskView) - maskView.setOnTouchListener { _, event -> - when (event.action) { - MotionEvent.ACTION_DOWN -> { - //预留出长按快进 - if (event.x < screenSize.width / 8 || event.x > screenSize.width - screenSize.width / 8) { - return@setOnTouchListener false - } - - //如果是评论区视频/图片 - if (isComment(view)) { - return@setOnTouchListener false + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + isLongPressFast = false + longPressFastRunnable?.runCatching { handler.removeCallbacks(this) } + longPressRunnable?.runCatching { handler.removeCallbacks(this) } } - // - longPressRunnable = Runnable { - val obtain = MotionEvent.obtain( - event.downTime, - event.eventTime + 100, - MotionEvent.ACTION_CANCEL, - event.x, - event.y, - event.metaState - ) - if (config.longPressMode) { - if (event.y < screenSize.height / 2) { - showOptionsMenuV1(view) - view.dispatchTouchEvent(obtain) - } - } else { - if (event.y > screenSize.height / 2) { - showOptionsMenuV1(view) - view.dispatchTouchEvent(obtain) - } - } + else -> { + isLongPressFast = false + longPressFastRunnable?.runCatching { handler.removeCallbacks(this) } + longPressRunnable?.runCatching { handler.removeCallbacks(this) } } - handler.postDelayed(longPressRunnable!!, 300L) - view.dispatchTouchEvent(event) - return@setOnTouchListener true } - else -> { - if (longPressRunnable != null) { - handler.removeCallbacks(longPressRunnable!!) - } - view.dispatchTouchEvent(event) - } } - return@setOnTouchListener false } - } - } - @Deprecated("Deprecated") - private fun isComment(viewGroup: ViewGroup): Boolean { - return try { - viewGroup.rootView.traverse { - if (it is TextView) { - if (it.text.contains("保存")) { - throw Exception("true") - } - if (it.text.contains("我也发一张")) { - KViewUtils.hideAll(it.parent as ViewGroup) - } + lpparam.hookClass(PinchPlayPauseView::class.java) + .methodAll { + onAfter { + if (!config.isNeatMode) return@onAfter + isAttentionalMode = method.name != "onDetachedFromWindow" } } - false - } catch (e: Exception) { - true - } } private fun showOptionsMenuV1(view: ViewGroup) { @@ -232,8 +203,8 @@ class HVerticalViewPager(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook? = null, - targetText: Regex = Regex(""), - targetHint: Regex = Regex(""), - targetContent: Regex = Regex(""), - ) { - launch { - //如果是清爽模式的状态下 - if (config.neatModeState) { - //先取消控件隐藏 - config.neatModeState = false - toggleView(parent) - - //等待300毫秒, 记录坐标 - delay(300) - val location = IntArray(2) { 0 } - parent.traverse { - var needClick = false - if (it is TextView) { - needClick = "${it.text}".containsNotEmpty(targetText) - needClick = needClick || "${it.hint}".containsNotEmpty(targetHint) - } - needClick = needClick || "${it.contentDescription}".containsNotEmpty(targetContent) - needClick = needClick || (targetView?.isInstance(it) ?: false) - if (!needClick) return@traverse - - val temp = IntArray(2) { 0 } - it.getLocationOnScreen(temp) - if (temp[1] > 0 && temp[1] < screenSize.height) { - location[0] = temp[0] + it.right / 2 - location[1] = temp[1] + it.bottom / 2 - - //模拟点击 - KAutomationUtils.simulateClickByView(it, location[0].toFloat(), location[1].toFloat()) - - //恢复清爽模式 - config.neatModeState = true - toggleView(parent) - } - } - } else { - //等待300毫秒, 记录坐标 - delay(300) - val location = IntArray(2) { 0 } - parent.traverse { - var needClick = false - if (it is TextView) { - needClick = "${it.text}".containsNotEmpty(targetText) - needClick = needClick || "${it.hint}".containsNotEmpty(targetHint) - } - needClick = needClick || "${it.contentDescription}".containsNotEmpty(targetContent) - needClick = needClick || (targetView?.isInstance(it) ?: false) - if (!needClick) return@traverse - - val temp = IntArray(2) { 0 } - it.getLocationOnScreen(temp) - if (temp[1] > 0 && temp[1] < screenSize.height) { - location[0] = temp[0] + it.right / 2 - location[1] = temp[1] + it.bottom / 2 - //模拟点击 - KAutomationUtils.simulateClickByView(it, location[0].toFloat(), location[1].toFloat()) - } - } + it.isVisible = !isLongPressFast + it.isVisible = if (isLongPressFast) false else !isAttentionalMode } } } @@ -346,17 +248,39 @@ class HVerticalViewPager(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook 0 && temp[1] < screenSize.height) { - val location = IntArray(2) { 0 } - location[0] = temp[0] + it.right / 2 - location[1] = temp[1] + it.bottom / 2 - KAutomationUtils.simulateClickByView(it, location[0].toFloat(), location[1].toFloat()) + val location = IntArray(2) { 0 } + it.getLocationOnScreen(location) + if (location[1] > 0 && location[1] < screenSize.height) { + location[0] = location[0] + it.right / 2 + location[1] = location[1] + it.bottom / 2 + if (!KFastClickUtils.isFastDoubleClick(200)) { + KAutomationUtils.simulateClickByView(it, location[0].toFloat(), location[1].toFloat()) + } + } + } + } + + private fun onSwipeView( + view: View, + msg: String, + ) { + launch { + delay(500L) + if (!KFastClickUtils.isFastDoubleClick(500L)) { + if (msg.isNotEmpty()) showToast(view.context, msg) + KAutomationUtils.simulateSwipeByView( + view, + screenSize.width / 2f, + screenSize.height / 2f + 200, + screenSize.width / 2f, + screenSize.height / 2f - 200, + 20, + ) } } } + private fun CharSequence.containsNotEmpty(regex: Regex): Boolean { if (regex.pattern.isEmpty()) return false return contains(regex) diff --git a/core/src/main/java/com/freegang/douyin/activity/FreedomSettingActivity.kt b/core/src/main/java/com/freegang/douyin/activity/FreedomSettingActivity.kt index 4cb7c70..6f0b7d6 100644 --- a/core/src/main/java/com/freegang/douyin/activity/FreedomSettingActivity.kt +++ b/core/src/main/java/com/freegang/douyin/activity/FreedomSettingActivity.kt @@ -502,7 +502,6 @@ class FreedomSettingActivity : BaseActivity() { showLongPressModeDialog = true }, onCheckedChange = { - showRestartAppDialog = true model.changeIsNeatMode(it) } ) diff --git a/core/src/main/java/com/freegang/douyin/logic/DownloadLogic.kt b/core/src/main/java/com/freegang/douyin/logic/DownloadLogic.kt index 19510a8..593db08 100644 --- a/core/src/main/java/com/freegang/douyin/logic/DownloadLogic.kt +++ b/core/src/main/java/com/freegang/douyin/logic/DownloadLogic.kt @@ -6,6 +6,7 @@ import com.freegang.base.BaseHook import com.freegang.config.ConfigV1 import com.freegang.ktutils.app.IProgressNotification import com.freegang.ktutils.app.KMediaUtils +import com.freegang.ktutils.app.KNotifiUtils import com.freegang.ktutils.io.child import com.freegang.ktutils.io.need import com.freegang.ktutils.io.pureFileName @@ -69,9 +70,8 @@ class DownloadLogic( mPureFileName = if (aweme.desc.isNullOrBlank()) { "${mPureNickname}_${mShortId}_${System.currentTimeMillis() / 1000}" } else { - "${mPureNickname}_${mShortId}_${aweme.desc.pureFileName.secureFilename}" + "${mPureNickname}_${mShortId}_${aweme.desc.pureFileName}" } - showChoiceDialog(aweme) } else { hook.showToast(context, "未获取到基本信息") @@ -144,7 +144,7 @@ class DownloadLogic( return } //构建视频文件名 - mPureFileName = mPureFileName.plus(".mp4") + mPureFileName = mPureFileName.plus(".mp4").secureFilename if (config.isNotification) { showDownloadByNotification(videoUrlList, mVideoParent.need(), mPureFileName, isWebDav) } else { @@ -163,7 +163,7 @@ class DownloadLogic( return } //构建视频文件名 - mPureFileName = mPureFileName.plus(".mp3") + mPureFileName = mPureFileName.plus(".mp3").secureFilename if (config.isNotification) { showDownloadByNotification(musicUrlList, mMusicParent.need(), mPureFileName, isWebDav) } else { @@ -194,7 +194,7 @@ class DownloadLogic( val imageFiles = mutableListOf() var downloadCount = 0 //下载计数器 structList.forEachIndexed { index, urlStruct -> - val downloadFile = File(mImageParent.need(), "${mPureFileName}_${index + 1}.jpg") + val downloadFile = File(mImageParent.need(), "${mPureFileName}_${index + 1}.jpg".secureFilename) val finished = download(urlStruct.urlList.first(), downloadFile, it, "$index/${aweme.images.size} %s%%") if (finished) { @@ -204,22 +204,28 @@ class DownloadLogic( } } - if (downloadCount == aweme.images.size) { - val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" - it.setFinishedText(message) - hook.showToast(context, message) - } else { - val failCount = aweme.images.size - downloadCount - it.setFinishedText("下载成功${downloadCount}, 失败${failCount}!") - hook.showToast(context, "下载成功${downloadCount}, 失败${failCount}!") - Toast.makeText(context, "正在上传WebDav!", Toast.LENGTH_SHORT).show() + hook.refresh { + if (downloadCount == aweme.images.size) { + val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" + it.setFinishedText(message) + hook.showToast(context, message) + } else { + val failCount = aweme.images.size - downloadCount + it.setFinishedText("下载成功${downloadCount}, 失败${failCount}!") + hook.showToast(context, "下载成功${downloadCount}, 失败${failCount}!") + Toast.makeText(context, "正在上传WebDav!", Toast.LENGTH_SHORT).show() + + } } + //上传WebDav if (isWebDav) { if (imageFiles.isEmpty()) { - it.setFinishedText("上传WebDav失败, 无法找到已下载的内容!") - hook.showToast(context, "上传WebDav失败, 无法找到已下载的内容!") + hook.refresh { + it.setFinishedText("上传WebDav失败, 无法找到已下载的内容!") + hook.showToast(context, "上传WebDav失败, 无法找到已下载的内容!") + } return@launch } var uploadCount = 0 @@ -227,12 +233,14 @@ class DownloadLogic( val uploadStatus = uploadToWebDav(image) if (uploadStatus) uploadCount += 1 } - if (uploadCount == imageFiles.size) { - it.setFinishedText("上传WebDav成功!") - hook.showToast(context, "上传WebDav成功!") - } else { - it.setFinishedText("上传WebDav成功${uploadCount}, 失败${imageFiles.size - uploadCount}!") - hook.showToast(context, "上传WebDav成功${uploadCount}, 失败${imageFiles.size - uploadCount}!") + hook.refresh { + if (uploadCount == imageFiles.size) { + it.setFinishedText("上传WebDav成功!") + hook.showToast(context, "上传WebDav成功!") + } else { + it.setFinishedText("上传WebDav成功${uploadCount}, 失败${imageFiles.size - uploadCount}!") + hook.showToast(context, "上传WebDav成功${uploadCount}, 失败${imageFiles.size - uploadCount}!") + } } } } @@ -243,13 +251,12 @@ class DownloadLogic( hook.showProgressDialog( context = context, title = "Freedom+", - needMultiple = true, listener = { dialog, notify -> //下载逻辑 hook.launch { var downloadCount = 0 //下载计数器 structList.forEachIndexed { index, urlStruct -> - val downloadFile = File(mImageParent.need(), "${mPureFileName}_${index + 1}.jpg") + val downloadFile = File(mImageParent.need(), "${mPureFileName}_${index + 1}.jpg".secureFilename) val finished = download(urlStruct.urlList.first(), downloadFile, notify, "$index/${aweme.images.size} %s%%") if (finished) { @@ -258,16 +265,18 @@ class DownloadLogic( } } - dialog.dismiss() - if (downloadCount == aweme.images.size) { - val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" - notify.setFinishedText(message) - hook.showToast(context, message) - } else { - val failCount = aweme.images.size - downloadCount - notify.setFinishedText("下载成功${downloadCount}, 失败${failCount}!") - hook.showToast(context, "下载成功${downloadCount}, 失败${failCount}!") - Toast.makeText(context, "正在上传WebDav!", Toast.LENGTH_SHORT).show() + hook.refresh { + dialog.dismiss() + if (downloadCount == aweme.images.size) { + val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" + notify.setFinishedText(message) + hook.showToast(context, message) + } else { + val failCount = aweme.images.size - downloadCount + notify.setFinishedText("下载成功${downloadCount}, 失败${failCount}!") + hook.showToast(context, "下载成功${downloadCount}, 失败${failCount}!") + Toast.makeText(context, "正在上传WebDav!", Toast.LENGTH_SHORT).show() + } } //上传WebDav @@ -312,20 +321,26 @@ class DownloadLogic( val downloadFile = File(parentPath.need(), pureFileName) val finished = download(urlList.first(), downloadFile, it, "下载中 %s%%") if (finished) { - val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" - it.setFinishedText(message) - hook.showToast(context, message) - KMediaUtils.notifyGallery(context, downloadFile.absolutePath) + hook.refresh { + val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" + it.setFinishedText(message) + hook.showToast(context, message) + KMediaUtils.notifyGallery(context, downloadFile.absolutePath) + } //上传WebDav if (isWebDav) { val uploadStatus = uploadToWebDav(downloadFile) - it.setFinishedText("上传WebDav${if (uploadStatus) "成功!" else "失败!"}") - hook.showToast(context, "上传WebDav${if (uploadStatus) "成功!" else "失败!"}") + hook.refresh { + it.setFinishedText("上传WebDav${if (uploadStatus) "成功!" else "失败!"}") + hook.showToast(context, "上传WebDav${if (uploadStatus) "成功!" else "失败!"}") + } } } else { - it.setFinishedText("下载失败!") - hook.showToast(context, "下载失败!") + hook.refresh { + it.setFinishedText("下载失败!") + hook.showToast(context, "下载失败!") + } } } } @@ -343,18 +358,19 @@ class DownloadLogic( hook.showProgressDialog( context = context, title = "Freedom+", - needMultiple = true, listener = { dialog, notify -> //下载逻辑 hook.launch { val downloadFile = File(parentPath.need(), pureFileName) val finished = download(urlList.first(), downloadFile, notify, "%s%%") if (finished) { - val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" - dialog.dismiss() - notify.setFinishedText(message) - hook.showToast(context, message) - KMediaUtils.notifyGallery(context, downloadFile.absolutePath) + hook.refresh { + dialog.dismiss() + val message = if (isWebDav) "下载成功, 正在上传WebDav!" else "下载成功!" + notify.setFinishedText(message) + hook.showToast(context, message) + KMediaUtils.notifyGallery(context, downloadFile.absolutePath) + } //上传WebDav if (isWebDav) { @@ -362,9 +378,11 @@ class DownloadLogic( hook.showToast(context, "上传WebDav${if (uploadStatus) "成功!" else "失败!"}") } } else { - dialog.dismiss() - notify.setFinishedText("下载失败!") - hook.showToast(context, "下载失败!") + hook.refresh { + dialog.dismiss() + notify.setFinishedText("下载失败!") + hook.showToast(context, "下载失败!") + } } } } @@ -381,10 +399,13 @@ class DownloadLogic( progressText: String, ): Boolean { return withContext(Dispatchers.IO) { - val outputStream = FileOutputStream(downloadFile) var finished = false - KHttpUtils.download(url, outputStream) { real, total, isInterrupt -> - hook.refresh { notify.notifyProgress((real * 100 / total).toInt(), progressText) } + KHttpUtils.download(url, FileOutputStream(downloadFile)) { real, total, isInterrupt -> + if (notify is KNotifiUtils.ProgressNotification) { //通知栏在ui线程中刷新会造成ui卡顿, 排查了一下午, 麻了 + notify.notifyProgress((real * 100 / total).toInt(), progressText) + } else { + hook.refresh { notify.notifyProgress((real * 100 / total).toInt(), progressText) } + } if (isInterrupt) finished = false if (real >= total) finished = true } diff --git a/core/src/main/java/com/freegang/view/MaskView.kt b/core/src/main/java/com/freegang/view/MaskView.kt deleted file mode 100644 index ab820b7..0000000 --- a/core/src/main/java/com/freegang/view/MaskView.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.freegang.view - -import android.content.Context -import android.util.AttributeSet -import android.view.GestureDetector -import android.view.MotionEvent -import android.widget.FrameLayout - -class MaskView @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null -) : FrameLayout(context, attrs) { - private var mGestureDetector: GestureDetector? = null - - fun setOnGestureListener(l: GestureDetector.SimpleOnGestureListener) { - this.mGestureDetector = GestureDetector(context, l) - } - - init { - layoutParams = LayoutParams(-1, -1) - contentDescription = "FreedomMaskView" - } - - override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { - return mGestureDetector?.onTouchEvent(ev!!) ?: super.dispatchTouchEvent(ev) - } - -} \ No newline at end of file diff --git a/core/src/main/java/com/freegang/view/OverlayView.kt b/core/src/main/java/com/freegang/view/OverlayView.kt new file mode 100644 index 0000000..0975272 --- /dev/null +++ b/core/src/main/java/com/freegang/view/OverlayView.kt @@ -0,0 +1,58 @@ +package com.freegang.view + + +import android.content.Context +import android.graphics.PixelFormat +import android.util.AttributeSet +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.RelativeLayout + +class OverlayView( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int, +) : RelativeLayout(context, attrs, defStyleAttr, defStyleRes) { + private val mScreenWidth = context.resources.displayMetrics.widthPixels + private val mScreenHeight = context.resources.displayMetrics.heightPixels + private val mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + + private var mLayoutParams: WindowManager.LayoutParams? = null + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : this(context, attrs, defStyleAttr, 0) + + constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) + + constructor(context: Context) : this(context, null) + + override fun setLayoutParams(params: ViewGroup.LayoutParams) { + super.setLayoutParams(params) + mLayoutParams = WindowManager.LayoutParams( + params.width, + params.height, + WindowManager.LayoutParams.FIRST_SUB_WINDOW, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, + PixelFormat.RGBA_8888, + ) + } + + fun setContentView(view: View) { + addView(view) + } + + fun show() { + show(Gravity.CENTER, 0, 0) + } + + fun show(gravity: Int, x: Int, y: Int) { + mLayoutParams?.runCatching { + this.gravity = gravity + this.x = x + this.y = y + mWindowManager.addView(this@OverlayView, this) + } + } +} \ No newline at end of file diff --git a/core/src/main/java/com/freegang/xpler/HookStatus.kt b/core/src/main/java/com/freegang/xpler/HookStatus.kt index 80517b0..5127075 100644 --- a/core/src/main/java/com/freegang/xpler/HookStatus.kt +++ b/core/src/main/java/com/freegang/xpler/HookStatus.kt @@ -8,6 +8,7 @@ import android.os.Bundle import android.util.Base64 import com.freegang.ktutils.app.KAppUtils import com.freegang.ktutils.json.KJSONUtils +import com.freegang.ktutils.json.getBooleanOrDefault import com.freegang.ktutils.json.getStringOrDefault object HookStatus { @@ -83,10 +84,11 @@ object HookStatus { val json = Base64.decode(config, Base64.DEFAULT).toString(Charsets.UTF_8) val patchConfig = KJSONUtils.parse(json) + val useManager = patchConfig.getBooleanOrDefault("useManager") val lspConfig = patchConfig.getJSONObject("lspConfig") val versionName = lspConfig.getStringOrDefault("VERSION_NAME") val versionCode = lspConfig.getStringOrDefault("VERSION_CODE") - return arrayOf(versionName, versionCode) + return arrayOf(if (useManager) "本地模式" else "集成模式", versionName, versionCode) } catch (e: Exception) { e.printStackTrace() //KLogCat.e(e.stackTraceToString()) diff --git a/core/src/main/java/com/freegang/xpler/core/KtOnHook.kt b/core/src/main/java/com/freegang/xpler/core/KtOnHook.kt index 30961a4..d5e7264 100644 --- a/core/src/main/java/com/freegang/xpler/core/KtOnHook.kt +++ b/core/src/main/java/com/freegang/xpler/core/KtOnHook.kt @@ -2,6 +2,7 @@ package com.freegang.xpler.core import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodReplacement +import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage import java.lang.reflect.Field @@ -184,7 +185,12 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara * 查找某类 */ open fun findClass(className: String, classLoader: ClassLoader? = null): Class<*> { - return XposedHelpers.findClass(className, classLoader ?: lpparam.classLoader) + return try { + XposedHelpers.findClass(className, classLoader ?: lpparam.classLoader) + } catch (e: Exception) { + XposedBridge.log(e) + Class::class.java + } } /** @@ -392,7 +398,8 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara //替换 @Param 指定的参数类型 val finalTargetMethodParamTypes = targetMethodParamTypes.mapIndexed { index, clazz -> if (parameterAnnotations[index].isEmpty()) return@mapIndexed clazz //如果某个参数没有注解 - val param = parameterAnnotations[index].filterIsInstance().ifEmpty { return@mapIndexed clazz } //如果某个参数有注解, 但没有@Param注解, 直接return + val param = parameterAnnotations[index].filterIsInstance() + .ifEmpty { return@mapIndexed clazz } //如果某个参数有注解, 但没有@Param注解, 直接return findClass(param[0].name) //寻找注解类 }.toTypedArray() diff --git a/core/src/main/res/layout/hook_appbar_layout.xml b/core/src/main/res/layout/hook_appbar_layout.xml index 175d7fa..68ab161 100644 --- a/core/src/main/res/layout/hook_appbar_layout.xml +++ b/core/src/main/res/layout/hook_appbar_layout.xml @@ -4,7 +4,6 @@ android:layout_height="wrap_content" android:background="#55000000"> - + + \ No newline at end of file diff --git a/readme.md b/readme.md index b95181c..e78f6ab 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ # FreedomPlus -[![](https://img.shields.io/github/v/release/GangJust/FreedomPlus)](https://github.com/GangJust/FreedomPlus/releases) [![](https://img.shields.io/github/downloads/GangJust/FreedomPlus/total?color=g)]() +[![](https://img.shields.io/github/v/release/GangJust/FreedomPlus)](https://github.com/GangJust/FreedomPlus/releases) [![](https://img.shields.io/github/downloads/GangJust/FreedomPlus/total?color=g)]() [![](https://img.shields.io/badge/telegram-freedom%2B-2481CC)](https://t.me/FreedomPlugin) 依赖于抖音运行的开源Xposed模块 @@ -16,6 +16,7 @@ - 首页控件半透明防烧屏 - 首页清爽模式隐藏大部分控件 - 顶部Tab栏自定义隐藏 +- 禁用双击点赞