Skip to content
Snippets Groups Projects
Verified Commit 4bc27eae authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Implement notification settings, fixes #48

parent b9760a0b
Branches
Tags
No related merge requests found
Pipeline #
Showing
with 438 additions and 15 deletions
......@@ -21,7 +21,7 @@ package de.kuschku.quasseldroid.ui.coresettings.identity
import android.content.Context
import android.content.Intent
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class IdentityCreateActivity : ServiceBoundSettingsActivity(IdentityCreateFragment()) {
companion object {
......
......@@ -22,7 +22,7 @@ package de.kuschku.quasseldroid.ui.coresettings.identity
import android.content.Context
import android.content.Intent
import de.kuschku.libquassel.protocol.IdentityId
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class IdentityEditActivity : ServiceBoundSettingsActivity(IdentityEditFragment()) {
companion object {
......
......@@ -22,7 +22,7 @@ package de.kuschku.quasseldroid.ui.coresettings.ignoreitem
import android.content.Context
import android.content.Intent
import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class IgnoreItemActivity : ServiceBoundSettingsActivity(IgnoreItemFragment()) {
companion object {
......
......@@ -21,7 +21,7 @@ package de.kuschku.quasseldroid.ui.coresettings.ignorelist
import android.content.Context
import android.content.Intent
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class IgnoreListActivity : ServiceBoundSettingsActivity(IgnoreListFragment()) {
companion object {
......
......@@ -21,7 +21,7 @@ package de.kuschku.quasseldroid.ui.coresettings.network
import android.content.Context
import android.content.Intent
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class NetworkCreateActivity : ServiceBoundSettingsActivity(NetworkCreateFragment()) {
companion object {
......
......@@ -22,7 +22,7 @@ package de.kuschku.quasseldroid.ui.coresettings.network
import android.content.Context
import android.content.Intent
import de.kuschku.libquassel.protocol.NetworkId
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class NetworkEditActivity : ServiceBoundSettingsActivity(NetworkEditFragment()) {
companion object {
......
......@@ -21,7 +21,7 @@ package de.kuschku.quasseldroid.ui.coresettings.networkconfig
import android.content.Context
import android.content.Intent
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class NetworkConfigActivity : ServiceBoundSettingsActivity(NetworkConfigFragment()) {
companion object {
......
......@@ -22,7 +22,7 @@ package de.kuschku.quasseldroid.ui.coresettings.networkserver
import android.content.Context
import android.content.Intent
import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
import de.kuschku.quasseldroid.util.ui.ServiceBoundSettingsActivity
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class NetworkServerActivity : ServiceBoundSettingsActivity(NetworkServerFragment()) {
companion object {
......
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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/>.
*/
package de.kuschku.quasseldroid.util.helper
import android.support.v7.preference.PreferenceCategory
import android.support.v7.preference.PreferenceScreen
fun PreferenceCategory.preferences() = (0 until preferenceCount).map(this::getPreference)
fun PreferenceScreen.preferences() = (0 until preferenceCount).map(this::getPreference)
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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/>.
*/
package de.kuschku.quasseldroid.util.ui.settings
import android.content.Intent
interface ActivityLauncher {
fun startActivityForResult(intent: Intent, requestCode: Int)
fun registerOnActivityResultListener(listener: OnActivityResultListener)
fun unregisterOnActivityResultListener(listener: OnActivityResultListener)
fun getNextRequestCode(): Int
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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/>.
*/
package de.kuschku.quasseldroid.util.ui.settings
import android.content.Intent
import android.os.Bundle
import android.support.v7.preference.Preference
import android.support.v7.preference.PreferenceCategory
import android.support.v7.preference.PreferenceFragmentCompat
import android.support.v7.preference.PreferenceScreen
import de.kuschku.quasseldroid.util.helper.preferences
import java.util.concurrent.atomic.AtomicInteger
abstract class AttachingPreferenceFragmentCompat : PreferenceFragmentCompat(), ActivityLauncher {
private val nextRequestCode = AtomicInteger(0)
private var activityResultListeners = emptySet<OnActivityResultListener>()
override fun registerOnActivityResultListener(listener: OnActivityResultListener) {
activityResultListeners += listener
}
override fun unregisterOnActivityResultListener(listener: OnActivityResultListener) {
activityResultListeners -= listener
}
override fun getNextRequestCode() = nextRequestCode.getAndIncrement()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
attachPreference(preferenceScreen)
}
private fun attachPreference(preference: Preference) {
when (preference) {
is PreferenceScreen -> preference.preferences().forEach(::attachPreference)
is PreferenceCategory -> preference.preferences().forEach(::attachPreference)
is RequiresActivityLauncher -> preference.activityLauncher = this
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
for (it in activityResultListeners) {
it.onActivityResult(requestCode, resultCode, data)
}
}
}
......@@ -17,18 +17,17 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.quasseldroid.util.backport
package de.kuschku.quasseldroid.util.ui.settings
import android.content.Context
import android.support.v4.app.Fragment
import android.support.v7.preference.PreferenceFragmentCompat
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.AndroidSupportInjection
import dagger.android.support.HasSupportFragmentInjector
import javax.inject.Inject
abstract class DaggerPreferenceFragmentCompat : PreferenceFragmentCompat(),
abstract class DaggerPreferenceFragmentCompat : AttachingPreferenceFragmentCompat(),
HasSupportFragmentInjector {
@Inject
lateinit var childFragmentInjector: DispatchingAndroidInjector<Fragment>
......
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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/>.
*/
package de.kuschku.quasseldroid.util.ui.settings
import android.content.Intent
interface OnActivityResultListener {
/**
* See Activity's onActivityResult.
*
* @return Whether the request code was handled (in which case
* subsequent listeners will not be called.
*/
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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/>.
*/
package de.kuschku.quasseldroid.util.ui.settings
interface RequiresActivityLauncher {
var activityLauncher: ActivityLauncher?
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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/>.
*/
package de.kuschku.quasseldroid.util.ui.settings
import android.content.Context
import android.content.Intent
import android.content.res.TypedArray
import android.media.RingtoneManager
import android.net.Uri
import android.support.v7.preference.DialogPreference
import android.text.TextUtils
import android.util.AttributeSet
import de.kuschku.quasseldroid.R
class RingtonePreference : DialogPreference,
RequiresActivityLauncher,
OnActivityResultListener {
private val TAG = "RingtonePreference"
private var mRingtoneType: Int = 0
private var mShowDefault: Boolean = false
private var mShowSilent: Boolean = false
private var mRequestCode: Int? = null
override var activityLauncher: ActivityLauncher? = null
set(value) {
field?.unregisterOnActivityResultListener(this)
field = value
value?.registerOnActivityResultListener(this)
mRequestCode = value?.getNextRequestCode()
}
constructor(context: Context) :
this(context, null)
constructor(context: Context, attrs: AttributeSet?) :
this(context, attrs, R.attr.ringtonePreferenceStyle)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
this(context, attrs, defStyleAttr, 0)
constructor(context: Context, attrs: AttributeSet?, styleAttr: Int, styleRes: Int) :
super(context, attrs, styleAttr, styleRes) {
val a = context.obtainStyledAttributes(
attrs, R.styleable.RingtonePreference, styleAttr, styleRes)
mRingtoneType = a.getInt(R.styleable.RingtonePreference_ringtoneType,
RingtoneManager.TYPE_RINGTONE)
mShowDefault = a.getBoolean(R.styleable.RingtonePreference_showDefault, true)
mShowSilent = a.getBoolean(R.styleable.RingtonePreference_showSilent, true)
a.recycle()
}
/**
* Returns the sound type(s) that are shown in the picker.
*
* @return The sound type(s) that are shown in the picker.
* @see .setRingtoneType
*/
fun getRingtoneType(): Int {
return mRingtoneType
}
/**
* Sets the sound type(s) that are shown in the picker.
*
* @param type The sound type(s) that are shown in the picker.
* @see RingtoneManager.EXTRA_RINGTONE_TYPE
*/
fun setRingtoneType(type: Int) {
mRingtoneType = type
}
/**
* Returns whether to a show an item for the default sound/ringtone.
*
* @return Whether to show an item for the default sound/ringtone.
*/
fun getShowDefault(): Boolean {
return mShowDefault
}
/**
* Sets whether to show an item for the default sound/ringtone. The default
* to use will be deduced from the sound type(s) being shown.
*
* @param showDefault Whether to show the default or not.
* @see RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT
*/
fun setShowDefault(showDefault: Boolean) {
mShowDefault = showDefault
}
/**
* Returns whether to a show an item for 'Silent'.
*
* @return Whether to show an item for 'Silent'.
*/
fun getShowSilent(): Boolean {
return mShowSilent
}
/**
* Sets whether to show an item for 'Silent'.
*
* @param showSilent Whether to show 'Silent'.
* @see RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT
*/
fun setShowSilent(showSilent: Boolean) {
mShowSilent = showSilent
}
override fun onClick() {
// Launch the ringtone picker
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER)
onPrepareRingtonePickerIntent(intent)
mRequestCode?.let {
activityLauncher?.startActivityForResult(intent, it)
}
}
/**
* Prepares the intent to launch the ringtone picker. This can be modified
* to adjust the parameters of the ringtone picker.
*
* @param ringtonePickerIntent The ringtone picker intent that can be
* modified by putting extras.
*/
protected fun onPrepareRingtonePickerIntent(ringtonePickerIntent: Intent) {
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault)
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent)
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType)
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, title)
if (mShowDefault) {
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
RingtoneManager.getDefaultUri(getRingtoneType()))
}
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, onRestoreRingtone())
}
/**
* Called when a ringtone is chosen.
*
*
* By default, this saves the ringtone URI to the persistent storage as a
* string.
*
* @param ringtoneUri The chosen ringtone's [Uri]. Can be null.
*/
protected fun onSaveRingtone(ringtoneUri: Uri?) {
persistString(ringtoneUri?.toString() ?: "")
updateSummary(ringtoneUri)
}
/**
* Called when the chooser is about to be shown and the current ringtone
* should be marked. Can return null to not mark any ringtone.
*
*
* By default, this restores the previous ringtone URI from the persistent
* storage.
*
* @return The ringtone to be marked as the current ringtone.
*/
protected fun onRestoreRingtone(): Uri? {
val uriString = getPersistedString(null)
return if (!TextUtils.isEmpty(uriString)) Uri.parse(uriString) else null
}
private fun updateSummary(ringtoneUri: Uri?) {
summary = ringtoneUri?.let {
RingtoneManager.getRingtone(context, ringtoneUri).getTitle(context)
} ?: context.getString(R.string.label_no_sound)
}
override fun onGetDefaultValue(a: TypedArray, index: Int): Any? {
return a.getString(index)
}
override fun onSetInitialValue(restorePersistedValue: Boolean, defaultValueObj: Any?) {
val defaultValue = defaultValueObj as? String ?: ""
if (restorePersistedValue) {
updateSummary(onRestoreRingtone())
return
}
// If we are setting to the default value, we should persist it.
if (!TextUtils.isEmpty(defaultValue)) {
onSaveRingtone(Uri.parse(defaultValue))
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
if (requestCode == mRequestCode) {
if (data != null) {
val uri = data.getParcelableExtra<Uri>(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
if (callChangeListener(uri?.toString() ?: "")) {
onSaveRingtone(uri)
}
}
return true
}
return false
}
}
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.kuschku.quasseldroid.util.ui
package de.kuschku.quasseldroid.util.ui.settings
import android.content.Context
import android.content.res.TypedArray
......
......@@ -17,7 +17,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.quasseldroid.util.ui
package de.kuschku.quasseldroid.util.ui.settings
import android.os.Bundle
import android.support.v4.app.Fragment
......
......@@ -17,7 +17,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.quasseldroid.util.ui
package de.kuschku.quasseldroid.util.ui.settings
import android.os.Bundle
import android.support.v4.app.Fragment
......@@ -28,6 +28,7 @@ import butterknife.ButterKnife
import com.afollestad.materialdialogs.MaterialDialog
import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
import de.kuschku.quasseldroid.util.ui.ThemedActivity
abstract class SettingsActivity(private val fragment: Fragment? = null) : ThemedActivity() {
protected open fun fragment(): Fragment? = null
......
<?xml version="1.0" encoding="utf-8"?><!--
Quasseldroid - Quassel client for Android
Copyright (c) 2018 Janne Koschinski
Copyright (c) 2018 The Quassel Project
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License version 3 as published
by the Free Software Foundation.
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/>.
-->
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?colorDivider" />
......@@ -25,7 +25,6 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="?listPreferredItemHeightSmall"
android:background="?background"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment