diff options
author | Amit Kumar <amitkma@e.email> | 2021-05-03 03:17:11 +0530 |
---|---|---|
committer | Amit Kumar <amitkma@e.email> | 2021-05-03 03:17:11 +0530 |
commit | 0d036a8742f54eb9ea87e64fdce9ab878f58859b (patch) | |
tree | 2ee2ddab1e61f2d436ce1d4401cbe1b032282e37 /app/src/main/java | |
parent | 75843f012b09f0f11da4aec10be2f378465a94c2 (diff) |
Connect multiple features
Diffstat (limited to 'app/src/main/java')
15 files changed, 764 insertions, 68 deletions
diff --git a/app/src/main/java/foundation/e/privacycentralapp/common/RightRadioButton.kt b/app/src/main/java/foundation/e/privacycentralapp/common/RightRadioButton.kt new file mode 100644 index 0000000..bbc108b --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/common/RightRadioButton.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.common + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.widget.RadioButton + +/** + * A custom [RadioButton] which displays the radio drawable on the right side. + */ +@SuppressLint("AppCompatCustomView") +class RightRadioButton : RadioButton { + + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + + // Returns layout direction as right-to-left to draw the compound button on right side. + override fun getLayoutDirection(): Int { + return LAYOUT_DIRECTION_RTL + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt b/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt new file mode 100644 index 0000000..65d072a --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.dummy + +import foundation.e.privacycentralapp.R + +// ======================================================// +// +// ============ ==== ==== ============ +// ============ ===== ===== ==== ==== +// ==== ====== ====== ==== ==== +// ==== ======= ======= ============ +// ==== ================ ==== +// ==== ==== ====== ==== ==== +// ============ ==== ==== ==== ==== +// ============ ==== == ==== ==== +// +// ======================================================// + +/** + * This whole file acts as a dummy source. All data classes and method implementations + * are not proper ones and are subject to change anytime. + */ + +/** + * Dummmy permission data class. + */ +data class Permission( + val name: String, + val iconId: Int, + val packagesRequested: List<String> = emptyList(), + val packagesAllowed: List<String> = emptyList() +) + +object DummyDataSource { + val permissions = arrayOf("Body Sensor", "Calendar", "Call Logs", "Location") + val icons = arrayOf( + R.drawable.ic_body_monitor, + R.drawable.ic_calendar, + R.drawable.ic_call, + R.drawable.ic_location + ) + + val packages = arrayOf( + "facebook", + "uber", + "instagram", + "openstreetmap", + "truecaller", + "netflix", + "firefox", + "pubg", + "amazon", + "calendar", + "zohomail", + "privacycentral" + ) + + val populatedPermission: List<Permission> by lazy { + fetchPermissions() + } + + private fun fetchPermissions(): List<Permission> { + val result = mutableListOf<Permission>() + permissions.forEachIndexed { index, permission -> + when (index) { + 0 -> result.add(Permission(permission, icons[index])) + 1 -> { + val randomPackages = getRandomItems(packages, 8) + val grantedPackages = getRandomItems(randomPackages, 3) + result.add( + Permission( + permission, + icons[index], + randomPackages, + grantedPackages + ) + ) + } + 2 -> { + val randomPackages = getRandomItems(packages, 10) + val grantedPackages = getRandomItems(randomPackages, 9) + result.add( + Permission( + permission, + icons[index], + randomPackages, + grantedPackages + ) + ) + } + 3 -> { + val randomPackages = getRandomItems(packages, 5) + val grantedPackages = getRandomItems(randomPackages, 3) + result.add( + Permission( + permission, + icons[index], + randomPackages, + grantedPackages + ) + ) + } + } + } + return result + } + + private fun <T> getRandomItems(data: Array<T>, limit: Int): List<T> = + getRandomItems(data.asList(), limit) + + private fun <T> getRandomItems(data: List<T>, limit: Int): List<T> { + val randomItems = mutableSetOf<T>() + val localData = data.toMutableList() + repeat(limit) { + val generated = localData.random() + randomItems.add(generated) + localData.remove(generated) + } + return randomItems.toList() + } + + fun getPermission(permissionId: Int): Permission { + return populatedPermission.get(permissionId) + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardActivity.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardActivity.kt deleted file mode 100644 index ef296ce..0000000 --- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardActivity.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2021 E FOUNDATION - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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 foundation.e.privacycentralapp.features.dashboard - -import android.graphics.Color -import android.os.Bundle -import android.text.Spannable -import android.text.SpannableString -import android.text.style.ForegroundColorSpan -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import foundation.e.privacycentralapp.R - -class DashboardActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - title = "My Privacy Dashboard" - setSupportActionBar(findViewById(R.id.toolbar)) - - addClickToMore(findViewById<TextView>(R.id.personal_leakag_info)) - } - - private fun addClickToMore(textView: TextView) { - val clickToMore = SpannableString("Click to learn more") - clickToMore.setSpan( - ForegroundColorSpan(Color.parseColor("#007fff")), - 0, - clickToMore.length, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE - ) - textView.append(clickToMore) - } -} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt index 9b8e28f..ecadea1 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt @@ -23,47 +23,51 @@ import foundation.e.flowmvi.feature.BaseFeature import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flowOf -// Define a state machine for HomeFeature -object HomeFeature { +// Define a state machine for Dashboard Feature +object DashboardFeature { sealed class State { - object Loading : State() - object Loaded : State() + object DashboardState : State() + object QuickProtectionState : State() } sealed class SingleEvent { - object NavigateToQuickProtection : SingleEvent() - object NavigateToTrackers : SingleEvent() - object NavigateToInternetActivityPolicy : SingleEvent() - object NavigateToLocation : SingleEvent() - object NavigateToPermissionManagement : SingleEvent() + object NavigateToQuickProtectionSingleEvent : SingleEvent() + object NavigateToTrackersSingleEvent : SingleEvent() + object NavigateToInternetActivityPolicySingleEvent : SingleEvent() + object NavigateToLocationSingleEvent : SingleEvent() + object NavigateToPermissionManagementSingleEvent : SingleEvent() } sealed class Action { - object load : Action() + object ShowQuickPrivacyProtectionInfoAction : Action() + object ShowDashboardAction : Action() } sealed class Effect { - object LoadingFinished : Effect() + object OpenQuickPrivacyProtectionEffect : Effect() + object OpenDashboardEffect : Effect() } } -private val reducer: Reducer<HomeFeature.State, HomeFeature.Effect> = { _, effect -> +private val reducer: Reducer<DashboardFeature.State, DashboardFeature.Effect> = { _, effect -> when (effect) { - HomeFeature.Effect.LoadingFinished -> HomeFeature.State.Loaded + DashboardFeature.Effect.OpenQuickPrivacyProtectionEffect -> DashboardFeature.State.QuickProtectionState + DashboardFeature.Effect.OpenDashboardEffect -> DashboardFeature.State.DashboardState } } -private val actor: Actor<HomeFeature.State, HomeFeature.Action, HomeFeature.Effect> = +private val actor: Actor<DashboardFeature.State, DashboardFeature.Action, DashboardFeature.Effect> = { _, action -> when (action) { - HomeFeature.Action.load -> flowOf(HomeFeature.Effect.LoadingFinished) + DashboardFeature.Action.ShowQuickPrivacyProtectionInfoAction -> flowOf(DashboardFeature.Effect.OpenQuickPrivacyProtectionEffect) + DashboardFeature.Action.ShowDashboardAction -> flowOf(DashboardFeature.Effect.OpenDashboardEffect) } } fun homeFeature( - initialState: HomeFeature.State = HomeFeature.State.Loading, + initialState: DashboardFeature.State = DashboardFeature.State.DashboardState, coroutineScope: CoroutineScope -) = BaseFeature<HomeFeature.State, HomeFeature.Action, HomeFeature.Effect, HomeFeature.SingleEvent>( +) = BaseFeature<DashboardFeature.State, DashboardFeature.Action, DashboardFeature.Effect, DashboardFeature.SingleEvent>( initialState, actor, reducer, diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt new file mode 100644 index 0000000..d6a91b8 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.dashboard + +import android.graphics.Color +import android.os.Bundle +import android.text.Spannable +import android.text.SpannableString +import android.text.style.ForegroundColorSpan +import android.view.View +import android.widget.TextView +import android.widget.Toolbar +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.fragment.app.add +import androidx.fragment.app.commit +import androidx.lifecycle.lifecycleScope +import foundation.e.flowmvi.MVIView +import foundation.e.privacycentralapp.R +import kotlinx.coroutines.flow.Flow + +class DashboardFragment : + Fragment(R.layout.fragment_dashboard), + MVIView<DashboardFeature.State, DashboardFeature.Action> { + + private val viewModel: DashboardViewModel by activityViewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + lifecycleScope.launchWhenStarted { + viewModel.homeFeature.takeView(this, this@DashboardFragment) + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val toolbar = view.findViewById<Toolbar>(R.id.toolbar) + setupToolbar(toolbar) + addClickToMore(view.findViewById(R.id.personal_leakag_info)) + view.let { + it.findViewById<TextView>(R.id.tap_to_enable_quick_protection).setOnClickListener { + viewModel.submitAction(DashboardFeature.Action.ShowQuickPrivacyProtectionInfoAction) + } + } + } + + private fun setupToolbar(toolbar: Toolbar) { + val activity = requireActivity() + activity.setActionBar(toolbar) + activity.title = "My Privacy Dashboard" + } + + private fun addClickToMore(textView: TextView) { + val clickToMore = SpannableString("Click to learn more") + clickToMore.setSpan( + ForegroundColorSpan(Color.parseColor("#007fff")), + 0, + clickToMore.length, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + textView.append(clickToMore) + } + + override fun render(state: DashboardFeature.State) { + when (state) { + is DashboardFeature.State.QuickProtectionState -> { + requireActivity().supportFragmentManager.commit { + add<QuickProtectionFragment>(R.id.container) + setReorderingAllowed(true) + addToBackStack("dashboard") + } + } + else -> { + // TODO: any remaining state must either be handled or needs to be passed down to the UI. + } + } + } + + override fun actions(): Flow<DashboardFeature.Action> = viewModel.actions +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt index 82c6c11..12696d5 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt @@ -20,11 +20,23 @@ package foundation.e.privacycentralapp.features.dashboard import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import foundation.e.flowmvi.feature.BaseFeature +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.launch class DashboardViewModel : ViewModel() { - val homeFeature: BaseFeature<HomeFeature.State, HomeFeature.Action, - HomeFeature.Effect, HomeFeature.SingleEvent> by lazy { + private val _actions = MutableSharedFlow<DashboardFeature.Action>() + val actions = _actions.asSharedFlow() + + val homeFeature: BaseFeature<DashboardFeature.State, DashboardFeature.Action, + DashboardFeature.Effect, DashboardFeature.SingleEvent> by lazy { homeFeature(coroutineScope = viewModelScope) } + + fun submitAction(action: DashboardFeature.Action) { + viewModelScope.launch { + _actions.emit(action) + } + } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt new file mode 100644 index 0000000..c120b49 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.dashboard + +import android.content.Context +import android.os.Bundle +import android.view.View +import android.widget.Toolbar +import androidx.activity.addCallback +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import foundation.e.privacycentralapp.R + +class QuickProtectionFragment : Fragment(R.layout.fragment_quick_protection) { + + private val viewModel: DashboardViewModel by activityViewModels() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val toolbar = view.findViewById<Toolbar>(R.id.toolbar) + setupToolbar(toolbar) + } + + override fun onAttach(context: Context) { + super.onAttach(context) + requireActivity().onBackPressedDispatcher.addCallback(this, true) { + viewModel.submitAction(DashboardFeature.Action.ShowDashboardAction) + this.isEnabled = false + requireActivity().onBackPressed() + } + } + + private fun setupToolbar(toolbar: Toolbar) { + val activity = requireActivity() + activity.setActionBar(toolbar) + activity.title = "Quick protection" + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt new file mode 100644 index 0000000..ddba807 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.internetprivacy + +import android.os.Bundle +import android.view.View +import android.widget.Toolbar +import androidx.fragment.app.Fragment +import foundation.e.privacycentralapp.R + +class InternetPrivacyFragment : Fragment(R.layout.fragment_internet_activity_policy) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val toolbar = view.findViewById<Toolbar>(R.id.toolbar) + setupToolbar(toolbar) + } + + private fun setupToolbar(toolbar: Toolbar) { + val activity = requireActivity() + activity.setActionBar(toolbar) + activity.title = "My Internet Activity Privacy" + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeMyLocationFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeMyLocationFragment.kt new file mode 100644 index 0000000..24d3951 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeMyLocationFragment.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.location + +import android.os.Bundle +import android.view.View +import android.widget.Toolbar +import androidx.fragment.app.Fragment +import foundation.e.privacycentralapp.R + +class FakeMyLocationFragment : Fragment(R.layout.fragment_fake_location) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val toolbar = view.findViewById<Toolbar>(R.id.toolbar) + setupToolbar(toolbar) + } + + private fun setupToolbar(toolbar: Toolbar) { + val activity = requireActivity() + activity.setActionBar(toolbar) + activity.title = "Fake My Location" + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionAppsAdapter.kt b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionAppsAdapter.kt new file mode 100644 index 0000000..19460cc --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionAppsAdapter.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.permissions + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.Switch +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import foundation.e.privacycentralapp.R + +class PermissionAppsAdapter(private val dataSet: List<Pair<String, Boolean>>) : + RecyclerView.Adapter<PermissionAppsAdapter.PermissionViewHolder>() { + + class PermissionViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val appName: TextView = view.findViewById(R.id.app_title) + @SuppressLint("UseSwitchCompatOrMaterialCode") val togglePermission: Switch = view.findViewById(R.id.togglePermission) + val appIcon: ImageView = view.findViewById(R.id.app_icon) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PermissionViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_permission_apps, parent, false) + return PermissionViewHolder(view) + } + + override fun onBindViewHolder(holder: PermissionViewHolder, position: Int) { + val permission = dataSet[position] + holder.appName.text = permission.first + holder.togglePermission.isChecked = permission.second + } + + override fun getItemCount(): Int = dataSet.size +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionControlFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionControlFragment.kt new file mode 100644 index 0000000..55e3f88 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionControlFragment.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.permissions + +import android.os.Bundle +import android.view.View +import android.widget.TextView +import android.widget.Toolbar +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import foundation.e.privacycentralapp.R +import foundation.e.privacycentralapp.dummy.DummyDataSource + +class PermissionControlFragment : Fragment(R.layout.fragment_permission_control) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val toolbar = view.findViewById<Toolbar>(R.id.toolbar) + setupToolbar(toolbar) + + val permissionId = requireArguments().getInt("PERMISSION_ID") + loadData(view, permissionId) + } + + private fun loadData(view: View, permissionId: Int) { + val recyclerView = view.findViewById<RecyclerView>(R.id.recylcer_view_permission_apps) + val permission = DummyDataSource.getPermission(permissionId) + val listOfPackages = mutableListOf<Pair<String, Boolean>>() + permission.packagesRequested.forEach { + listOfPackages.add(it to permission.packagesAllowed.contains(it)) + } + recyclerView.layoutManager = LinearLayoutManager(requireContext()) + recyclerView.setHasFixedSize(true) + recyclerView.adapter = PermissionAppsAdapter(listOfPackages) + view.findViewById<TextView>(R.id.permission_control).text = + getString(R.string.apps_access_to_permission, permission.name) + } + + private fun setupToolbar(toolbar: Toolbar) { + val activity = requireActivity() + activity.setActionBar(toolbar) + activity.title = "My Apps Permission" + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionsAdapter.kt b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionsAdapter.kt new file mode 100644 index 0000000..330a1ac --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionsAdapter.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.permissions + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import foundation.e.privacycentralapp.R +import foundation.e.privacycentralapp.dummy.Permission + +class PermissionsAdapter( + private val context: Context, + private val dataSet: List<Permission>, + private val listener: (Int) -> Unit +) : + RecyclerView.Adapter<PermissionsAdapter.PermissionViewHolder>() { + + class PermissionViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val nameView: TextView = view.findViewById(R.id.permission_title) + val permissionCountView: TextView = view.findViewById(R.id.permission_count) + val permissionIcon: ImageView = view.findViewById(R.id.permission_icon) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PermissionViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_permission, parent, false) + val holder = PermissionViewHolder(view) + view.setOnClickListener { listener(holder.adapterPosition) } + return holder + } + + override fun onBindViewHolder(holder: PermissionViewHolder, position: Int) { + val permission = dataSet[position] + holder.nameView.text = permission.name + holder.permissionCountView.text = context.getString( + R.string.apps_allowed, + permission.packagesAllowed.size, + permission.packagesRequested.size + ) + holder.permissionIcon.setImageResource(permission.iconId) + } + + override fun getItemCount(): Int = dataSet.size +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionsFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionsFragment.kt new file mode 100644 index 0000000..27247ea --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/permissions/PermissionsFragment.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.features.permissions + +import android.os.Bundle +import android.view.View +import android.widget.Toolbar +import androidx.core.os.bundleOf +import androidx.fragment.app.Fragment +import androidx.fragment.app.add +import androidx.fragment.app.commit +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import foundation.e.privacycentralapp.R +import foundation.e.privacycentralapp.dummy.DummyDataSource + +class PermissionsFragment : Fragment(R.layout.fragment_permissions) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val toolbar = view.findViewById<Toolbar>(R.id.toolbar) + setupToolbar(toolbar) + + loadDataIntoRecyclerView(view.findViewById(R.id.recylcer_view_permissions)) + } + + private fun loadDataIntoRecyclerView(view: RecyclerView) { + val permissions = DummyDataSource.populatedPermission + view.layoutManager = LinearLayoutManager(requireContext()) + view.setHasFixedSize(true) + view.adapter = PermissionsAdapter(requireContext(), permissions) { permissionId -> + requireActivity().supportFragmentManager.commit { + val bundle = bundleOf("PERMISSION_ID" to permissionId) + add<PermissionControlFragment>(R.id.container, args = bundle) + setReorderingAllowed(true) + addToBackStack("permissions") + } + } + } + + private fun setupToolbar(toolbar: Toolbar) { + val activity = requireActivity() + activity.setActionBar(toolbar) + activity.title = "My Apps Permission" + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt b/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt new file mode 100644 index 0000000..d5b449f --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.main + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.activity.viewModels +import androidx.fragment.app.FragmentActivity +import androidx.fragment.app.add +import androidx.fragment.app.commit +import foundation.e.privacycentralapp.R +import foundation.e.privacycentralapp.features.permissions.PermissionsFragment + +open class MainActivity : FragmentActivity(R.layout.activity_main) { + + private val viewModel: MainViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (savedInstanceState == null) { + supportFragmentManager.commit { + setReorderingAllowed(true) + add<PermissionsFragment>(R.id.container) + } + } + } + + override fun onPostCreate(savedInstanceState: Bundle?) { + super.onPostCreate(savedInstanceState) + handleIntent(intent) + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + handleIntent(intent) + } + + open fun handleIntent(intent: Intent) {} + + override fun finishAfterTransition() { + val resultData = Intent() + val result = onPopulateResultIntent(resultData) + setResult(result, resultData) + + super.finishAfterTransition() + } + + open fun onPopulateResultIntent(intent: Intent): Int = Activity.RESULT_OK +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/main/MainViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/main/MainViewModel.kt new file mode 100644 index 0000000..7e758b7 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/main/MainViewModel.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 foundation.e.privacycentralapp.main + +import androidx.lifecycle.ViewModel + +class MainViewModel : ViewModel() |