Skip to content

Commit

Permalink
Attempt to fix Search toolbar having wrong query after configuration …
Browse files Browse the repository at this point in the history
…change from Slide to Split layout

which lead to nothing (couple of other bugs were fixed though). The problem is in inability (at least
I don't know how) to remove controllers from backstack upon config change before
calling router.rebindIfNeeded() (it results in NPEs, maybe it's a bug). Waiting for the devs' response
bluelinelabs/Conductor#636
  • Loading branch information
K1rakishou committed Dec 10, 2020
1 parent 8c3b286 commit 49f66da
Show file tree
Hide file tree
Showing 15 changed files with 270 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class MyApplication : Application() {

Thread.setDefaultUncaughtExceptionHandler { thread, exception ->
Timber.e(exception, "Unhandled exception in thread ${thread.name}")

throw exception
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package com.github.k1rakishou.kurobanewnavstacktest.activity

import android.app.Activity
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import com.bluelinelabs.conductor.Conductor
import com.bluelinelabs.conductor.Router
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.internal.LifecycleHandler
import com.github.k1rakishou.kurobanewnavstacktest.R
import com.github.k1rakishou.kurobanewnavstacktest.base.BaseController
import com.github.k1rakishou.kurobanewnavstacktest.base.ControllerPresenterDelegate
import com.github.k1rakishou.kurobanewnavstacktest.base.ControllerPresenterDelegateImpl
import com.github.k1rakishou.kurobanewnavstacktest.controller.MainController
import com.github.k1rakishou.kurobanewnavstacktest.controller.slide.SlideUiElementsController
import com.github.k1rakishou.kurobanewnavstacktest.controller.split.SplitNavController
import com.github.k1rakishou.kurobanewnavstacktest.utils.BackgroundUtils
import com.github.k1rakishou.kurobanewnavstacktest.utils.ChanSettings.isSplitMode
import com.github.k1rakishou.kurobanewnavstacktest.utils.findRouterWithControllerByTag
import com.github.k1rakishou.kurobanewnavstacktest.widget.TouchBlockingFrameLayout
import dev.chrisbanes.insetter.Insetter

Expand All @@ -28,6 +36,7 @@ class MainActivity : AppCompatActivity(), ControllerPresenterDelegate, ActivityC
window.navigationBarColor = Color.TRANSPARENT

rootContainer = findViewById(R.id.root_container)
// router = attachRouterHacky(this, rootContainer, savedInstanceState)
router = Conductor.attachRouter(this, rootContainer, savedInstanceState)
controllerPresenterDelegate = ControllerPresenterDelegateImpl(router)

Expand Down Expand Up @@ -69,4 +78,55 @@ class MainActivity : AppCompatActivity(), ControllerPresenterDelegate, ActivityC
override fun activity(): AppCompatActivity {
return this
}

// TODO(KurobaEx): this doesn't work. Because of this not working there is a problem with
// Split/Slide root controller getting rebound upon config change which leads to nasty bugs
// (one of them is causing toolbars to get initialized with wrong state). This cannot be fixed
// right now because I have no idea how to properly remove controller from backstack upon config
// change.
private fun attachRouterHacky(
activity: Activity,
container: ViewGroup,
savedInstanceState: Bundle?
): Router {
BackgroundUtils.ensureMainThread()
val isSplitMode = isSplitMode(activity)
val router = LifecycleHandler.install(activity)
.getRouter(container, savedInstanceState)

if (savedInstanceState != null) {
// This is a hack to remove previously added controllers to avoid rebinding them just to pop
// them again afterwards when screen orientation change occurs. Basically, what happens, after
// the phone is rotated, and lets say we were in Portrait orientation, the Slide controller
// stack is present in the router backstack and it is rebound. Then we get to the point where
// we decide what layout mode to use (slide or split) and replace the previous controller
// (slide in this case) with new controller (split in this case). This may lead to all kind of
// funny bugs so we want to avoid that controller getting rebound. So we want to pop it before
// calling "router.rebindIfNeeded()"
val controllerTag = if (isSplitMode) {
SlideUiElementsController.CONTROLLER_TAG
} else {
SplitNavController.CONTROLLER_TAG
}

val result = router.findRouterWithControllerByTag(controllerTag)
if (result != null) {
val (foundRouter, foundController) = result
val backstackCopy = foundRouter.backstack

val index = backstackCopy.indexOfFirst { routerTransaction ->
(routerTransaction.controller as? BaseController)?.getControllerTag() == controllerTag
}

if (index >= 0) {
backstackCopy.removeAt(index)
foundRouter.setBackstack(backstackCopy, null)
}
}
}

router.rebindIfNeeded()
return router
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ object AndroidUtils {
fun getBoolRes(@BoolRes id: Int): Boolean = getResources().getBoolean(id)
fun isTablet(): Boolean = getBoolRes(R.bool.isTablet)

fun Context.isLandscapeOrientation(): Boolean {
return resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
}

fun isAndroid11(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.github.k1rakishou.kurobanewnavstacktest.utils

import android.content.Context
import android.content.res.Configuration
import com.github.k1rakishou.kurobanewnavstacktest.utils.AndroidUtils.isLandscapeOrientation
import com.github.k1rakishou.kurobanewnavstacktest.utils.AndroidUtils.isTablet

object ChanSettings {
val OVERHANG_SIZE = 20.dp

fun showLockCollapsableViews(context: Context): Boolean {
// TODO(KurobaEx):
// TODO(KurobaEx): make this a separate setting when migrating this
// into the main project
return isSplitMode(context) && isTablet()
}

Expand All @@ -17,7 +18,7 @@ object ChanSettings {
return false
}

return context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
return context.isLandscapeOrientation()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import androidx.core.view.updateLayoutParams
import com.airbnb.epoxy.AsyncEpoxyController
import com.airbnb.epoxy.EpoxyController
import com.airbnb.epoxy.EpoxyRecyclerView
import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.Router
import com.github.k1rakishou.kurobanewnavstacktest.base.BaseController
import com.github.k1rakishou.kurobanewnavstacktest.base.ControllerTag
import java.util.*

val Int.dp: Int
Expand Down Expand Up @@ -153,4 +157,30 @@ fun EditText.doIgnoringTextWatcher(textWatcher: TextWatcher, func: EditText.() -
removeTextChangedListener(textWatcher)
func(this)
addTextChangedListener(textWatcher)
}

fun Router.findRouterWithControllerByTag(controllerTag: ControllerTag): Pair<Router, BaseController>? {
return findRouterWithControllerByTagInternal(this, controllerTag)
}

private fun findRouterWithControllerByTagInternal(
router: Router,
controllerTag: ControllerTag
): Pair<Router, BaseController>? {
for (routerTransaction in router.backstack) {
val controller = routerTransaction.controller

if ((controller as? BaseController)?.getControllerTag() == controllerTag) {
return Pair(router, controller)
}

for (childRouter in routerTransaction.controller.childRouters) {
val result = findRouterWithControllerByTagInternal(childRouter, controllerTag)
if (result != null) {
return result
}
}
}

return null
}
Loading

0 comments on commit 49f66da

Please sign in to comment.