From 56678f8a76a4034ae8a63c92e49ba39cc54ee057 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Thu, 22 Jun 2017 15:20:11 -0700 Subject: Add notification filtering --- .../com/pitchedapps/frost/SettingsActivity.kt | 64 ++++++++++++- .../frost/services/NotificationService.kt | 2 + .../kotlin/com/pitchedapps/frost/utils/Prefs.kt | 9 ++ .../com/pitchedapps/frost/views/AccountItem.kt | 2 +- .../kotlin/com/pitchedapps/frost/views/Keywords.kt | 101 +++++++++++++++++++++ .../pitchedapps/frost/web/FrostWebViewClient.kt | 9 +- .../com/pitchedapps/frost/web/FrostWebViewCore.kt | 3 +- 7 files changed, 178 insertions(+), 12 deletions(-) create mode 100644 app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt (limited to 'app/src/main/kotlin/com') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt index bcf30614..ca823513 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt @@ -11,19 +11,37 @@ import ca.allanwang.kau.utils.* import ca.allanwang.kau.views.RippleCanvas import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.pitchedapps.frost.utils.* +import com.pitchedapps.frost.views.Keywords /** * Created by Allan Wang on 2017-06-06. */ class SettingsActivity : KPrefActivity() { + override fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit = { textColor = { Prefs.textColor } - accentColor = { Prefs.textColor } + accentColor = { + if (Prefs.headerColor.isColorVisibleOn(Prefs.bgColor, 100)) Prefs.headerColor + else Prefs.textColor + } } override fun onCreateKPrefs(savedInstanceState: android.os.Bundle?): KPrefAdapterBuilder.() -> Unit = { - header(R.string.settings) + subItems(R.string.appearance, subPrefsAppearance()) { + descRes = R.string.appearance_desc + iicon = GoogleMaterial.Icon.gmd_palette + } + subItems(R.string.notifications, subPrefsNotifications()) { + descRes = R.string.notifications_desc + iicon = GoogleMaterial.Icon.gmd_notifications + } + } + + fun subPrefsAppearance(): KPrefAdapterBuilder.() -> Unit = { + + header(R.string.base_customization) + text(R.string.theme, { Prefs.theme }, { Prefs.theme = it }) { onClick = { _, _, item -> @@ -88,15 +106,32 @@ class SettingsActivity : KPrefActivity() { onDisabledClick = { itemView, _, _ -> itemView.snackbar(R.string.requires_custom_theme); true } allowCustom = true } + + checkbox(R.string.rounded_icons, { Prefs.showRoundedIcons }, { Prefs.showRoundedIcons = it }) + + checkbox(R.string.fancy_animations, { Prefs.animate }, { Prefs.animate = it; animate = it }) { + descRes = R.string.fancy_animations_desc + } + + header(R.string.feed_customization) + + checkbox(R.string.suggested_friends, { Prefs.showSuggestedFriends }, { Prefs.showSuggestedFriends = it }) { + descRes = R.string.suggested_friends_desc + } } - text(R.string.notifications, { Prefs.notificationFreq }, { Prefs.notificationFreq = it; reloadByTitle(R.string.notifications) }) { + + } + + fun subPrefsNotifications(): KPrefAdapterBuilder.() -> Unit = { + + text(R.string.notification_frequency, { Prefs.notificationFreq }, { Prefs.notificationFreq = it; reloadByTitle(R.string.notifications) }) { val options = longArrayOf(-1, 15, 30, 60, 120, 180, 300, 1440, 2880) val texts = options.map { this@SettingsActivity.minuteToText(it) } onClick = { _, _, item -> this@SettingsActivity.materialDialogThemed { - title(R.string.notifications) + title(R.string.notification_frequency) items(texts) itemsCallbackSingleChoice(options.indexOf(item.pref), { _, _, which, text -> @@ -110,6 +145,23 @@ class SettingsActivity : KPrefActivity() { textGetter = { this@SettingsActivity.minuteToText(it) } } + text(R.string.notification_keywords, { null }, { }) { + descRes = R.string.notification_keywords_desc + onClick = { + _, _, _ -> + val keywordView = Keywords(this@SettingsActivity) + this@SettingsActivity.materialDialogThemed { + title(R.string.notification_keywords) + customView(keywordView, false) + canceledOnTouchOutside(false) + positiveText(R.string.kau_done) + negativeText(R.string.kau_cancel) + onPositive { _, _ -> keywordView.save() } + } + true + } + } + } fun shouldRestartMain() { @@ -118,6 +170,7 @@ class SettingsActivity : KPrefActivity() { override fun onCreate(savedInstanceState: Bundle?) { setFrostTheme(true) + animate = Prefs.animate super.onCreate(savedInstanceState) themeExterior(false) } @@ -132,7 +185,8 @@ class SettingsActivity : KPrefActivity() { } override fun onBackPressed() { - finishSlideOut() + if (!super.backPress()) + finishSlideOut() } override fun onCreateOptionsMenu(menu: Menu): Boolean { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt index 03dd21a4..23bf7f96 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -18,6 +18,7 @@ import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FB_URL_BASE import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.frostAnswersCustom import com.pitchedapps.frost.utils.frostNotification import org.jetbrains.anko.doAsync @@ -83,6 +84,7 @@ class NotificationService : JobService() { val abbr = element.getElementsByTag("abbr") val timeString = abbr?.text() var text = a.text().replace("\u00a0", " ") //remove   + if (Prefs.notificationKeywords.any { text.contains(it, ignoreCase = true) }) return null //notification filtered out if (timeString != null) text = text.removeSuffix(timeString) text = text.trim() val abbrData = abbr?.attr("data-store") diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt index 83564be9..428d0c30 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -2,6 +2,7 @@ package com.pitchedapps.frost.utils import android.graphics.Color import ca.allanwang.kau.kpref.KPref +import ca.allanwang.kau.kpref.StringSet import ca.allanwang.kau.kpref.kpref import ca.allanwang.kau.utils.lazyResettable import com.pitchedapps.frost.injectors.InjectorContract @@ -60,4 +61,12 @@ object Prefs : KPref() { val isCustomTheme: Boolean get() = t == Theme.CUSTOM + + var showRoundedIcons: Boolean by kpref("rounded_icons", true) + + var showSuggestedFriends: Boolean by kpref("suggested_friends_feed", true) + + var animate: Boolean by kpref("fancy_animations", true) + + var notificationKeywords: StringSet by kpref("notification_keywords", mutableSetOf()) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt index 3de038bf..c9ee5a76 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt @@ -33,7 +33,7 @@ class AccountItem(val cookie: CookieModel?) : AbstractItem) { + override fun bindView(viewHolder: ViewHolder, payloads: List?) { super.bindView(viewHolder, payloads) with(viewHolder) { text.visibility = View.INVISIBLE diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt new file mode 100644 index 00000000..25079834 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt @@ -0,0 +1,101 @@ +package com.pitchedapps.frost.views + +import android.content.Context +import android.graphics.drawable.Drawable +import android.support.constraint.ConstraintLayout +import android.support.v7.widget.AppCompatEditText +import android.support.v7.widget.AppCompatTextView +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import ca.allanwang.kau.kpref.StringSet +import ca.allanwang.kau.utils.bindView +import ca.allanwang.kau.utils.string +import ca.allanwang.kau.utils.tint +import ca.allanwang.kau.utils.toDrawable +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter +import com.mikepenz.fastadapter.items.AbstractItem +import com.mikepenz.fastadapter.listeners.ClickEventHook +import com.mikepenz.google_material_typeface_library.GoogleMaterial +import com.mikepenz.iconics.typeface.IIcon +import com.pitchedapps.frost.R +import com.pitchedapps.frost.utils.Prefs + + +/** + * Created by Allan Wang on 2017-06-19. + */ +class Keywords @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : ConstraintLayout(context, attrs, defStyleAttr) { + + val editText: AppCompatEditText by bindView(R.id.edit_text) + val addIcon: ImageView by bindView(R.id.add_icon) + val recycler: RecyclerView by bindView(R.id.recycler) + val adapter = FastItemAdapter() + + init { + inflate(context, R.layout.view_keywords, this) + editText.tint(Prefs.textColor) + addIcon.setImageDrawable(GoogleMaterial.Icon.gmd_add.keywordDrawable(context)) + addIcon.setOnClickListener { + if (editText.text.isEmpty()) editText.error = context.string(R.string.empty_keyword) + else { + adapter.add(0, KeywordItem(editText.text.toString())) + editText.text.clear() + } + } + adapter.add(Prefs.notificationKeywords.map { KeywordItem(it) }) + recycler.layoutManager = LinearLayoutManager(context) + recycler.adapter = adapter + adapter.withEventHook(object : ClickEventHook() { + override fun onBind(viewHolder: RecyclerView.ViewHolder): View? + = (viewHolder as? KeywordItem.ViewHolder)?.delete + + override fun onClick(v: View, position: Int, fastAdapter: FastAdapter, item: KeywordItem) { + adapter.remove(position) + } + }) + } + + fun save() { + val keywords = adapter.adapterItems.map { it.keyword } + Prefs.notificationKeywords = StringSet(keywords) + } + + +} + +private fun IIcon.keywordDrawable(context: Context): Drawable = toDrawable(context, 20, Prefs.textColor) + +class KeywordItem(val keyword: String) : AbstractItem() { + + override fun getViewHolder(v: View): ViewHolder = ViewHolder(v) + + override fun getType(): Int = R.id.item_keyword + + override fun getLayoutRes(): Int = R.layout.item_keyword + + override fun bindView(holder: ViewHolder, payloads: MutableList?) { + super.bindView(holder, payloads) + holder.text.text = keyword + } + + override fun unbindView(holder: ViewHolder) { + super.unbindView(holder) + holder.text.text = null + } + + class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { + val text: AppCompatTextView by bindView(R.id.keyword_text) + val delete: ImageView by bindView(R.id.keyword_delete) + + init { + text.setTextColor(Prefs.textColor) + delete.setImageDrawable(GoogleMaterial.Icon.gmd_delete.keywordDrawable(itemView.context)) + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt index a791363e..8b1eca1e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt @@ -12,10 +12,7 @@ import com.pitchedapps.frost.MainActivity import com.pitchedapps.frost.SelectorActivity import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FbCookie -import com.pitchedapps.frost.injectors.CssHider -import com.pitchedapps.frost.injectors.JsActions -import com.pitchedapps.frost.injectors.JsAssets -import com.pitchedapps.frost.injectors.jsInject +import com.pitchedapps.frost.injectors.* import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.cookies @@ -53,7 +50,9 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : WebViewClient() { refreshObservable.onNext(false) return } - view.jsInject(JsActions.LOGIN_CHECK, JsAssets.HEADER_BADGES.maybe(webCore.baseEnum != null)) + view.jsInject(JsActions.LOGIN_CHECK, + CssAssets.ROUND_ICONS.maybe(Prefs.showRoundedIcons), + JsAssets.HEADER_BADGES.maybe(webCore.baseEnum != null)) onPageFinishedActions(url) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt index 6e9e956f..b953e092 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt @@ -18,6 +18,7 @@ import ca.allanwang.kau.utils.fadeOut import ca.allanwang.kau.utils.isVisible import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.USER_AGENT_BASIC +import com.pitchedapps.frost.utils.Prefs import io.reactivex.Scheduler import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable @@ -93,7 +94,7 @@ class FrostWebViewCore @JvmOverloads constructor( if (isVisible()) fadeOut(duration = 200L) } else if (loading) { dispose?.dispose() - if (animate) circularReveal(offset = 150L) + if (animate && Prefs.animate) circularReveal(offset = 150L) else fadeIn(duration = 100L) } } -- cgit v1.2.3