Move lock screen fragment within pager

This commit is contained in:
Jonas Lochmann 2020-11-02 01:00:00 +01:00
parent 73f1a22ab4
commit 7f207d0c08
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
6 changed files with 151 additions and 134 deletions

View file

@ -23,15 +23,18 @@ import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import io.timelimit.android.R
import io.timelimit.android.extensions.showSafe
import io.timelimit.android.logic.BlockingReason
import io.timelimit.android.logic.DefaultAppLogic
import io.timelimit.android.sync.network.UpdatePrimaryDeviceRequestType
import io.timelimit.android.ui.IsAppInForeground
import io.timelimit.android.ui.login.NewLoginFragment
import io.timelimit.android.ui.main.ActivityViewModel
import io.timelimit.android.ui.main.ActivityViewModelHolder
import io.timelimit.android.ui.manage.child.primarydevice.UpdatePrimaryDeviceDialogFragment
import io.timelimit.android.ui.util.SyncStatusModel
import kotlinx.android.synthetic.main.lock_activity.*
class LockActivity : AppCompatActivity(), ActivityViewModelHolder {
companion object {
@ -58,6 +61,9 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder {
}
private val model: LockModel by viewModels()
private val syncModel: SyncStatusModel by viewModels()
private val activityModel: ActivityViewModel by viewModels()
private var isResumed = false
override var ignoreStop: Boolean = false
@ -74,27 +80,30 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.lock_activity)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, LockFragment.newInstance(blockedPackageName, blockedActivityName))
.commitNow()
}
setContentView(R.layout.lock_activity)
if (savedInstanceState == null) {
stopMediaPlayback()
}
val syncModel = ViewModelProviders.of(this).get(SyncStatusModel::class.java)
syncModel.statusText.observe(this, Observer {
supportActionBar?.subtitle = it
})
syncModel.statusText.observe(this) { supportActionBar?.subtitle = it }
currentInstances.add(this)
model.init(blockedPackageName, blockedActivityName)
pager.adapter = LockActivityAdapter(supportFragmentManager)
model.content.observe(this) {
if (isResumed && it is LockscreenContent.Blocked.BlockedCategory && it.reason == BlockingReason.RequiresCurrentDevice && !model.didOpenSetCurrentDeviceScreen) {
model.didOpenSetCurrentDeviceScreen = true
UpdatePrimaryDeviceDialogFragment
.newInstance(UpdatePrimaryDeviceRequestType.SetThisDevice)
.show(supportFragmentManager)
}
}
}
override fun onDestroy() {
@ -103,9 +112,7 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder {
currentInstances.remove(this)
}
override fun getActivityViewModel(): ActivityViewModel {
return ViewModelProviders.of(this).get(ActivityViewModel::class.java)
}
override fun getActivityViewModel(): ActivityViewModel = activityModel
override fun showAuthenticationScreen() {
NewLoginFragment().showSafe(supportFragmentManager, LOGIN_DIALOG_TAG)
@ -115,12 +122,14 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder {
super.onResume()
lockTaskModeWorkaround()
isResumed = true
}
override fun onPause() {
super.onPause()
lockTaskModeWorkaround()
isResumed = false
}
override fun onStart() {

View file

@ -0,0 +1,30 @@
/*
* TimeLimit Copyright <C> 2019 - 2020 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.timelimit.android.ui.lock
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
class LockActivityAdapter(fragmentManager: FragmentManager): FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getCount(): Int = 1
override fun getItem(position: Int): Fragment = when (position) {
0 -> LockReasonFragment()
else -> throw IllegalArgumentException()
}
}

View file

@ -54,6 +54,8 @@ class LockModel(application: Application): AndroidViewModel(application) {
val title: String? get() = logic.platformIntegration.getLocalAppTitle(packageAndActivityNameLiveInternal.value!!.first)
val icon: Drawable? get() = logic.platformIntegration.getAppIcon(packageAndActivityNameLiveInternal.value!!.first)
val packageAndActivityNameLive: LiveData<Pair<String, String?>> = packageAndActivityNameLiveInternal
var didOpenSetCurrentDeviceScreen = false
fun init(packageName: String, activityName: String?) {
if (didInit) return
@ -119,18 +121,21 @@ class LockModel(application: Application): AndroidViewModel(application) {
val categoryHandlings = appBaseHandling.categoryIds.map { handlingCache.get(it) }
val blockingHandling = categoryHandlings.find { it.shouldBlockActivities }
value = if (blockingHandling == null) LockscreenContent.Close else LockscreenContent.BlockedCategory(
value = if (blockingHandling == null) LockscreenContent.Close else LockscreenContent.Blocked.BlockedCategory(
deviceAndUserRelatedData = deviceAndUserRelatedData,
blockingHandling = blockingHandling,
level = appBaseHandling.level,
userRelatedData = deviceAndUserRelatedData.userRelatedData,
appBaseHandling = appBaseHandling
appPackageName = packageName,
appActivityName = activityName
).also { scheduleUpdate((blockingHandling.dependsOnMaxTime - realTime.timeInMillis)) }
} else if (appBaseHandling is AppBaseHandling.BlockDueToNoCategory) {
value = LockscreenContent.BlockDueToNoCategory(
value = LockscreenContent.Blocked.BlockDueToNoCategory(
userRelatedData = deviceAndUserRelatedData.userRelatedData,
deviceId = deviceAndUserRelatedData.deviceRelatedData.deviceEntry.id,
enableActivityLevelBlocking = deviceAndUserRelatedData.deviceRelatedData.deviceEntry.enableActivityLevelBlocking
enableActivityLevelBlocking = deviceAndUserRelatedData.deviceRelatedData.deviceEntry.enableActivityLevelBlocking,
appPackageName = packageName,
appActivityName = activityName
)
} else {
value = LockscreenContent.Close; return
@ -201,13 +206,20 @@ class LockModel(application: Application): AndroidViewModel(application) {
sealed class LockscreenContent {
object Close: LockscreenContent()
data class BlockedCategory(
sealed class Blocked: LockscreenContent() {
abstract val userRelatedData: UserRelatedData
abstract val appPackageName: String
abstract val appActivityName: String?
abstract val enableActivityLevelBlocking: Boolean
class BlockedCategory(
val deviceAndUserRelatedData: DeviceAndUserRelatedData,
val blockingHandling: CategoryItselfHandling,
val appBaseHandling: AppBaseHandling,
val level: BlockingLevel,
val userRelatedData: UserRelatedData
): LockscreenContent() {
override val userRelatedData: UserRelatedData,
override val appPackageName: String,
override val appActivityName: String?
): Blocked() {
val appCategoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title
val reason = blockingHandling.activityBlockingReason
val deviceId = deviceAndUserRelatedData.deviceRelatedData.deviceEntry.id
@ -216,12 +228,15 @@ sealed class LockscreenContent {
val blockedCategoryId = blockingHandling.createdWithCategoryRelatedData.category.id
val deviceRelatedData = deviceAndUserRelatedData.deviceRelatedData
val hasFullVersion = deviceRelatedData.isConnectedAndHasPremium || deviceRelatedData.isLocalMode
val enableActivityLevelBlocking = deviceAndUserRelatedData.deviceRelatedData.deviceEntry.enableActivityLevelBlocking
override val enableActivityLevelBlocking = deviceAndUserRelatedData.deviceRelatedData.deviceEntry.enableActivityLevelBlocking
}
data class BlockDueToNoCategory(
val userRelatedData: UserRelatedData,
class BlockDueToNoCategory(
override val userRelatedData: UserRelatedData,
val deviceId: String,
val enableActivityLevelBlocking: Boolean
): LockscreenContent()
override val enableActivityLevelBlocking: Boolean,
override val appPackageName: String,
override val appActivityName: String?
): Blocked()
}
}

View file

@ -30,8 +30,8 @@ import io.timelimit.android.data.extensions.sortedCategories
import io.timelimit.android.data.model.*
import io.timelimit.android.data.model.derived.DeviceRelatedData
import io.timelimit.android.data.model.derived.UserRelatedData
import io.timelimit.android.databinding.LockFragmentBinding
import io.timelimit.android.databinding.LockFragmentCategoryButtonBinding
import io.timelimit.android.databinding.LockReasonFragmentBinding
import io.timelimit.android.date.DateInTimezone
import io.timelimit.android.livedata.*
import io.timelimit.android.logic.*
@ -53,38 +53,13 @@ import io.timelimit.android.ui.payment.RequiresPurchaseDialogFragment
import io.timelimit.android.ui.view.SelectTimeSpanViewListener
import java.util.*
class LockFragment : Fragment() {
class LockReasonFragment : Fragment() {
companion object {
private const val EXTRA_PACKAGE_NAME = "pkg"
private const val EXTRA_ACTIVITY = "activitiy"
private const val STATUS_DID_OPEN_SET_CURRENT_DEVICE_SCREEN = "didOpenSetCurrentDeviceScreen"
private const val LOCATION_REQUEST_CODE = 1
fun newInstance(packageName: String, activity: String?): LockFragment {
val result = LockFragment()
val arguments = Bundle()
arguments.putString(EXTRA_PACKAGE_NAME, packageName)
if (activity != null) {
arguments.putString(EXTRA_ACTIVITY, activity)
}
result.arguments = arguments
return result
}
}
private var didOpenSetCurrentDeviceScreen = false
private val packageName: String by lazy { requireArguments().getString(EXTRA_PACKAGE_NAME)!! }
private val activityName: String? by lazy {
if (requireArguments().containsKey(EXTRA_ACTIVITY))
requireArguments().getString(EXTRA_ACTIVITY)
else
null
}
private val auth: ActivityViewModel by lazy { getActivityViewModel(requireActivity()) }
private lateinit var binding: LockFragmentBinding
private lateinit var binding: LockReasonFragmentBinding
private val model: LockModel by activityViewModels()
private fun setupHandlers(deviceId: String, userRelatedData: UserRelatedData, blockedCategoryId: String?) {
@ -140,23 +115,23 @@ class LockFragment : Fragment() {
(activity as LockActivity).showAuthenticationScreen()
}
override fun setThisDeviceAsCurrentDevice() = this@LockFragment.setThisDeviceAsCurrentDevice()
override fun setThisDeviceAsCurrentDevice() = this@LockReasonFragment.setThisDeviceAsCurrentDevice()
override fun requestLocationPermission() {
RequestWifiPermission.doRequest(this@LockFragment, LOCATION_REQUEST_CODE)
RequestWifiPermission.doRequest(this@LockReasonFragment, LOCATION_REQUEST_CODE)
}
}
}
private fun setThisDeviceAsCurrentDevice() {
didOpenSetCurrentDeviceScreen = true
model.didOpenSetCurrentDeviceScreen = true
UpdatePrimaryDeviceDialogFragment
.newInstance(UpdatePrimaryDeviceRequestType.SetThisDevice)
.show(parentFragmentManager)
}
private fun bindAddToCategoryOptions(userRelatedData: UserRelatedData) {
private fun bindAddToCategoryOptions(userRelatedData: UserRelatedData, blockedPackageName: String) {
binding.addToCategoryOptions.removeAllViews()
userRelatedData.sortedCategories().forEach { (_, category) ->
@ -166,7 +141,7 @@ class LockFragment : Fragment() {
auth.tryDispatchParentAction(
AddCategoryAppsAction(
categoryId = category.category.id,
packageNames = listOf(packageName)
packageNames = listOf(blockedPackageName)
)
)
}
@ -238,22 +213,8 @@ class LockFragment : Fragment() {
model.missingNetworkIdPermission.observe(viewLifecycleOwner) { binding.missingNetworkIdPermission = it }
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
didOpenSetCurrentDeviceScreen = savedInstanceState.getBoolean(STATUS_DID_OPEN_SET_CURRENT_DEVICE_SCREEN)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean(STATUS_DID_OPEN_SET_CURRENT_DEVICE_SCREEN, didOpenSetCurrentDeviceScreen)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = LockFragmentBinding.inflate(layoutInflater, container, false)
binding = LockReasonFragmentBinding.inflate(layoutInflater, container, false)
AuthenticationFab.manageAuthenticationFab(
fab = binding.fab,
@ -272,7 +233,7 @@ class LockFragment : Fragment() {
)
}
binding.packageName = packageName
model.packageAndActivityNameLive.observe(viewLifecycleOwner) { binding.packageName = it.first }
binding.appTitle = model.title ?: "???"
binding.appIcon.setImageDrawable(model.icon)
@ -288,9 +249,11 @@ class LockFragment : Fragment() {
requireActivity().finish()
}
is LockscreenContent.BlockedCategory -> {
binding.activityName = if (content.enableActivityLevelBlocking) activityName?.removePrefix(packageName) else null
is LockscreenContent.Blocked -> {
binding.activityName = if (content.enableActivityLevelBlocking) content.appActivityName?.removePrefix(content.appPackageName) else null
when (content) {
is LockscreenContent.Blocked.BlockedCategory -> {
binding.appCategoryTitle = content.appCategoryTitle
binding.reason = content.reason
binding.blockedKindLabel = when (content.level) {
@ -313,14 +276,8 @@ class LockFragment : Fragment() {
activity = requireActivity(),
hasFullVersion = content.hasFullVersion
)
if (content.reason == BlockingReason.RequiresCurrentDevice && !didOpenSetCurrentDeviceScreen && isResumed) {
setThisDeviceAsCurrentDevice()
} else null
}
is LockscreenContent.BlockDueToNoCategory -> {
binding.activityName = if (content.enableActivityLevelBlocking) activityName?.removePrefix(packageName) else null
is LockscreenContent.Blocked.BlockDueToNoCategory -> {
binding.appCategoryTitle = null
binding.reason = BlockingReason.NotPartOfAnCategory
binding.blockedKindLabel = "App"
@ -331,7 +288,12 @@ class LockFragment : Fragment() {
userRelatedData = content.userRelatedData
)
bindAddToCategoryOptions(content.userRelatedData)
bindAddToCategoryOptions(
userRelatedData = content.userRelatedData,
blockedPackageName = content.appPackageName
)
}
}.let {/* require handling all paths */}
}
}.let {/* require handling all paths */}
}

View file

@ -13,9 +13,10 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container"
android:id="@+id/pager"
tools:context=".ui.lock.LockActivity" />

View file

@ -16,7 +16,7 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.lock.LockFragment">
tools:context=".ui.lock.LockReasonFragment">
<data>
<variable