diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ae4138c..d420b88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -187,7 +187,7 @@
android:exported="false"
android:label="@string/dashboard" />
sc = service -> updateUi();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_focusmode);
- setSupportActionBar(findViewById(R.id.topbar));
- ActionBar actionBar = getSupportActionBar();
- assert actionBar != null;
- actionBar.setDisplayHomeAsUpEnabled(true);
- LayoutTransition layoutTransition = ((LinearLayoutCompat) findViewById(R.id.focusModeRoot)).getLayoutTransition();
- layoutTransition.enableTransitionType(LayoutTransition.CHANGING);
-
- findViewById(R.id.schedule).setOnClickListener(v ->
- startActivity(new Intent(this, ScheduleActivity.class).putExtra("type", "focus_mode").putExtra("name", getString(R.string.focus_mode))));
-
- WellbeingService tw = WellbeingService.get();
- tw.addStateCallback(sc);
-
- RecyclerView r = findViewById(R.id.focusModePkgs);
- r.setAdapter(
- new PackageRecyclerViewAdapter(this,
- tw.getInstalledApplications(PackageManager.GET_META_DATA),
- "focus_mode", tw::onFocusModePreferenceChanged));
-
- updateUi();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- WellbeingService tw = WellbeingService.get();
- tw.removeStateCallback(sc);
- }
-
- private void updateUi() {
- WellbeingService tw = WellbeingService.get();
- State state = tw.getState();
- MaterialSwitch toggle = findViewById(R.id.topsw);
- toggle.setChecked(state.isFocusModeEnabled());
- findViewById(R.id.topsc).setOnClickListener(v -> {
- if (state.isFocusModeEnabled()) {
- tw.disableFocusMode();
- } else {
- tw.enableFocusMode();
- }
- });
- View takeBreak = findViewById(R.id.takeBreak);
- ((AppCompatTextView) findViewById(R.id.title)).setText(state.isOnFocusModeBreakGlobal() ? R.string.focus_mode_break_end : R.string.focus_mode_break);
- takeBreak.setOnClickListener(v -> {
- if (state.isOnFocusModeBreakGlobal()) {
- tw.endFocusModeBreak();
- } else {
- tw.takeFocusModeBreakWithDialog(FocusModeActivity.this, false, null);
- }
- });
- takeBreak.setVisibility(state.isFocusModeEnabled() ? View.VISIBLE : View.GONE);
- }
-
- @Override
- public boolean onSupportNavigateUp() {
- finish();
- return true;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/eu/droid_ng/wellbeing/prefs/PackageRecyclerViewAdapter.java b/app/src/main/java/org/eu/droid_ng/wellbeing/prefs/PackageRecyclerViewAdapter.java
index 341e396..e4ef87d 100644
--- a/app/src/main/java/org/eu/droid_ng/wellbeing/prefs/PackageRecyclerViewAdapter.java
+++ b/app/src/main/java/org/eu/droid_ng/wellbeing/prefs/PackageRecyclerViewAdapter.java
@@ -32,7 +32,7 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
-class PackageRecyclerViewAdapter extends RecyclerView.Adapter {
+public class PackageRecyclerViewAdapter extends RecyclerView.Adapter {
private final Context mContext;
private final LayoutInflater inflater;
private final List mData;
diff --git a/app/src/main/java/org/eu/droid_ng/wellbeing/ui/FocusModeActivity.kt b/app/src/main/java/org/eu/droid_ng/wellbeing/ui/FocusModeActivity.kt
new file mode 100644
index 0000000..7481c8f
--- /dev/null
+++ b/app/src/main/java/org/eu/droid_ng/wellbeing/ui/FocusModeActivity.kt
@@ -0,0 +1,101 @@
+package org.eu.droid_ng.wellbeing.ui
+
+import android.animation.LayoutTransition
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.LinearLayoutCompat
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.appbar.MaterialToolbar
+import com.google.android.material.textview.MaterialTextView
+import org.eu.droid_ng.wellbeing.R
+import org.eu.droid_ng.wellbeing.lib.WellbeingService
+import org.eu.droid_ng.wellbeing.prefs.PackageRecyclerViewAdapter
+import org.eu.droid_ng.wellbeing.prefs.ScheduleActivity
+import org.eu.droid_ng.wellbeing.widget.MainSwitchBar
+import java.util.function.Consumer
+
+class FocusModeActivity : AppCompatActivity() {
+
+ private val service: WellbeingService by lazy {
+ WellbeingService.get()
+ }
+
+ private val stateCallback = Consumer { _: WellbeingService ->
+ updateUi()
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_focus_mode)
+ // Set support action bar
+ val topAppBar = findViewById(R.id.topbar)
+ setSupportActionBar(topAppBar)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ // Enable layout transition
+ val layoutTransition =
+ (findViewById(R.id.focusModeRoot) as LinearLayoutCompat).layoutTransition
+ layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
+ // Open schedule screen
+ findViewById(R.id.schedule)?.setOnClickListener {
+ startActivity(
+ Intent(this, ScheduleActivity::class.java)
+ .putExtra("type", "focus_mode")
+ .putExtra("name", getString(R.string.focus_mode))
+ )
+ }
+ // Add state call back to the service
+ service.addStateCallback(stateCallback)
+ val r = findViewById(R.id.focusModePkgs)
+ r.adapter = PackageRecyclerViewAdapter(
+ this,
+ service.getInstalledApplications(PackageManager.GET_META_DATA),
+ "focus_mode"
+ ) { packageName: String? ->
+ service.onFocusModePreferenceChanged(
+ packageName!!
+ )
+ }
+ // Handle on click for main switch
+ findViewById(R.id.mainSwitchBar)?.setOnClickListener {
+ val state = service.getState()
+ if (state.isFocusModeEnabled()) {
+ service.disableFocusMode()
+ } else {
+ service.enableFocusMode()
+ }
+ }
+ updateUi()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ service.removeStateCallback(stateCallback)
+ }
+
+ private fun updateUi() {
+ val state = service.getState()
+ updateMainSwitch(state.isFocusModeEnabled())
+// val takeBreak = findViewById(R.id.takeBreak)
+// (findViewById(R.id.title) as AppCompatTextView).setText(if (state.isOnFocusModeBreakGlobal()) R.string.focus_mode_break_end else R.string.focus_mode_break)
+// takeBreak.setOnClickListener { v: View? ->
+// if (state.isOnFocusModeBreakGlobal()) {
+// service.endFocusModeBreak()
+// } else {
+// service.takeFocusModeBreakWithDialog(this@FocusModeActivity, false, null)
+// }
+// }
+// takeBreak.visibility = if (state.isFocusModeEnabled()) View.VISIBLE else View.GONE
+ }
+
+ private fun updateMainSwitch(checked: Boolean) {
+ findViewById(R.id.mainSwitchBar)?.isChecked = checked
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ finish()
+ return true
+ }
+}
diff --git a/app/src/main/java/org/eu/droid_ng/wellbeing/utils/BuildUtils.kt b/app/src/main/java/org/eu/droid_ng/wellbeing/utils/BuildUtils.kt
new file mode 100644
index 0000000..cf4db84
--- /dev/null
+++ b/app/src/main/java/org/eu/droid_ng/wellbeing/utils/BuildUtils.kt
@@ -0,0 +1,10 @@
+package org.eu.droid_ng.wellbeing.utils
+
+import android.os.Build
+
+object BuildUtils {
+
+ fun isAtLeastS(): Boolean {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+ }
+}
diff --git a/app/src/main/java/org/eu/droid_ng/wellbeing/widget/MainSwitchBar.kt b/app/src/main/java/org/eu/droid_ng/wellbeing/widget/MainSwitchBar.kt
new file mode 100644
index 0000000..af2aa8c
--- /dev/null
+++ b/app/src/main/java/org/eu/droid_ng/wellbeing/widget/MainSwitchBar.kt
@@ -0,0 +1,252 @@
+package org.eu.droid_ng.wellbeing.widget
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.os.Parcel
+import android.os.Parcelable
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.CompoundButton
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.annotation.ColorInt
+import androidx.core.content.ContextCompat
+import com.google.android.material.materialswitch.MaterialSwitch
+import org.eu.droid_ng.wellbeing.R
+import org.eu.droid_ng.wellbeing.utils.BuildUtils
+
+class MainSwitchBar @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+ defStyleRes: Int = 0
+) : LinearLayout(context, attrs, defStyleAttr, defStyleRes),
+ CompoundButton.OnCheckedChangeListener {
+
+ private val switchChangeListeners: MutableList = ArrayList()
+
+ @ColorInt
+ private var backgroundColor = 0
+
+ @ColorInt
+ private var backgroundActivatedColor = 0
+
+ private var textView: TextView? = null
+
+ /**
+ * Return the Switch
+ */
+ var switch: MaterialSwitch? = null
+ private set
+
+
+ private var backgroundOn: Drawable? = null
+ private var backgroundOff: Drawable? = null
+ private var backgroundDisabled: Drawable? = null
+ private var frameView: View? = null
+
+ /**
+ * Return the status of the Switch
+ */
+ /**
+ * Update the switch status
+ */
+ var isChecked: Boolean
+ get() = switch?.isChecked == true
+ set(checked) {
+ switch?.isChecked = checked
+ setBackground(checked)
+ }
+
+ /**
+ * Return the displaying status of org.eu.droid_ng.wellbeing.widget.MainSwitchBar
+ */
+ val isShowing: Boolean
+ get() = visibility == VISIBLE
+
+ init {
+ LayoutInflater.from(context).inflate(R.layout.main_switch_bar, this)
+ if (!BuildUtils.isAtLeastS()) {
+ val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.colorAccent))
+ backgroundActivatedColor = a.getColor(0, 0)
+ backgroundColor = context.getColor(androidx.appcompat.R.color.material_grey_600)
+ a.recycle()
+ }
+ isFocusable = true
+ isClickable = true
+ frameView = findViewById(R.id.frame)
+ textView = findViewById(R.id.switch_text)
+ switch = findViewById(R.id.materialSwitch)
+ val switchChecked = switch?.isChecked ?: false
+ if (BuildUtils.isAtLeastS()) {
+ backgroundOn = ContextCompat.getDrawable(context, R.drawable.main_switch_bar_bg_on)
+ backgroundOff = ContextCompat.getDrawable(context, R.drawable.main_switch_bar_bg_off)
+ backgroundDisabled = ContextCompat.getDrawable(
+ context,
+ R.drawable.main_switch_bar_bg_disabled
+ )
+ }
+ addOnSwitchChangeListener { _, isChecked ->
+ this@MainSwitchBar.isChecked = isChecked
+ }
+ if (switch?.visibility == VISIBLE) {
+ switch?.setOnCheckedChangeListener(this)
+ }
+ isChecked = switchChecked
+
+ if (attrs != null) {
+ val a = context.obtainStyledAttributes(
+ attrs,
+ intArrayOf(android.R.attr.text)
+ )
+ val title = a.getText(0)
+ setTitle(title)
+ a.recycle()
+ }
+ setBackground(switchChecked)
+ }
+
+ override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
+ propagateChecked(isChecked)
+ }
+
+ override fun performClick(): Boolean {
+ switch?.performClick()
+ return super.performClick()
+ }
+
+ /**
+ * Set the title text
+ */
+ fun setTitle(text: CharSequence?) {
+ textView?.text = text
+ }
+
+ /**
+ * Show the MainSwitchBar
+ */
+ fun show() {
+ visibility = VISIBLE
+ switch?.setOnCheckedChangeListener(this)
+ }
+
+ /**
+ * Hide the MainSwitchBar
+ */
+ fun hide() {
+ if (isShowing) {
+ visibility = GONE
+ switch?.setOnCheckedChangeListener(null)
+ }
+ }
+
+ /**
+ * Adds a listener for switch changes
+ */
+ fun addOnSwitchChangeListener(listener: OnMainSwitchChangeListener) {
+ if (!switchChangeListeners.contains(listener)) {
+ switchChangeListeners.add(listener)
+ }
+ }
+
+ /**
+ * Remove a listener for switch changes
+ */
+ fun removeOnSwitchChangeListener(listener: OnMainSwitchChangeListener) {
+ switchChangeListeners.remove(listener)
+ }
+
+ /**
+ * Enable or disable the text and switch.
+ */
+ override fun setEnabled(enabled: Boolean) {
+ super.setEnabled(enabled)
+ textView!!.isEnabled = enabled
+ switch!!.isEnabled = enabled
+ if (BuildUtils.isAtLeastS()) {
+ if (enabled) {
+ frameView?.background = if (isChecked) backgroundOn else backgroundOff
+ } else {
+ frameView?.background = backgroundDisabled
+ }
+ }
+ }
+
+ private fun propagateChecked(isChecked: Boolean) {
+ setBackground(isChecked)
+ val count = switchChangeListeners.size
+ for (n in 0 until count) {
+ switchChangeListeners[n].onSwitchChanged(switch, isChecked)
+ }
+ }
+
+ private fun setBackground(isChecked: Boolean) {
+ if (!BuildUtils.isAtLeastS()) {
+ setBackgroundColor(if (isChecked) backgroundActivatedColor else backgroundColor)
+ } else {
+ frameView?.background = if (isChecked) backgroundOn else backgroundOff
+ }
+ }
+
+ internal class SavedState : BaseSavedState {
+ var mChecked = false
+ var mVisible = false
+
+ constructor(superState: Parcelable?) : super(superState)
+
+ /**
+ * Constructor called from [.CREATOR]
+ */
+ private constructor(input: Parcel) : super(input) {
+ mChecked = input.readValue(null) as Boolean
+ mVisible = input.readValue(null) as Boolean
+ }
+
+ override fun writeToParcel(out: Parcel, flags: Int) {
+ super.writeToParcel(out, flags)
+ out.writeValue(mChecked)
+ out.writeValue(mVisible)
+ }
+
+ override fun toString(): String {
+ return ("MainSwitchBar.SavedState{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " checked=" + mChecked
+ + " visible=" + mVisible + "}")
+ }
+
+ object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): SavedState {
+ return SavedState(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+ }
+
+ public override fun onSaveInstanceState(): Parcelable {
+ val superState = super.onSaveInstanceState()
+ val ss = SavedState(superState)
+ ss.mChecked = switch?.isChecked ?: false
+ ss.mVisible = isShowing
+ return ss
+ }
+
+ public override fun onRestoreInstanceState(state: Parcelable) {
+ val ss = state as SavedState
+ super.onRestoreInstanceState(ss.superState)
+ switch?.isChecked = ss.mChecked
+ isChecked = ss.mChecked
+ setBackground(ss.mChecked)
+ visibility = if (ss.mVisible) VISIBLE else GONE
+ switch?.setOnCheckedChangeListener(if (ss.mVisible) this else null)
+ requestLayout()
+ }
+}
diff --git a/app/src/main/java/org/eu/droid_ng/wellbeing/widget/OnMainSwitchChangeListener.kt b/app/src/main/java/org/eu/droid_ng/wellbeing/widget/OnMainSwitchChangeListener.kt
new file mode 100644
index 0000000..6941077
--- /dev/null
+++ b/app/src/main/java/org/eu/droid_ng/wellbeing/widget/OnMainSwitchChangeListener.kt
@@ -0,0 +1,14 @@
+package org.eu.droid_ng.wellbeing.widget
+
+import com.google.android.material.materialswitch.MaterialSwitch
+
+/**
+ * Called when the checked state of the Switch has changed.
+ */
+fun interface OnMainSwitchChangeListener {
+ /**
+ * @param switchView The Switch view whose state has changed.
+ * @param isChecked The new checked state of switchView.
+ */
+ fun onSwitchChanged(switchView: MaterialSwitch?, isChecked: Boolean)
+}
diff --git a/app/src/main/res/drawable/main_switch_bar_bg_disabled.xml b/app/src/main/res/drawable/main_switch_bar_bg_disabled.xml
new file mode 100644
index 0000000..e3ac7a3
--- /dev/null
+++ b/app/src/main/res/drawable/main_switch_bar_bg_disabled.xml
@@ -0,0 +1,25 @@
+
+
+
+ -
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/main_switch_bar_bg_off.xml b/app/src/main/res/drawable/main_switch_bar_bg_off.xml
new file mode 100644
index 0000000..5455bd0
--- /dev/null
+++ b/app/src/main/res/drawable/main_switch_bar_bg_off.xml
@@ -0,0 +1,10 @@
+
+
+ -
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/main_switch_bar_bg_on.xml b/app/src/main/res/drawable/main_switch_bar_bg_on.xml
new file mode 100644
index 0000000..fc3688e
--- /dev/null
+++ b/app/src/main/res/drawable/main_switch_bar_bg_on.xml
@@ -0,0 +1,9 @@
+
+ -
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_focus_mode.xml b/app/src/main/res/layout/activity_focus_mode.xml
new file mode 100644
index 0000000..609147f
--- /dev/null
+++ b/app/src/main/res/layout/activity_focus_mode.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_focusmode.xml b/app/src/main/res/layout/activity_focusmode.xml
deleted file mode 100644
index 12e9206..0000000
--- a/app/src/main/res/layout/activity_focusmode.xml
+++ /dev/null
@@ -1,182 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/main_switch_bar.xml b/app/src/main/res/layout/main_switch_bar.xml
new file mode 100644
index 0000000..b34c6b1
--- /dev/null
+++ b/app/src/main/res/layout/main_switch_bar.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7e0381a..243ba06 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -7,6 +7,12 @@
@string/other
Tap to set up
+
+ Enable Focus mode
+ Focus mode is blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah
+ Focus mode settings
+ Set a schedule
+
Loading…
Focus mode, bedtime mode, app timers
App is blocked
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 5089b2e..1f57e53 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -33,4 +33,13 @@
- @layout/preference_material_switch
+
diff --git a/app/src/main/res/xml/main_preferences.xml b/app/src/main/res/xml/main_preferences.xml
index 77e0a5c..24e8c93 100644
--- a/app/src/main/res/xml/main_preferences.xml
+++ b/app/src/main/res/xml/main_preferences.xml
@@ -15,7 +15,7 @@
app:icon="@drawable/ic_baseline_person_24dp"
app:summary="@string/main_preference_focus_mode_summary">