mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 17:59:51 +02:00
Improve edge to edge support
This commit is contained in:
parent
679276e3cf
commit
bc0e83b916
6 changed files with 209 additions and 190 deletions
|
@ -183,6 +183,7 @@ dependencies {
|
||||||
implementation 'androidx.compose.material:material-icons-extended:1.7.5'
|
implementation 'androidx.compose.material:material-icons-extended:1.7.5'
|
||||||
debugImplementation "androidx.compose.ui:ui-tooling:1.7.5"
|
debugImplementation "androidx.compose.ui:ui-tooling:1.7.5"
|
||||||
implementation 'androidx.fragment:fragment-ktx:1.8.5'
|
implementation 'androidx.fragment:fragment-ktx:1.8.5'
|
||||||
|
implementation 'androidx.fragment:fragment-compose:1.8.5'
|
||||||
|
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||||
implementation "androidx.navigation:navigation-ui:$nav_version"
|
implementation "androidx.navigation:navigation-ui:$nav_version"
|
||||||
|
|
|
@ -23,16 +23,30 @@ import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.SystemBarStyle
|
import androidx.activity.SystemBarStyle
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.core.view.updatePadding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.material.Tab
|
||||||
|
import androidx.compose.material.TabRow
|
||||||
|
import androidx.compose.material.TabRowDefaults
|
||||||
|
import androidx.compose.material.TabRowDefaults.tabIndicatorOffset
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.fragment.compose.AndroidFragment
|
||||||
|
import androidx.lifecycle.asFlow
|
||||||
|
import androidx.lifecycle.map
|
||||||
import io.timelimit.android.R
|
import io.timelimit.android.R
|
||||||
import io.timelimit.android.databinding.LockActivityBinding
|
import io.timelimit.android.data.model.UserType
|
||||||
import io.timelimit.android.extensions.showSafe
|
import io.timelimit.android.extensions.showSafe
|
||||||
import io.timelimit.android.logic.BlockingReason
|
import io.timelimit.android.logic.BlockingReason
|
||||||
import io.timelimit.android.logic.DefaultAppLogic
|
import io.timelimit.android.logic.DefaultAppLogic
|
||||||
|
@ -40,11 +54,12 @@ import io.timelimit.android.sync.network.UpdatePrimaryDeviceRequestType
|
||||||
import io.timelimit.android.u2f.U2fManager
|
import io.timelimit.android.u2f.U2fManager
|
||||||
import io.timelimit.android.u2f.protocol.U2FDevice
|
import io.timelimit.android.u2f.protocol.U2FDevice
|
||||||
import io.timelimit.android.ui.IsAppInForeground
|
import io.timelimit.android.ui.IsAppInForeground
|
||||||
|
import io.timelimit.android.ui.ScreenScaffold
|
||||||
|
import io.timelimit.android.ui.Theme
|
||||||
import io.timelimit.android.ui.login.AuthTokenLoginProcessor
|
import io.timelimit.android.ui.login.AuthTokenLoginProcessor
|
||||||
import io.timelimit.android.ui.login.NewLoginFragment
|
import io.timelimit.android.ui.login.NewLoginFragment
|
||||||
import io.timelimit.android.ui.main.ActivityViewModel
|
import io.timelimit.android.ui.main.ActivityViewModel
|
||||||
import io.timelimit.android.ui.main.ActivityViewModelHolder
|
import io.timelimit.android.ui.main.ActivityViewModelHolder
|
||||||
import io.timelimit.android.ui.main.AuthenticationFab
|
|
||||||
import io.timelimit.android.ui.manage.child.primarydevice.UpdatePrimaryDeviceDialogFragment
|
import io.timelimit.android.ui.manage.child.primarydevice.UpdatePrimaryDeviceDialogFragment
|
||||||
import io.timelimit.android.ui.util.SyncStatusModel
|
import io.timelimit.android.ui.util.SyncStatusModel
|
||||||
|
|
||||||
|
@ -91,8 +106,6 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
private val showAuth = MutableLiveData<Boolean>().apply { value = false }
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
@ -107,19 +120,98 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
supportActionBar!!.hide()
|
||||||
|
|
||||||
U2fManager.setupActivity(this)
|
U2fManager.setupActivity(this)
|
||||||
|
|
||||||
val adapter = LockActivityAdapter(supportFragmentManager, this)
|
val subtitleLive = syncModel.statusText.asFlow()
|
||||||
|
val showTasksLive = model.content.map {
|
||||||
|
val isTimeOver = it is LockscreenContent.Blocked.BlockedCategory && it.blockingHandling.activityBlockingReason == BlockingReason.TimeOver
|
||||||
|
|
||||||
val binding = LockActivityBinding.inflate(layoutInflater)
|
isTimeOver
|
||||||
setContentView(binding.root)
|
}.asFlow()
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
|
setContent {
|
||||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
val subtitle by subtitleLive.collectAsState(null)
|
||||||
|
val showTasks by showTasksLive.collectAsState(false)
|
||||||
|
val pager = rememberPagerState(initialPage = 0, pageCount = {
|
||||||
|
if (showTasks) 3
|
||||||
|
else 2
|
||||||
|
})
|
||||||
|
val isAuthenticated by getActivityViewModel().authenticatedUser
|
||||||
|
.map { it?.second?.type == UserType.Parent }
|
||||||
|
.asFlow().collectAsState(initial = false)
|
||||||
|
|
||||||
view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)
|
Theme {
|
||||||
|
ScreenScaffold(
|
||||||
|
screen = null,
|
||||||
|
title = getString(R.string.app_name),
|
||||||
|
subtitle = subtitle,
|
||||||
|
backStack = emptyList(),
|
||||||
|
snackbarHostState = null,
|
||||||
|
content = { padding ->
|
||||||
|
Column (Modifier.fillMaxSize().padding(padding)) {
|
||||||
|
TabRow(
|
||||||
|
pager.currentPage,
|
||||||
|
indicator = { tabPositions ->
|
||||||
|
// workaround for bug
|
||||||
|
TabRowDefaults.Indicator(
|
||||||
|
Modifier.tabIndicatorOffset(tabPositions[
|
||||||
|
pager.currentPage.coerceAtMost(tabPositions.size - 1)
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Tab(
|
||||||
|
selected = pager.currentPage == 0,
|
||||||
|
onClick = { pager.requestScrollToPage(0) }
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.lock_tab_reason),
|
||||||
|
Modifier.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
WindowInsetsCompat.CONSUMED
|
Tab(
|
||||||
|
selected = pager.currentPage == 1,
|
||||||
|
onClick = { pager.requestScrollToPage(1) }
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.lock_tab_action),
|
||||||
|
Modifier.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showTasks) Tab(
|
||||||
|
selected = pager.currentPage == 2,
|
||||||
|
onClick = { pager.requestScrollToPage(2) }
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.lock_tab_task),
|
||||||
|
Modifier.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalPager(
|
||||||
|
pager,
|
||||||
|
Modifier.weight(1.0F, fill = true),
|
||||||
|
pageContent = { index ->
|
||||||
|
when (index) {
|
||||||
|
0 -> AndroidFragment<LockReasonFragment>(Modifier.fillMaxSize())
|
||||||
|
1 -> AndroidFragment<LockActionFragment>(Modifier.fillMaxSize())
|
||||||
|
2 -> AndroidFragment<LockTaskFragment>(Modifier.fillMaxSize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
executeCommand = {},
|
||||||
|
showAuthenticationDialog =
|
||||||
|
if (pager.currentPage == 1 && !isAuthenticated) ({ showAuthenticationScreen() })
|
||||||
|
else null
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
syncModel.statusText.observe(this) { supportActionBar?.subtitle = it }
|
syncModel.statusText.observe(this) { supportActionBar?.subtitle = it }
|
||||||
|
@ -128,8 +220,6 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
||||||
|
|
||||||
model.init(blockedPackageName, blockedActivityName)
|
model.init(blockedPackageName, blockedActivityName)
|
||||||
|
|
||||||
binding.pager.adapter = adapter
|
|
||||||
|
|
||||||
model.content.observe(this) {
|
model.content.observe(this) {
|
||||||
if (isResumed && it is LockscreenContent.Blocked.BlockedCategory && it.reason == BlockingReason.RequiresCurrentDevice && !model.didOpenSetCurrentDeviceScreen) {
|
if (isResumed && it is LockscreenContent.Blocked.BlockedCategory && it.reason == BlockingReason.RequiresCurrentDevice && !model.didOpenSetCurrentDeviceScreen) {
|
||||||
model.didOpenSetCurrentDeviceScreen = true
|
model.didOpenSetCurrentDeviceScreen = true
|
||||||
|
@ -140,30 +230,12 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.De
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationFab.manageAuthenticationFab(
|
activityModel.shouldHighlightAuthenticationButton.observe(this) {
|
||||||
fab = binding.fab,
|
if (it) {
|
||||||
shouldHighlight = activityModel.shouldHighlightAuthenticationButton,
|
activityModel.shouldHighlightAuthenticationButton.postValue(false)
|
||||||
authenticatedUser = activityModel.authenticatedUser,
|
|
||||||
activity = this,
|
|
||||||
doesSupportAuth = showAuth
|
|
||||||
)
|
|
||||||
|
|
||||||
binding.fab.setOnClickListener { showAuthenticationScreen() }
|
showAuthenticationScreen()
|
||||||
|
|
||||||
binding.pager.addOnPageChangeListener(object: ViewPager.SimpleOnPageChangeListener() {
|
|
||||||
override fun onPageSelected(position: Int) {
|
|
||||||
super.onPageSelected(position)
|
|
||||||
|
|
||||||
showAuth.value = position == 1
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
binding.tabs.setupWithViewPager(binding.pager)
|
|
||||||
|
|
||||||
model.content.observe(this) {
|
|
||||||
val isTimeOver = it is LockscreenContent.Blocked.BlockedCategory && it.blockingHandling.activityBlockingReason == BlockingReason.TimeOver
|
|
||||||
|
|
||||||
adapter.showTasksFragment = isTimeOver
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(object: OnBackPressedCallback(true) {
|
onBackPressedDispatcher.addCallback(object: OnBackPressedCallback(true) {
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 android.content.Context
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import androidx.fragment.app.FragmentPagerAdapter
|
|
||||||
import io.timelimit.android.R
|
|
||||||
import kotlin.properties.Delegates
|
|
||||||
|
|
||||||
class LockActivityAdapter(fragmentManager: FragmentManager, private val context: Context): FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
|
||||||
var showTasksFragment: Boolean by Delegates.observable(false) { _, _, _ -> notifyDataSetChanged() }
|
|
||||||
|
|
||||||
override fun getCount(): Int = if (showTasksFragment) 3 else 2
|
|
||||||
|
|
||||||
override fun getItem(position: Int): Fragment = when (position) {
|
|
||||||
0 -> LockReasonFragment()
|
|
||||||
1 -> LockActionFragment()
|
|
||||||
2 -> LockTaskFragment()
|
|
||||||
else -> throw IllegalArgumentException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPageTitle(position: Int): CharSequence? = context.getString(when (position) {
|
|
||||||
0 -> R.string.lock_tab_reason
|
|
||||||
1 -> R.string.lock_tab_action
|
|
||||||
2 -> R.string.lock_tab_task
|
|
||||||
else -> throw IllegalArgumentException()
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -22,14 +22,17 @@ import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.SystemBarStyle
|
import androidx.activity.SystemBarStyle
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.core.view.updatePadding
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import androidx.lifecycle.map
|
import androidx.lifecycle.map
|
||||||
import io.timelimit.android.BuildConfig
|
import io.timelimit.android.BuildConfig
|
||||||
import io.timelimit.android.R
|
import io.timelimit.android.R
|
||||||
|
@ -40,6 +43,8 @@ import io.timelimit.android.integration.platform.android.AndroidIntegrationApps
|
||||||
import io.timelimit.android.logic.DefaultAppLogic
|
import io.timelimit.android.logic.DefaultAppLogic
|
||||||
import io.timelimit.android.u2f.U2fManager
|
import io.timelimit.android.u2f.U2fManager
|
||||||
import io.timelimit.android.u2f.protocol.U2FDevice
|
import io.timelimit.android.u2f.protocol.U2FDevice
|
||||||
|
import io.timelimit.android.ui.ScreenScaffold
|
||||||
|
import io.timelimit.android.ui.Theme
|
||||||
import io.timelimit.android.ui.backdoor.BackdoorDialogFragment
|
import io.timelimit.android.ui.backdoor.BackdoorDialogFragment
|
||||||
import io.timelimit.android.ui.login.AuthTokenLoginProcessor
|
import io.timelimit.android.ui.login.AuthTokenLoginProcessor
|
||||||
import io.timelimit.android.ui.login.NewLoginFragment
|
import io.timelimit.android.ui.login.NewLoginFragment
|
||||||
|
@ -71,6 +76,8 @@ class AnnoyActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.D
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val logic = DefaultAppLogic.with(this)
|
||||||
|
|
||||||
val isNightMode =
|
val isNightMode =
|
||||||
(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==
|
(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==
|
||||||
Configuration.UI_MODE_NIGHT_YES
|
Configuration.UI_MODE_NIGHT_YES
|
||||||
|
@ -82,21 +89,63 @@ class AnnoyActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.D
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
U2fManager.setupActivity(this)
|
supportActionBar!!.hide()
|
||||||
|
|
||||||
val logic = DefaultAppLogic.with(this)
|
setContent {
|
||||||
|
Theme {
|
||||||
|
ScreenScaffold(
|
||||||
|
screen = null,
|
||||||
|
title = getString(R.string.app_name),
|
||||||
|
subtitle = null,
|
||||||
|
backStack = emptyList(),
|
||||||
|
snackbarHostState = null,
|
||||||
|
content = { padding ->
|
||||||
|
AndroidView(
|
||||||
|
factory = {
|
||||||
|
val binding = AnnoyActivityBinding.inflate(LayoutInflater.from(it))
|
||||||
|
|
||||||
val binding = AnnoyActivityBinding.inflate(layoutInflater)
|
logic.annoyLogic.nextManualUnblockCountdown.observe(this) { countdown ->
|
||||||
setContentView(binding.root)
|
binding.canRequestUnlock = countdown == 0L
|
||||||
|
binding.countdownText = getString(R.string.annoy_timer, TimeTextUtil.seconds((countdown / 1000).toInt(), this@AnnoyActivity))
|
||||||
|
}
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
|
logic.deviceEntry.map {
|
||||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
val reasonItems = (it?.let { ManipulationWarnings.getFromDevice(it) } ?: ManipulationWarnings.empty)
|
||||||
|
.current
|
||||||
|
.map { getString(it.labelResourceId) }
|
||||||
|
|
||||||
view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)
|
if (reasonItems.isEmpty()) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
getString(R.string.annoy_reason, reasonItems.joinToString(separator = ", "))
|
||||||
|
}
|
||||||
|
}.observe(this) { binding.reasonText = it }
|
||||||
|
|
||||||
WindowInsetsCompat.CONSUMED
|
binding.unlockTemporarilyButton.setOnClickListener {
|
||||||
|
AnnoyUnlockDialogFragment.newInstance(AnnoyUnlockDialogFragment.UnlockDuration.Short)
|
||||||
|
.show(supportFragmentManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.parentUnlockButton.setOnClickListener {
|
||||||
|
AnnoyUnlockDialogFragment.newInstance(AnnoyUnlockDialogFragment.UnlockDuration.Long)
|
||||||
|
.show(supportFragmentManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.useBackdoorButton.setOnClickListener { BackdoorDialogFragment().show(supportFragmentManager) }
|
||||||
|
|
||||||
|
binding.root
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxSize().padding(padding)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
executeCommand = {},
|
||||||
|
showAuthenticationDialog = null
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U2fManager.setupActivity(this)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
val systemImageApps = packageManager.getInstalledApplications(0)
|
val systemImageApps = packageManager.getInstalledApplications(0)
|
||||||
.filter { it.flags and ApplicationInfo.FLAG_SYSTEM == ApplicationInfo.FLAG_SYSTEM }
|
.filter { it.flags and ApplicationInfo.FLAG_SYSTEM == ApplicationInfo.FLAG_SYSTEM }
|
||||||
|
@ -117,35 +166,6 @@ class AnnoyActivity : AppCompatActivity(), ActivityViewModelHolder, U2fManager.D
|
||||||
if (!shouldRun) shutdown()
|
if (!shouldRun) shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
logic.annoyLogic.nextManualUnblockCountdown.observe(this) { countdown ->
|
|
||||||
binding.canRequestUnlock = countdown == 0L
|
|
||||||
binding.countdownText = getString(R.string.annoy_timer, TimeTextUtil.seconds((countdown / 1000).toInt(), this@AnnoyActivity))
|
|
||||||
}
|
|
||||||
|
|
||||||
logic.deviceEntry.map {
|
|
||||||
val reasonItems = (it?.let { ManipulationWarnings.getFromDevice(it) } ?: ManipulationWarnings.empty)
|
|
||||||
.current
|
|
||||||
.map { getString(it.labelResourceId) }
|
|
||||||
|
|
||||||
if (reasonItems.isEmpty()) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
getString(R.string.annoy_reason, reasonItems.joinToString(separator = ", "))
|
|
||||||
}
|
|
||||||
}.observe(this) { binding.reasonText = it }
|
|
||||||
|
|
||||||
binding.unlockTemporarilyButton.setOnClickListener {
|
|
||||||
AnnoyUnlockDialogFragment.newInstance(AnnoyUnlockDialogFragment.UnlockDuration.Short)
|
|
||||||
.show(supportFragmentManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.parentUnlockButton.setOnClickListener {
|
|
||||||
AnnoyUnlockDialogFragment.newInstance(AnnoyUnlockDialogFragment.UnlockDuration.Long)
|
|
||||||
.show(supportFragmentManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.useBackdoorButton.setOnClickListener { BackdoorDialogFragment().show(supportFragmentManager) }
|
|
||||||
|
|
||||||
model.authenticatedUser.observe(this) { user ->
|
model.authenticatedUser.observe(this) { user ->
|
||||||
if (user?.second?.type == UserType.Parent) {
|
if (user?.second?.type == UserType.Parent) {
|
||||||
logic.annoyLogic.doParentTempUnlock()
|
logic.annoyLogic.doParentTempUnlock()
|
||||||
|
|
|
@ -17,16 +17,20 @@ package io.timelimit.android.ui.update
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.SystemBarStyle
|
import androidx.activity.SystemBarStyle
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.core.view.updatePadding
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import io.timelimit.android.R
|
import io.timelimit.android.R
|
||||||
import io.timelimit.android.databinding.UpdateActivityBinding
|
import io.timelimit.android.databinding.UpdateActivityBinding
|
||||||
import io.timelimit.android.logic.DefaultAppLogic
|
import io.timelimit.android.logic.DefaultAppLogic
|
||||||
|
import io.timelimit.android.ui.ScreenScaffold
|
||||||
|
import io.timelimit.android.ui.Theme
|
||||||
|
|
||||||
class UpdateActivity: AppCompatActivity() {
|
class UpdateActivity: AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -43,21 +47,37 @@ class UpdateActivity: AppCompatActivity() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val binding = DataBindingUtil.setContentView<UpdateActivityBinding>(this, R.layout.update_activity)
|
supportActionBar!!.hide()
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
|
setContent {
|
||||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
Theme {
|
||||||
|
ScreenScaffold(
|
||||||
|
screen = null,
|
||||||
|
title = getString(R.string.app_name),
|
||||||
|
subtitle = null,
|
||||||
|
backStack = emptyList(),
|
||||||
|
snackbarHostState = null,
|
||||||
|
content = { padding ->
|
||||||
|
AndroidView(
|
||||||
|
factory = {
|
||||||
|
val binding = UpdateActivityBinding.inflate(LayoutInflater.from(it))
|
||||||
|
|
||||||
view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)
|
UpdateView.bind(
|
||||||
|
view = binding.update,
|
||||||
|
lifecycleOwner = this,
|
||||||
|
fragmentManager = supportFragmentManager,
|
||||||
|
appLogic = DefaultAppLogic.with(this)
|
||||||
|
)
|
||||||
|
|
||||||
WindowInsetsCompat.CONSUMED
|
binding.root
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxSize().padding(padding)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
executeCommand = {},
|
||||||
|
showAuthenticationDialog = null
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateView.bind(
|
|
||||||
view = binding.update,
|
|
||||||
lifecycleOwner = this,
|
|
||||||
fragmentManager = supportFragmentManager,
|
|
||||||
appLogic = DefaultAppLogic.with(this)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,50 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
TimeLimit Copyright <C> 2019 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/>.
|
|
||||||
-->
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".ui.lock.LockActivity" >
|
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/tabs"
|
|
||||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
|
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.viewpager.widget.ViewPager
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:id="@+id/pager" />
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/fab"
|
|
||||||
app:fabSize="normal"
|
|
||||||
android:src="@drawable/ic_lock_open_white_24dp"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:layout_gravity="end|bottom"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
||||||
</LinearLayout>
|
|
Loading…
Add table
Add a link
Reference in a new issue