diff --git a/app/build.gradle b/app/build.gradle index 6530752..2c6456c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,14 +16,10 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-parcelize' apply plugin: "androidx.navigation.safeargs.kotlin" apply plugin: 'kotlin-kapt' -androidExtensions { - experimental = true -} - android { compileSdkVersion 30 defaultConfig { @@ -49,6 +45,9 @@ android { // set to empty string to disable this check buildConfigField 'String', 'updateServerBuildsCertificate', '"2170068198547F15129DE8CC46E2A8BF1485A6E5030916E26DDE41AE0E81DAC2"' } + buildFeatures { + viewBinding true + } flavorDimensions 'api', 'channel', 'server' productFlavors { diff --git a/app/src/main/java/io/timelimit/android/data/customtypes/Bitmask.kt b/app/src/main/java/io/timelimit/android/data/customtypes/Bitmask.kt index 27c5d0b..161f66b 100644 --- a/app/src/main/java/io/timelimit/android/data/customtypes/Bitmask.kt +++ b/app/src/main/java/io/timelimit/android/data/customtypes/Bitmask.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -18,7 +18,7 @@ package io.timelimit.android.data.customtypes import android.os.Parcelable import android.text.TextUtils import androidx.room.TypeConverter -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize import java.util.* import kotlin.collections.ArrayList diff --git a/app/src/main/java/io/timelimit/android/data/model/TimeLimitRule.kt b/app/src/main/java/io/timelimit/android/data/model/TimeLimitRule.kt index a874757..ce3808a 100644 --- a/app/src/main/java/io/timelimit/android/data/model/TimeLimitRule.kt +++ b/app/src/main/java/io/timelimit/android/data/model/TimeLimitRule.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -29,7 +29,7 @@ import io.timelimit.android.data.customtypes.ImmutableBitmaskAdapter import io.timelimit.android.extensions.MinuteOfDay import io.timelimit.android.livedata.ignoreUnchanged import io.timelimit.android.livedata.map -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize @Entity(tableName = "time_limit_rule") @TypeConverters(ImmutableBitmaskAdapter::class) diff --git a/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt b/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt index 1a8e230..e8951e3 100644 --- a/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt +++ b/app/src/main/java/io/timelimit/android/integration/platform/PlatformIntegration.kt @@ -21,7 +21,7 @@ import androidx.lifecycle.LiveData import androidx.room.TypeConverter import io.timelimit.android.data.model.App import io.timelimit.android.data.model.AppActivity -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize abstract class PlatformIntegration( val maximumProtectionLevel: ProtectionLevel diff --git a/app/src/main/java/io/timelimit/android/ui/fragment/SingleFragmentWrapper.kt b/app/src/main/java/io/timelimit/android/ui/fragment/SingleFragmentWrapper.kt index 791b626..2cb3f19 100644 --- a/app/src/main/java/io/timelimit/android/ui/fragment/SingleFragmentWrapper.kt +++ b/app/src/main/java/io/timelimit/android/ui/fragment/SingleFragmentWrapper.kt @@ -23,41 +23,40 @@ import androidx.fragment.app.Fragment import androidx.navigation.NavController import androidx.navigation.Navigation import io.timelimit.android.R +import io.timelimit.android.databinding.SingleFragmentWrapperBinding import io.timelimit.android.livedata.liveDataFromNonNullValue import io.timelimit.android.ui.main.ActivityViewModelHolder import io.timelimit.android.ui.main.AuthenticationFab -import kotlinx.android.synthetic.main.single_fragment_wrapper.* abstract class SingleFragmentWrapper: Fragment() { val activity: ActivityViewModelHolder by lazy { getActivity() as ActivityViewModelHolder } private lateinit var navController: NavController + protected lateinit var binding: SingleFragmentWrapperBinding protected val navigation get() = navController override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { navController = Navigation.findNavController(container!!) - return inflater.inflate(R.layout.single_fragment_wrapper, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + binding = SingleFragmentWrapperBinding.inflate(inflater, container, false) AuthenticationFab.manageAuthenticationFab( - fab = fab, + fab = binding.fab, fragment = this, shouldHighlight = activity.getActivityViewModel().shouldHighlightAuthenticationButton, authenticatedUser = activity.getActivityViewModel().authenticatedUser, doesSupportAuth = liveDataFromNonNullValue(showAuthButton) ) - fab.setOnClickListener { activity.showAuthenticationScreen() } + binding.fab.setOnClickListener { activity.showAuthenticationScreen() } if (savedInstanceState == null) { childFragmentManager.beginTransaction() .replace(R.id.container, createChildFragment()) .commit() } + + return binding.root } abstract fun createChildFragment(): Fragment diff --git a/app/src/main/java/io/timelimit/android/ui/homescreen/HomescreenActivity.kt b/app/src/main/java/io/timelimit/android/ui/homescreen/HomescreenActivity.kt index 09a7399..9d77f6d 100644 --- a/app/src/main/java/io/timelimit/android/ui/homescreen/HomescreenActivity.kt +++ b/app/src/main/java/io/timelimit/android/ui/homescreen/HomescreenActivity.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -26,8 +26,8 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import io.timelimit.android.R +import io.timelimit.android.databinding.ActivityHomescreenBinding import io.timelimit.android.databinding.ActivityHomescreenItemBinding -import kotlinx.android.synthetic.main.activity_homescreen.* class HomescreenActivity: AppCompatActivity() { companion object { @@ -35,11 +35,13 @@ class HomescreenActivity: AppCompatActivity() { } private val model: HomescreenModel by lazy { ViewModelProvider(this).get(HomescreenModel::class.java) } + private lateinit var binding: ActivityHomescreenBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_homescreen) + binding = ActivityHomescreenBinding.inflate(layoutInflater) + setContentView(binding.root) model.handleLaunchIfNotYetExecuted(intent.getBooleanExtra(FORCE_SELECTION, false)) @@ -80,14 +82,14 @@ class HomescreenActivity: AppCompatActivity() { } private fun initOptionList() { - maincard.visibility = View.VISIBLE + binding.maincard.visibility = View.VISIBLE val options = HomescreenUtil.launcherOptions(this) - launcher_options.removeAllViews() + binding.launcherOptions.removeAllViews() options.forEach { option -> - val view = ActivityHomescreenItemBinding.inflate(LayoutInflater.from(this), launcher_options, true) + val view = ActivityHomescreenItemBinding.inflate(LayoutInflater.from(this), binding.launcherOptions, true) view.label = try { packageManager.getApplicationLabel( @@ -119,18 +121,18 @@ class HomescreenActivity: AppCompatActivity() { } private fun hideOptionList() { - maincard.visibility = View.GONE + binding.maincard.visibility = View.GONE - launcher_options.removeAllViews() + binding.launcherOptions.removeAllViews() } private fun showProgress(progresss: Int) { - progress_card.visibility = View.VISIBLE - progress_bar.progress = progresss + binding.progressCard.visibility = View.VISIBLE + binding.progressBar.progress = progresss } private fun hideProgress() { - progress_card.visibility = View.GONE + binding.progressCard.visibility = View.GONE } override fun onResume() { diff --git a/app/src/main/java/io/timelimit/android/ui/lock/LockActivity.kt b/app/src/main/java/io/timelimit/android/ui/lock/LockActivity.kt index b8b4148..aa79d11 100644 --- a/app/src/main/java/io/timelimit/android/ui/lock/LockActivity.kt +++ b/app/src/main/java/io/timelimit/android/ui/lock/LockActivity.kt @@ -25,6 +25,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.MutableLiveData import androidx.viewpager.widget.ViewPager import io.timelimit.android.R +import io.timelimit.android.databinding.LockActivityBinding import io.timelimit.android.extensions.showSafe import io.timelimit.android.logic.BlockingReason import io.timelimit.android.logic.DefaultAppLogic @@ -36,7 +37,6 @@ 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.util.SyncStatusModel -import kotlinx.android.synthetic.main.lock_activity.* class LockActivity : AppCompatActivity(), ActivityViewModelHolder { companion object { @@ -88,7 +88,8 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder { val adapter = LockActivityAdapter(supportFragmentManager, this) - setContentView(R.layout.lock_activity) + val binding = LockActivityBinding.inflate(layoutInflater) + setContentView(binding.root) syncModel.statusText.observe(this) { supportActionBar?.subtitle = it } @@ -96,7 +97,7 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder { model.init(blockedPackageName, blockedActivityName) - pager.adapter = adapter + binding.pager.adapter = adapter model.content.observe(this) { if (isResumed && it is LockscreenContent.Blocked.BlockedCategory && it.reason == BlockingReason.RequiresCurrentDevice && !model.didOpenSetCurrentDeviceScreen) { @@ -109,16 +110,16 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder { } AuthenticationFab.manageAuthenticationFab( - fab = fab, + fab = binding.fab, shouldHighlight = activityModel.shouldHighlightAuthenticationButton, authenticatedUser = activityModel.authenticatedUser, activity = this, doesSupportAuth = showAuth ) - fab.setOnClickListener { showAuthenticationScreen() } + binding.fab.setOnClickListener { showAuthenticationScreen() } - pager.addOnPageChangeListener(object: ViewPager.SimpleOnPageChangeListener() { + binding.pager.addOnPageChangeListener(object: ViewPager.SimpleOnPageChangeListener() { override fun onPageSelected(position: Int) { super.onPageSelected(position) @@ -126,7 +127,7 @@ class LockActivity : AppCompatActivity(), ActivityViewModelHolder { } }) - tabs.setupWithViewPager(pager) + binding.tabs.setupWithViewPager(binding.pager) model.content.observe(this) { val isTimeOver = it is LockscreenContent.Blocked.BlockedCategory && it.blockingHandling.activityBlockingReason == BlockingReason.TimeOver diff --git a/app/src/main/java/io/timelimit/android/ui/lock/LockTaskFragment.kt b/app/src/main/java/io/timelimit/android/ui/lock/LockTaskFragment.kt index 6201e92..a7658d9 100644 --- a/app/src/main/java/io/timelimit/android/ui/lock/LockTaskFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/lock/LockTaskFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -23,25 +23,19 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.LinearLayoutManager -import io.timelimit.android.R import io.timelimit.android.data.model.ChildTask +import io.timelimit.android.databinding.RecyclerFragmentBinding import io.timelimit.android.ui.manage.child.tasks.ConfirmTaskDialogFragment -import kotlinx.android.synthetic.main.recycler_fragment.* class LockTaskFragment: Fragment() { private val model: LockModel by activityViewModels() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.recycler_fragment, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - + val binding = RecyclerFragmentBinding.inflate(inflater, container, false) val adapter = LockTaskAdapter() - recycler.layoutManager = LinearLayoutManager(requireContext()) - recycler.adapter = adapter + binding.recycler.layoutManager = LinearLayoutManager(requireContext()) + binding.recycler.adapter = adapter model.blockedCategoryTasks.observe(viewLifecycleOwner) { tasks -> adapter.content = listOf(LockTaskItem.Introduction) + tasks.map { LockTaskItem.Task(it) } @@ -55,5 +49,7 @@ class LockTaskFragment: Fragment() { ConfirmTaskDialogFragment.newInstance(taskId = task.taskId, taskTitle = task.taskTitle, fromManageScreen = false).show(parentFragmentManager) } } + + return binding.root } } \ No newline at end of file diff --git a/app/src/main/java/io/timelimit/android/ui/manage/category/appsandrules/CategoryAppsAndRulesFragment.kt b/app/src/main/java/io/timelimit/android/ui/manage/category/appsandrules/CategoryAppsAndRulesFragment.kt index 1a5490b..9275525 100644 --- a/app/src/main/java/io/timelimit/android/ui/manage/category/appsandrules/CategoryAppsAndRulesFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/manage/category/appsandrules/CategoryAppsAndRulesFragment.kt @@ -31,6 +31,7 @@ import io.timelimit.android.async.Threads import io.timelimit.android.data.Database import io.timelimit.android.data.model.HintsToShow import io.timelimit.android.data.model.TimeLimitRule +import io.timelimit.android.databinding.FragmentCategoryAppsAndRulesBinding import io.timelimit.android.logic.DefaultAppLogic import io.timelimit.android.sync.actions.AddCategoryAppsAction import io.timelimit.android.sync.actions.CreateTimeLimitRuleAction @@ -42,7 +43,6 @@ import io.timelimit.android.ui.manage.category.apps.add.AddCategoryAppsFragment import io.timelimit.android.ui.manage.category.timelimit_rules.edit.EditTimeLimitRuleDialogFragment import io.timelimit.android.ui.manage.category.timelimit_rules.edit.EditTimeLimitRuleDialogFragmentListener import io.timelimit.android.ui.manage.child.apps.assign.AssignAppCategoryDialogFragment -import kotlinx.android.synthetic.main.fragment_category_apps_and_rules.* abstract class CategoryAppsAndRulesFragment: Fragment(), Handlers, EditTimeLimitRuleDialogFragmentListener { private val adapter = AppAndRuleAdapter().also { it.handlers = this } @@ -53,16 +53,12 @@ abstract class CategoryAppsAndRulesFragment: Fragment(), Handlers, EditTimeLimit abstract val categoryId: String override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_category_apps_and_rules, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + val binding = FragmentCategoryAppsAndRulesBinding.inflate(inflater, container, false) model.init(userId = childId, categoryId = categoryId) - recycler.layoutManager = LinearLayoutManager(requireContext()) - recycler.adapter = adapter + binding.recycler.layoutManager = LinearLayoutManager(requireContext()) + binding.recycler.adapter = adapter model.dateAndUsedTimes.observe(viewLifecycleOwner) { (date, usedTimes) -> adapter.date = date @@ -91,7 +87,9 @@ abstract class CategoryAppsAndRulesFragment: Fragment(), Handlers, EditTimeLimit database.config().setHintsShownSync(HintsToShow.TIME_LIMIT_RULE_INTRODUCTION) } } - }).attachToRecyclerView(recycler) + }).attachToRecyclerView(binding.recycler) + + return binding.root } fun setListContent(items: List) { adapter.items = items } diff --git a/app/src/main/java/io/timelimit/android/ui/manage/category/blocked_times/BlockedTimeAreasFragment.kt b/app/src/main/java/io/timelimit/android/ui/manage/category/blocked_times/BlockedTimeAreasFragment.kt index a31fad3..4f50cee 100644 --- a/app/src/main/java/io/timelimit/android/ui/manage/category/blocked_times/BlockedTimeAreasFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/manage/category/blocked_times/BlockedTimeAreasFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -31,6 +31,7 @@ import io.timelimit.android.data.customtypes.ImmutableBitmask import io.timelimit.android.data.model.Category import io.timelimit.android.data.model.HintsToShow import io.timelimit.android.data.model.withConfigCopiedToOtherDates +import io.timelimit.android.databinding.FragmentBlockedTimeAreasBinding import io.timelimit.android.livedata.map import io.timelimit.android.livedata.waitForNonNullValue import io.timelimit.android.logic.DefaultAppLogic @@ -38,7 +39,6 @@ import io.timelimit.android.sync.actions.UpdateCategoryBlockedTimesAction import io.timelimit.android.ui.main.ActivityViewModel import io.timelimit.android.ui.main.getActivityViewModel import io.timelimit.android.ui.mustread.MustReadFragment -import kotlinx.android.synthetic.main.fragment_blocked_time_areas.* class BlockedTimeAreasFragment : Fragment(), CopyBlockedTimeAreasDialogFragmentListener { companion object { @@ -59,6 +59,7 @@ class BlockedTimeAreasFragment : Fragment(), CopyBlockedTimeAreasDialogFragmentL private val items = MutableLiveData() private val childId: String get() = requireArguments().getString(CHILD_ID)!! private val categoryId: String get() = requireArguments().getString(CATEGORY_ID)!! + private lateinit var binding: FragmentBlockedTimeAreasBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -82,10 +83,6 @@ class BlockedTimeAreasFragment : Fragment(), CopyBlockedTimeAreasDialogFragmentL } } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_blocked_time_areas, container, false) - } - fun updateBlockedTimes(oldMask: ImmutableBitmask, newMask: ImmutableBitmask) { if ( auth.tryDispatchParentAction( @@ -96,7 +93,7 @@ class BlockedTimeAreasFragment : Fragment(), CopyBlockedTimeAreasDialogFragmentL allowAsChild = true ) ) { - Snackbar.make(coordinator.parent as View, R.string.blocked_time_areas_snackbar_modified, Snackbar.LENGTH_SHORT) + Snackbar.make(binding.coordinator.parent as View, R.string.blocked_time_areas_snackbar_modified, Snackbar.LENGTH_SHORT) .also { if (auth.isParentAuthenticated()) { it.setAction(R.string.generic_undo) { @@ -119,29 +116,29 @@ class BlockedTimeAreasFragment : Fragment(), CopyBlockedTimeAreasDialogFragmentL } } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = FragmentBlockedTimeAreasBinding.inflate(inflater, container, false) - btn_help.setOnClickListener { + binding.btnHelp.setOnClickListener { BlockedTimeAreasHelpDialog().show(parentFragmentManager) } - btn_copy_to_other_days.setOnClickListener { + binding.btnCopyToOtherDays.setOnClickListener { if (auth.requestAuthenticationOrReturnTrue()) { CopyBlockedTimeAreasDialogFragment.newInstance(this@BlockedTimeAreasFragment).show(parentFragmentManager) } } BlockedTimeAreasLogic.init( - recycler = recycler, - daySpinner = spinner_day, - detailedModeCheckbox = detailed_mode, + recycler = binding.recycler, + daySpinner = binding.spinnerDay, + detailedModeCheckbox = binding.detailedMode, checkAuthentication = { if (auth.isParentAuthenticated()) { BlockedTimeAreasLogic.Authentication.FullyAvailable } else if (auth.isParentOrChildAuthenticated(childId = childId)) { BlockedTimeAreasLogic.Authentication.OnlyAllowAddingLimits( - showHintHook = { Snackbar.make(coordinator.parent as View, R.string.blocked_time_areas_snackbar_child_hint, Snackbar.LENGTH_LONG).show() }, + showHintHook = { Snackbar.make(binding.coordinator.parent as View, R.string.blocked_time_areas_snackbar_child_hint, Snackbar.LENGTH_LONG).show() }, showErrorHook = { auth.requestAuthentication() } ) } else { @@ -154,5 +151,7 @@ class BlockedTimeAreasFragment : Fragment(), CopyBlockedTimeAreasDialogFragmentL currentData = category.map { it?.blockedMinutesInWeek }, lifecycleOwner = this ) + + return binding.root } } diff --git a/app/src/main/java/io/timelimit/android/ui/manage/child/ManageChildFragment.kt b/app/src/main/java/io/timelimit/android/ui/manage/child/ManageChildFragment.kt index d6de291..5f8788f 100644 --- a/app/src/main/java/io/timelimit/android/ui/manage/child/ManageChildFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/manage/child/ManageChildFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -28,7 +28,6 @@ import io.timelimit.android.livedata.map import io.timelimit.android.ui.fragment.ChildFragmentWrapper import io.timelimit.android.ui.main.FragmentWithCustomTitle import io.timelimit.android.ui.manage.child.category.ManageChildCategoriesFragment -import kotlinx.android.synthetic.main.single_fragment_wrapper.* class ManageChildFragment : ChildFragmentWrapper(), FragmentWithCustomTitle { private val params: ManageChildFragmentArgs by lazy { ManageChildFragmentArgs.fromBundle(arguments!!) } @@ -46,7 +45,7 @@ class ManageChildFragment : ChildFragmentWrapper(), FragmentWithCustomTitle { super.onViewCreated(view, savedInstanceState) if (savedInstanceState == null && params.fromRedirect) { - Snackbar.make(coordinator, R.string.manage_child_redirected_toast, Snackbar.LENGTH_LONG).show() + Snackbar.make(binding.coordinator, R.string.manage_child_redirected_toast, Snackbar.LENGTH_LONG).show() } } diff --git a/app/src/main/java/io/timelimit/android/ui/manage/child/category/ManageChildCategoriesFragment.kt b/app/src/main/java/io/timelimit/android/ui/manage/child/category/ManageChildCategoriesFragment.kt index b7107bd..fe5f439 100644 --- a/app/src/main/java/io/timelimit/android/ui/manage/child/category/ManageChildCategoriesFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/manage/child/category/ManageChildCategoriesFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -30,6 +30,7 @@ import io.timelimit.android.R import io.timelimit.android.async.Threads import io.timelimit.android.data.model.Category import io.timelimit.android.data.model.HintsToShow +import io.timelimit.android.databinding.RecyclerFragmentBinding import io.timelimit.android.extensions.safeNavigate import io.timelimit.android.logic.AppLogic import io.timelimit.android.logic.DefaultAppLogic @@ -42,7 +43,6 @@ import io.timelimit.android.ui.manage.child.ManageChildFragmentArgs import io.timelimit.android.ui.manage.child.ManageChildFragmentDirections import io.timelimit.android.ui.manage.child.category.create.CreateCategoryDialogFragment import io.timelimit.android.ui.manage.child.category.specialmode.SetCategorySpecialModeFragment -import kotlinx.android.synthetic.main.recycler_fragment.* class ManageChildCategoriesFragment : Fragment() { companion object { @@ -55,9 +55,12 @@ class ManageChildCategoriesFragment : Fragment() { private val auth: ActivityViewModel by lazy { getActivityViewModel(requireActivity()) } private val logic: AppLogic by lazy { DefaultAppLogic.with(requireContext()) } private val model: ManageChildCategoriesModel by viewModels() + private lateinit var binding: RecyclerFragmentBinding override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.recycler_fragment, container, false) + binding = RecyclerFragmentBinding.inflate(inflater, container, false) + + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -134,8 +137,8 @@ class ManageChildCategoriesFragment : Fragment() { } } - recycler.adapter = adapter - recycler.layoutManager = LinearLayoutManager(context) + binding.recycler.adapter = adapter + binding.recycler.layoutManager = LinearLayoutManager(context) model.init(params.childId) model.listContent.observe(viewLifecycleOwner, Observer { adapter.categories = it }) @@ -199,6 +202,6 @@ class ManageChildCategoriesFragment : Fragment() { database.config().setHintsShownSync(HintsToShow.CATEGORIES_INTRODUCTION) } } - }).attachToRecyclerView(recycler) + }).attachToRecyclerView(binding.recycler) } } diff --git a/app/src/main/java/io/timelimit/android/ui/manage/child/tasks/ManageChildTasksFragment.kt b/app/src/main/java/io/timelimit/android/ui/manage/child/tasks/ManageChildTasksFragment.kt index e7ea8d0..c225fbe 100644 --- a/app/src/main/java/io/timelimit/android/ui/manage/child/tasks/ManageChildTasksFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/manage/child/tasks/ManageChildTasksFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -28,9 +28,9 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.Snackbar import io.timelimit.android.R import io.timelimit.android.data.model.ChildTask +import io.timelimit.android.databinding.RecyclerFragmentBinding import io.timelimit.android.sync.actions.UpdateChildTaskAction import io.timelimit.android.ui.main.getActivityViewModel -import kotlinx.android.synthetic.main.recycler_fragment.* class ManageChildTasksFragment: Fragment(), EditTaskDialogFragment.Listener { companion object { @@ -54,16 +54,11 @@ class ManageChildTasksFragment: Fragment(), EditTaskDialogFragment.Listener { } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.recycler_fragment, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - + val binding = RecyclerFragmentBinding.inflate(inflater, container, false) val adapter = ChildTaskAdapter() - recycler.layoutManager = LinearLayoutManager(requireContext()) - recycler.adapter = adapter + binding.recycler.layoutManager = LinearLayoutManager(requireContext()) + binding.recycler.adapter = adapter model.listContent.observe(viewLifecycleOwner) { adapter.data = it } model.isChildTheCurrentDeviceUser.observe(viewLifecycleOwner) {/* keep the value fresh */} @@ -100,7 +95,9 @@ class ManageChildTasksFragment: Fragment(), EditTaskDialogFragment.Listener { override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { model.hideIntro() } override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean = throw IllegalStateException() - }).attachToRecyclerView(recycler) + }).attachToRecyclerView(binding.recycler) + + return binding.root } override fun onTaskRemoved(task: ChildTask) { diff --git a/app/src/main/java/io/timelimit/android/ui/manipulation/AnnoyActivity.kt b/app/src/main/java/io/timelimit/android/ui/manipulation/AnnoyActivity.kt index 25f0d95..1aedd29 100644 --- a/app/src/main/java/io/timelimit/android/ui/manipulation/AnnoyActivity.kt +++ b/app/src/main/java/io/timelimit/android/ui/manipulation/AnnoyActivity.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -24,12 +24,12 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import io.timelimit.android.R +import io.timelimit.android.databinding.AnnoyActivityBinding import io.timelimit.android.livedata.map import io.timelimit.android.logic.DefaultAppLogic import io.timelimit.android.ui.manage.device.manage.ManipulationWarningTypeLabel import io.timelimit.android.ui.manage.device.manage.ManipulationWarnings import io.timelimit.android.util.TimeTextUtil -import kotlinx.android.synthetic.main.annoy_activity.* class AnnoyActivity : AppCompatActivity() { companion object { @@ -53,7 +53,8 @@ class AnnoyActivity : AppCompatActivity() { val model = ViewModelProviders.of(this).get(AnnoyModel::class.java) val logic = DefaultAppLogic.with(this) - setContentView(R.layout.annoy_activity) + val binding = AnnoyActivityBinding.inflate(layoutInflater) + setContentView(binding.root) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (logic.platformIntegration.setLockTaskPackages(listOf(packageName))) { @@ -67,7 +68,7 @@ class AnnoyActivity : AppCompatActivity() { shutdown() } - annoy_timer.setText( + binding.annoyTimer.setText( getString(R.string.annoy_timer, TimeTextUtil.seconds(it.toInt(), this@AnnoyActivity)) ) }) @@ -86,10 +87,10 @@ class AnnoyActivity : AppCompatActivity() { } }.observe(this, Observer { if (it.isNullOrEmpty()) { - annoy_reason.visibility = View.GONE + binding.annoyReason.visibility = View.GONE } else { - annoy_reason.visibility = View.VISIBLE - annoy_reason.setText(it) + binding.annoyReason.visibility = View.VISIBLE + binding.annoyReason.setText(it) } }) } diff --git a/app/src/main/java/io/timelimit/android/ui/manipulation/UnlockAfterManipulationActivity.kt b/app/src/main/java/io/timelimit/android/ui/manipulation/UnlockAfterManipulationActivity.kt index c8ba5aa..f8a3198 100644 --- a/app/src/main/java/io/timelimit/android/ui/manipulation/UnlockAfterManipulationActivity.kt +++ b/app/src/main/java/io/timelimit/android/ui/manipulation/UnlockAfterManipulationActivity.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -21,16 +21,15 @@ import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders -import io.timelimit.android.R import io.timelimit.android.async.Threads import io.timelimit.android.data.model.UserType +import io.timelimit.android.databinding.ActivityUnlockAfterManipulationBinding import io.timelimit.android.extensions.showSafe import io.timelimit.android.logic.DefaultAppLogic import io.timelimit.android.ui.backdoor.BackdoorDialogFragment import io.timelimit.android.ui.login.NewLoginFragment import io.timelimit.android.ui.main.ActivityViewModel import io.timelimit.android.ui.main.ActivityViewModelHolder -import kotlinx.android.synthetic.main.activity_unlock_after_manipulation.* class UnlockAfterManipulationActivity : AppCompatActivity(), ActivityViewModelHolder { private val model: ActivityViewModel by lazy { @@ -42,7 +41,9 @@ class UnlockAfterManipulationActivity : AppCompatActivity(), ActivityViewModelHo override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_unlock_after_manipulation) + + val binding = ActivityUnlockAfterManipulationBinding.inflate(layoutInflater) + setContentView(binding.root) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { startLockTask() @@ -74,8 +75,8 @@ class UnlockAfterManipulationActivity : AppCompatActivity(), ActivityViewModelHo } }) - auth_btn.setOnClickListener { showAuthenticationScreen() } - use_backdoor.setOnClickListener { BackdoorDialogFragment().show(supportFragmentManager) } + binding.authBtn.setOnClickListener { showAuthenticationScreen() } + binding.useBackdoor.setOnClickListener { BackdoorDialogFragment().show(supportFragmentManager) } } override fun showAuthenticationScreen() { diff --git a/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewFragment.kt b/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewFragment.kt index d198bd3..852a347 100644 --- a/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -23,10 +23,10 @@ import androidx.fragment.app.viewModels import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import io.timelimit.android.R import io.timelimit.android.async.Threads import io.timelimit.android.coroutines.CoroutineFragment import io.timelimit.android.data.model.* +import io.timelimit.android.databinding.FragmentOverviewBinding import io.timelimit.android.livedata.waitForNonNullValue import io.timelimit.android.logic.AppLogic import io.timelimit.android.logic.DefaultAppLogic @@ -34,7 +34,6 @@ import io.timelimit.android.sync.actions.ReviewChildTaskAction import io.timelimit.android.ui.main.ActivityViewModel import io.timelimit.android.ui.main.getActivityViewModel import io.timelimit.android.ui.payment.RequiresPurchaseDialogFragment -import kotlinx.android.synthetic.main.fragment_overview.* import kotlinx.coroutines.launch class OverviewFragment : CoroutineFragment() { @@ -44,16 +43,11 @@ class OverviewFragment : CoroutineFragment() { private val model: OverviewFragmentModel by viewModels() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_overview, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - + val binding = FragmentOverviewBinding.inflate(inflater, container, false) val adapter = OverviewFragmentAdapter() - recycler.adapter = adapter - recycler.layoutManager = LinearLayoutManager(requireContext()) + binding.recycler.adapter = adapter + binding.recycler.layoutManager = LinearLayoutManager(requireContext()) adapter.handlers = object: OverviewFragmentHandlers { override fun onAddUserClicked() { @@ -155,7 +149,9 @@ class OverviewFragment : CoroutineFragment() { } } } - ).attachToRecyclerView(recycler) + ).attachToRecyclerView(binding.recycler) + + return binding.root } } diff --git a/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewItemVisibility.kt b/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewItemVisibility.kt index f43889d..0f98f97 100644 --- a/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewItemVisibility.kt +++ b/app/src/main/java/io/timelimit/android/ui/overview/overview/OverviewItemVisibility.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -16,7 +16,7 @@ package io.timelimit.android.ui.overview.overview import android.os.Parcelable -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize @Parcelize data class OverviewItemVisibility( diff --git a/app/src/main/java/io/timelimit/android/ui/overview/uninstall/UninstallFragment.kt b/app/src/main/java/io/timelimit/android/ui/overview/uninstall/UninstallFragment.kt index 6f32803..1637e19 100644 --- a/app/src/main/java/io/timelimit/android/ui/overview/uninstall/UninstallFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/overview/uninstall/UninstallFragment.kt @@ -34,7 +34,6 @@ import io.timelimit.android.ui.main.ActivityViewModel import io.timelimit.android.ui.main.ActivityViewModelHolder import io.timelimit.android.ui.main.AuthenticationFab import io.timelimit.android.ui.main.FragmentWithCustomTitle -import kotlinx.android.synthetic.main.single_fragment_wrapper.* class UninstallFragment : Fragment(), FragmentWithCustomTitle { companion object { @@ -79,21 +78,17 @@ class UninstallFragment : Fragment(), FragmentWithCustomTitle { if (it == null) { navigation.popBackStack() } } - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - AuthenticationFab.manageAuthenticationFab( - fab = fab, + fab = binding.fab, fragment = this, shouldHighlight = activity.getActivityViewModel().shouldHighlightAuthenticationButton, authenticatedUser = activity.getActivityViewModel().authenticatedUser, doesSupportAuth = liveDataFromNonNullValue(!BuildConfig.storeCompilant) ) - fab.setOnClickListener { activity.showAuthenticationScreen() } + binding.fab.setOnClickListener { activity.showAuthenticationScreen() } + + return binding.root } override fun onSaveInstanceState(outState: Bundle) { diff --git a/app/src/main/java/io/timelimit/android/ui/parentmode/ParentModeFragment.kt b/app/src/main/java/io/timelimit/android/ui/parentmode/ParentModeFragment.kt index 7bac651..d743a8c 100644 --- a/app/src/main/java/io/timelimit/android/ui/parentmode/ParentModeFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/parentmode/ParentModeFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -22,16 +22,12 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import io.timelimit.android.R +import io.timelimit.android.databinding.ParentModeFragmentBinding import io.timelimit.android.ui.overview.about.AboutFragment -import kotlinx.android.synthetic.main.parent_mode_fragment.* class ParentModeFragment : Fragment() { - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.parent_mode_fragment, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val binding = ParentModeFragmentBinding.inflate(inflater, container, false) if (savedInstanceState == null) { childFragmentManager.beginTransaction() @@ -39,7 +35,7 @@ class ParentModeFragment : Fragment() { .commitNow() } - bottom_navigation_view.setOnNavigationItemSelectedListener { menuItem -> + binding.bottomNavigationView.setOnNavigationItemSelectedListener { menuItem -> if (childFragmentManager.isStateSaved) { false } else { @@ -56,5 +52,7 @@ class ParentModeFragment : Fragment() { true } } + + return binding.root } } \ No newline at end of file diff --git a/app/src/main/java/io/timelimit/android/ui/setup/SetupLocalModeFragment.kt b/app/src/main/java/io/timelimit/android/ui/setup/SetupLocalModeFragment.kt index 53c8c9a..cdf8f86 100644 --- a/app/src/main/java/io/timelimit/android/ui/setup/SetupLocalModeFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/setup/SetupLocalModeFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -38,7 +38,6 @@ import io.timelimit.android.logic.DefaultAppLogic import io.timelimit.android.ui.mustread.MustReadFragment import io.timelimit.android.ui.update.UpdateConsentCard import io.timelimit.android.update.UpdateUtil -import kotlinx.android.synthetic.main.fragment_setup_local_mode.* class SetupLocalModeFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -69,7 +68,7 @@ class SetupLocalModeFragment : Fragment() { binding.nextBtn.setOnClickListener { model.trySetupWithPassword( - set_password_view.readPassword(), + binding.setPasswordView.readPassword(), SetupNetworkTimeVerification.readSelection(binding.networkTimeVerification), enableUpdateChecks = binding.update.enableSwitch.isChecked ) diff --git a/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt b/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt index 082a5b5..c0694a7 100644 --- a/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 Jonas Lochmann + * TimeLimit Copyright 2019 - 2021 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 @@ -34,7 +34,6 @@ import io.timelimit.android.extensions.safeNavigate import io.timelimit.android.logic.DefaultAppLogic import io.timelimit.android.ui.setup.parentmode.SetupParentmodeDialogFragment import io.timelimit.android.ui.setup.privacy.PrivacyInfoDialogFragment -import kotlinx.android.synthetic.main.fragment_setup_select_mode.* class SetupSelectModeFragment : Fragment() { companion object { @@ -44,9 +43,10 @@ class SetupSelectModeFragment : Fragment() { } private lateinit var navigation: NavController + private lateinit var binding: FragmentSetupSelectModeBinding override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val binding = FragmentSetupSelectModeBinding.inflate(inflater, container, false) + binding = FragmentSetupSelectModeBinding.inflate(inflater, container, false) return binding.root } @@ -56,43 +56,43 @@ class SetupSelectModeFragment : Fragment() { navigation = Navigation.findNavController(view) - btn_local_mode.setOnClickListener { + binding.btnLocalMode.setOnClickListener { navigation.safeNavigate( SetupSelectModeFragmentDirections.actionSetupSelectModeFragmentToSetupDevicePermissionsFragment(), R.id.setupSelectModeFragment ) } - btn_parent_mode.setOnClickListener { + binding.btnParentMode.setOnClickListener { PrivacyInfoDialogFragment().apply { setTargetFragment(this@SetupSelectModeFragment, REQ_SETUP_CONNECTED_PARENT) - }.show(fragmentManager!!) + }.show(parentFragmentManager) } - btn_network_child_mode.setOnClickListener { + binding.btnNetworkChildMode.setOnClickListener { PrivacyInfoDialogFragment().apply { setTargetFragment(this@SetupSelectModeFragment, REQ_SETUP_CONNECTED_CHILD) - }.show(fragmentManager!!) + }.show(parentFragmentManager) } - btn_parent_key_mode.setOnClickListener { + binding.btnParentKeyMode.setOnClickListener { SetupParentmodeDialogFragment().apply { setTargetFragment(this@SetupSelectModeFragment, REQUEST_SETUP_PARENT_MODE) }.show(parentFragmentManager) } - btn_uninstall.setOnClickListener { - DefaultAppLogic.with(context!!).platformIntegration.disableDeviceAdmin() + binding.btnUninstall.setOnClickListener { + DefaultAppLogic.with(requireContext()).platformIntegration.disableDeviceAdmin() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { startActivity( - Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:${context!!.packageName}")) + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:${requireContext().packageName}")) .addCategory(Intent.CATEGORY_DEFAULT) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ) } else { startActivity( - Intent(Intent.ACTION_UNINSTALL_PACKAGE, Uri.parse("package:${context!!.packageName}")) + Intent(Intent.ACTION_UNINSTALL_PACKAGE, Uri.parse("package:${requireContext().packageName}")) ) } }