Commit 6596cfaa authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch '42-split-the-settings' into 'master'

Resolve "Split the settings"

Closes #42

See merge request PublicAndroidApps/smokescreen!37
parents 7ddd029d 2b9c6508
Pipeline #5094 passed with stage
in 1 minute and 57 seconds
......@@ -36,6 +36,13 @@
</activity>
<activity android:name=".activity.MainActivity">
</activity>
<activity
android:name=".activity.SettingsActivity"
android:label="@string/menu_settings"
android:theme="@style/AppTheme_Mono_ActionBar"
android:parentActivityName=".activity.MainActivity">
</activity>
<activity
android:name=".activity.ShortcutActivity"
......
......@@ -167,7 +167,7 @@ class MainActivity : NavigationDrawerActivity() {
)
fragmentItem(getString(R.string.menu_settings),
iconLeft = getDrawable(R.drawable.ic_menu_settings),
fragmentCreator = singleInstanceFragment { SettingsFragment() })
fragmentCreator = singleInstanceFragment { SettingsOverviewFragment() })
if (getPreferences().queryLoggingEnabled) {
divider()
fragmentItem(getString(R.string.menu_querylogging),
......
package com.frostnerd.smokescreen.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.frostnerd.lifecyclemanagement.BaseActivity
import com.frostnerd.smokescreen.fragment.SettingsFragment
import com.frostnerd.smokescreen.getPreferences
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
*
* 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 <http://www.gnu.org/licenses/>.
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
class SettingsActivity : BaseActivity() {
companion object {
fun showCategory(context: Context, category: Category) {
Intent(context, SettingsActivity::class.java).apply {
putExtra("category", category)
}.also {
context.startActivity(it)
}
}
}
override fun getConfiguration(): Configuration {
return Configuration.withDefaults()
}
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(getPreferences().theme.layoutStyleWithActionbar)
super.onCreate(savedInstanceState)
supportFragmentManager.beginTransaction().replace(android.R.id.content, SettingsFragment().apply {
arguments = Bundle().apply {
putSerializable("category", intent.getSerializableExtra("category"))
}
}).commit()
}
enum class Category {
GENERAL, NOTIFICATION, PIN, CACHE, LOGGING, IP, NETWORK, QUERIES
}
}
\ No newline at end of file
......@@ -19,6 +19,7 @@ import androidx.preference.PreferenceFragmentCompat
import com.frostnerd.general.isInt
import com.frostnerd.smokescreen.*
import com.frostnerd.smokescreen.activity.MainActivity
import com.frostnerd.smokescreen.activity.SettingsActivity
import com.frostnerd.smokescreen.database.getDatabase
import com.frostnerd.smokescreen.dialog.AppChoosalDialog
import com.frostnerd.smokescreen.dialog.CrashReportingEnableDialog
......@@ -51,10 +52,23 @@ class SettingsFragment : PreferenceFragmentCompat() {
SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
context?.getPreferences()?.notifyPreferenceChangedFromExternal(key)
}
private val category:SettingsActivity.Category by lazy {
arguments!!.getSerializable("category") as SettingsActivity.Category
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
log("Adding preferences from resources...")
setPreferencesFromResource(R.xml.preferences, rootKey)
val resource = when(category) {
SettingsActivity.Category.GENERAL -> R.xml.preferences_general
SettingsActivity.Category.NOTIFICATION -> R.xml.preferences_notification
SettingsActivity.Category.PIN -> R.xml.preferences_pin
SettingsActivity.Category.CACHE -> R.xml.preferences_cache
SettingsActivity.Category.LOGGING -> R.xml.preferences_logging
SettingsActivity.Category.IP -> R.xml.preferences_ip
SettingsActivity.Category.NETWORK -> R.xml.preferences_network
SettingsActivity.Category.QUERIES -> R.xml.preferences_queries
}
setPreferencesFromResource(resource, rootKey)
log("Preferences added.")
werePreferencesAdded = true
createPreferenceListener()
......@@ -101,44 +115,24 @@ class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
log("Fragment created")
findPreference("theme").setOnPreferenceChangeListener { _, newValue ->
val id = (newValue as? String)?.toInt() ?: newValue as Int
val newTheme = Theme.findById(id)
log("Updated theme to $newValue")
if (newTheme != null) {
removePreferenceListener()
requireContext().getPreferences().theme = newTheme
requireActivity().restart()
true
} else {
false
}
}
findPreference("app_exclusion_list").setOnPreferenceClickListener {
showExcludedAppsDialog()
true
}
findPreference("send_logs").setOnPreferenceClickListener {
requireContext().showLogExportDialog()
true
}
findPreference("delete_logs").setOnPreferenceClickListener {
showLogDeletionDialog()
true
when(category) {
SettingsActivity.Category.GENERAL -> processGeneralCategory()
SettingsActivity.Category.NOTIFICATION -> processNotificationCategory()
SettingsActivity.Category.PIN -> processPinCategory()
SettingsActivity.Category.CACHE -> processCacheCategory()
SettingsActivity.Category.LOGGING -> processLoggingCategory()
SettingsActivity.Category.IP -> processIPCategory()
SettingsActivity.Category.NETWORK -> processNetworkCategory()
SettingsActivity.Category.QUERIES -> processQueryCategory()
}
}
private fun processNotificationCategory() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val hideIconPreference = findPreference("hide_notification_icon")
hideIconPreference.isEnabled = false
hideIconPreference.isVisible = false
}
processGeneralCategory()
processCacheCategory()
processLoggingCategory()
processIPCategory()
processNetworkCategory()
processQueryCategory()
processPinCategory()
}
private fun processPinCategory() {
......@@ -250,6 +244,24 @@ class SettingsFragment : PreferenceFragmentCompat() {
} else true
}
}
findPreference("theme").setOnPreferenceChangeListener { _, newValue ->
val id = (newValue as? String)?.toInt() ?: newValue as Int
val newTheme = Theme.findById(id)
log("Updated theme to $newValue")
if (newTheme != null) {
removePreferenceListener()
requireContext().getPreferences().theme = newTheme
requireActivity().restart()
true
} else {
false
}
}
findPreference("app_exclusion_list").setOnPreferenceClickListener {
showExcludedAppsDialog()
true
}
}
private fun processIPCategory() {
......@@ -391,6 +403,14 @@ class SettingsFragment : PreferenceFragmentCompat() {
}
true
}
findPreference("send_logs").setOnPreferenceClickListener {
requireContext().showLogExportDialog()
true
}
findPreference("delete_logs").setOnPreferenceClickListener {
showLogDeletionDialog()
true
}
}
private fun showLogDeletionDialog() {
......
package com.frostnerd.smokescreen.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.activity.SettingsActivity
import kotlinx.android.synthetic.main.fragment_settings_overview.*
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
*
* 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 <http://www.gnu.org/licenses/>.
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
class SettingsOverviewFragment: Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_settings_overview, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
general.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.GENERAL)
}
notification.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.NOTIFICATION)
}
pin.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.PIN)
}
cache.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.CACHE)
}
logging.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.LOGGING)
}
ip.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.IP)
}
network.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.NETWORK)
}
queryLogging.setOnClickListener {
SettingsActivity.showCategory(context!!, SettingsActivity.Category.QUERIES)
}
}
}
\ No newline at end of file
......@@ -33,11 +33,15 @@ import kotlin.reflect.KProperty
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
enum class Theme(val id: Int, @StyleRes val layoutStyle: Int, @StyleRes val dialogStyle: Int, @StyleRes val preferenceStyle: Int) {
MONO(1, R.style.AppTheme_Mono, R.style.DialogTheme_Mono, R.style.PreferenceTheme_Mono),
DARK(2, R.style.AppTheme_Dark, R.style.DialogTheme_Dark, R.style.PreferenceTheme_Dark),
TRUE_BLACK(3, R.style.AppTheme_True_Black, R.style.DialogTheme_True_Black, R.style.PreferenceTheme_True_Black),
BLUE(4, R.style.AppTheme_Blue, R.style.DialogTheme_Blue, R.style.PreferenceTheme_Blue);
enum class Theme(val id: Int,
@StyleRes val layoutStyle: Int,
@StyleRes val dialogStyle: Int,
@StyleRes val preferenceStyle: Int,
@StyleRes val layoutStyleWithActionbar:Int) {
MONO(1, R.style.AppTheme_Mono, R.style.DialogTheme_Mono, R.style.PreferenceTheme_Mono, R.style.AppTheme_Mono_ActionBar),
DARK(2, R.style.AppTheme_Dark, R.style.DialogTheme_Dark, R.style.PreferenceTheme_Dark, R.style.AppTheme_Dark_ActionBar),
TRUE_BLACK(3, R.style.AppTheme_True_Black, R.style.DialogTheme_True_Black, R.style.PreferenceTheme_True_Black, R.style.AppTheme_True_Black_ActionBar),
BLUE(4, R.style.AppTheme_Blue, R.style.DialogTheme_Blue, R.style.PreferenceTheme_Blue, R.style.AppTheme_Blue_ActionBar);
@ColorInt
fun getColor(context: Context, @AttrRes attribute: Int, @ColorInt defaultValue: Int = Color.BLACK): Int {
......
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/general"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerVertical="true"
android:text="@string/preference_category_general"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/notification"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerVertical="true"
android:text="@string/preference_category_notification"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/pin"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:layout_centerVertical="true"
android:textStyle="bold"
android:text="@string/preference_category_pin"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/cache"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerVertical="true"
android:text="@string/preference_category_cache"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/logging"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:layout_centerVertical="true"
android:textStyle="bold"
android:text="@string/preference_category_logging"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/ip"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerVertical="true"
android:text="@string/preference_category_ip"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/network"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerVertical="true"
android:text="@string/preference_category_network"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:id="@+id/queryLogging"
android:textStyle="bold"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:text="@string/preference_category_querylogging"
android:layout_centerVertical="true"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="32dp"
android:src="@drawable/ic_chevron_right"
android:tint="?android:attr/textColor"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_height="32dp"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>
\ No newline at end of file
......@@ -29,6 +29,11 @@
<item name="android:navigationBarColor">?android:attr/statusBarColor</item>
</style>
<style name="AppTheme_Blue_ActionBar" parent="AppTheme_Blue">
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
</style>
<style name="AppTheme_Dark" parent="Theme.AppCompat.DayNight.DarkActionBar">
<item name="colorPrimary">#424242</item>
<item name="colorPrimaryDark">#212121</item>
......@@ -57,6 +62,11 @@
<item name="android:navigationBarColor">?android:attr/statusBarColor</item>
</style>
<style name="AppTheme_Dark_ActionBar" parent="AppTheme_Dark">
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
</style>
<style name="AppTheme_Mono" parent="Theme.AppCompat.DayNight.DarkActionBar">
<item name="colorPrimary">#607D8B</item>
<item name="colorPrimaryDark">#37474F</item>
......@@ -85,6 +95,11 @@
<item name="android:navigationBarColor">?android:attr/statusBarColor</item>
</style>
<style name="AppTheme_Mono_ActionBar" parent="AppTheme_Mono">
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
</style>
<style name="DrawerArrowStyle" parent="@style/Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">?android:attr/textColor</item>
......@@ -117,6 +132,10 @@
<item name="android:statusBarColor">?attr/colorPrimary</item>
<item name="android:navigationBarColor">?android:attr/statusBarColor</item>
</style>
<style name="AppTheme_True_Black_ActionBar" parent="AppTheme_True_Black">
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
</style>
<style name="DialogTheme_Blue" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorPrimary">@color/colorPrimary</item>
......
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/preference_category_general">
<ListPreference
android:defaultValue="1"
android:entries="@array/theme"
android:entryValues="@array/themeValues"
android:key="theme"
android:summary="@string/summary_theme"
android:title="@string/title_theme"/>
<CheckBoxPreference
android:defaultValue="true"
android:summary="@string/summary_start_on_boot"
android:title="@string/title_start_on_boot"
android:key="start_on_boot"/>
<CheckBoxPreference
android:key="start_after_update"
android:title="@string/title_start_after_update"
android:summary="@string/summary_start_after_update"
android:defaultValue="true"/>
<Preference
android:key="app_exclusion_list"
android:title="@string/title_excluded_apps"
android:summary="@string/summary_excluded_apps"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/preference_category_notification">
<CheckBoxPreference
android:key="show_notification_on_lockscreen"
android:title="@string/title_show_notification_on_lockscreen"
android:defaultValue="true"
android:summary="@string/summary_show_notification_on_lockscreen"/>
<CheckBoxPreference
android:key="hide_notification_icon"
android:title="@string/title_notification_hide_icon"
android:summary="@string/summary_notification_hide_icon"
android:defaultValue="false"
/>
<CheckBoxPreference
android:key="notification_allow_stop"
android:title="@string/title_notification_allow_stop"
android:summary="@string/summary_notification_allow_stop"
android:defaultValue="true"/>
<CheckBoxPreference
android:key="notification_allow_pause"
android:title="@string/title_notification_allow_pause"
android:summary="@string/summary_notification_allow_pause"
android:defaultValue="true"/>
</PreferenceCategory>