From db9e362fbbf9ff8c6635850afd776acf280f75b3 Mon Sep 17 00:00:00 2001 From: IndusAryan <125901294+IndusAryan@users.noreply.github.com> Date: Wed, 5 Mar 2025 05:15:12 +0530 Subject: [PATCH] =?UTF-8?q?refactor:=20convert=20monkey=20activity=20?= =?UTF-8?q?=F0=9F=90=92=20into=20a=20fragment=20monke=20=F0=9F=A6=8D=20(#1?= =?UTF-8?q?576)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Turn monkey activity 🐒 into a fragment monke 🦍 --- app/src/main/AndroidManifest.xml | 5 - .../cloudstream3/ui/EasterEggMonkeActivity.kt | 97 --------- .../cloudstream3/ui/EasterEggMonkeFragment.kt | 189 ++++++++++++++++++ .../ui/settings/SettingsGeneral.kt | 2 +- .../res/layout/activity_easter_egg_monke.xml | 47 ----- .../res/layout/fragment_easter_egg_monke.xml | 15 ++ .../main/res/navigation/mobile_navigation.xml | 21 +- 7 files changed, 219 insertions(+), 157 deletions(-) delete mode 100644 app/src/main/java/com/lagradost/cloudstream3/ui/EasterEggMonkeActivity.kt create mode 100644 app/src/main/java/com/lagradost/cloudstream3/ui/EasterEggMonkeFragment.kt delete mode 100644 app/src/main/res/layout/activity_easter_egg_monke.xml create mode 100644 app/src/main/res/layout/fragment_easter_egg_monke.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dac2fa0c7..d960d910c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -196,11 +196,6 @@ - - = listOf( + R.drawable.monke_benene, + R.drawable.monke_burrito, + R.drawable.monke_coco, + R.drawable.monke_cookie, + R.drawable.monke_flusdered, + R.drawable.monke_funny, + R.drawable.monke_like, + R.drawable.monke_party, + R.drawable.monke_sob, + R.drawable.monke_drink, + R.drawable.benene, + R.drawable.ic_launcher_foreground, + R.drawable.quick_novel_icon, + ) + + private val activeMonkeys = mutableListOf() + private var spawningJob: Job? = null + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? + ): View { + _binding = FragmentEasterEggMonkeBinding.inflate(layoutInflater) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + activity?.hideSystemUI() + spawningJob = lifecycleScope.launch { + delay(1000) + while (isActive) { + spawnMonkey() + delay(500) + } + } + } + + private fun spawnMonkey() { + val newMonkey = ImageView(context ?: return).apply { + setImageResource(monkeys.random()) + isVisible = true + } + + val initialScale = Random.nextFloat() * 1.5f + 0.5f + newMonkey.scaleX = initialScale + newMonkey.scaleY = initialScale + + newMonkey.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) + val monkeyW = newMonkey.measuredWidth * initialScale + val monkeyH = newMonkey.measuredHeight * initialScale + + newMonkey.x = Random.nextFloat() * (binding.frame.width.toFloat() - monkeyW) + newMonkey.y = Random.nextFloat() * (binding.frame.height.toFloat() - monkeyH) + + binding.frame.addView(newMonkey, FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT + )) + + activeMonkeys.add(newMonkey) + + newMonkey.alpha = 0f + ObjectAnimator.ofFloat(newMonkey, View.ALPHA, 0f, 1f).apply { + duration = Random.nextLong(1000, 2500) + interpolator = AccelerateInterpolator() + start() + } + + @SuppressLint("ClickableViewAccessibility") + newMonkey.setOnTouchListener { view, event -> handleTouch(view, event) } + + startFloatingAnimation(newMonkey) + } + + private fun startFloatingAnimation(monkey: ImageView) { + val floatUpAnimator = ObjectAnimator.ofFloat( + monkey, View.TRANSLATION_Y, monkey.y, -monkey.height.toFloat() + ).apply { + duration = Random.nextLong(8000, 15000) + interpolator = LinearInterpolator() + } + + floatUpAnimator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + // necessary check because binding becomes null but monkes are still moving until onDestroy() + if (_binding != null) { + binding.frame.removeView(monkey) + activeMonkeys.remove(monkey) + } + } + }) + + floatUpAnimator.start() + monkey.tag = floatUpAnimator + } + + private fun handleTouch(view: View, event: MotionEvent): Boolean { + val monkey = view as ImageView + when (event.action) { + MotionEvent.ACTION_DOWN -> { + (monkey.tag as? ObjectAnimator)?.pause() + return true + } + + MotionEvent.ACTION_MOVE -> { + // Update both X and Y positions properly + monkey.x = event.rawX - monkey.width / 2 + monkey.y = event.rawY - monkey.height / 2 + + // Check if monkey touches the screen edge + if (isTouchingEdge(monkey)) { + removeMonkey(monkey) + } + return true + } + + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + if (isTouchingEdge(monkey)) { + removeMonkey(monkey) + } else { + startFloatingAnimation(monkey) + } + return true + } + } + return false + } + + private fun isTouchingEdge(monkey: ImageView): Boolean { + return monkey.x <= 0 || monkey.x + monkey.width >= binding.frame.width || + monkey.y <= 0 || monkey.y + monkey.height >= binding.frame.height + } + + private fun removeMonkey(monkey: ImageView) { + // Fade out and remove the monkey + ObjectAnimator.ofFloat(monkey, View.ALPHA, 1f, 0f).apply { + duration = 300 + addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + binding.frame.removeView(monkey) + activeMonkeys.remove(monkey) + } + }) + start() + } + } + + override fun onDestroyView() { + super.onDestroyView() + activity?.showSystemUI() + spawningJob?.cancel() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt index 3861bcb78..74910ecbc 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt @@ -391,7 +391,7 @@ class SettingsGeneral : PreferenceFragmentCompat() { try { beneneCount++ if (beneneCount%20 == 0) { - activity?.navigate(R.id.easterEggMonkeActivity) + activity?.navigate(R.id.action_navigation_settings_general_to_easterEggMonkeFragment) } settingsManager.edit().putInt( getString(R.string.benene_count), diff --git a/app/src/main/res/layout/activity_easter_egg_monke.xml b/app/src/main/res/layout/activity_easter_egg_monke.xml deleted file mode 100644 index 9003cd211..000000000 --- a/app/src/main/res/layout/activity_easter_egg_monke.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_easter_egg_monke.xml b/app/src/main/res/layout/fragment_easter_egg_monke.xml new file mode 100644 index 000000000..8440d40ce --- /dev/null +++ b/app/src/main/res/layout/fragment_easter_egg_monke.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index ab1291a90..784fc515e 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -184,7 +184,15 @@ app:enterAnim="@anim/enter_anim" app:exitAnim="@anim/exit_anim" app:popEnterAnim="@anim/enter_anim" - app:popExitAnim="@anim/exit_anim" /> + app:popExitAnim="@anim/exit_anim" > + + - - +