aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2018-03-11 15:47:35 -0400
committerGitHub <noreply@github.com>2018-03-11 15:47:35 -0400
commit67988a25d83fc10b187fcc821c3ceacfad0195d5 (patch)
tree58d6622f3eccf0275d55ee7f6ef2ba76845211ab /app
parent7f74e08270e34eb66a824ac18519293d4a42278c (diff)
downloadfrost-67988a25d83fc10b187fcc821c3ceacfad0195d5.tar.gz
frost-67988a25d83fc10b187fcc821c3ceacfad0195d5.tar.bz2
frost-67988a25d83fc10b187fcc821c3ceacfad0195d5.zip
Fix/notification sound (#763)
* Update dependencies * Update theme * Fix bad css merge * Add notification feedback for fetching now * Hide notif settings that no longer work with channels * Wip android o channels * Revert back to old group method * Update dependencies * Update rxnetwork version
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle1
-rw-r--r--app/src/main/assets/css/core/_core_bg.scss4
-rw-r--r--app/src/main/assets/css/core/_core_border.scss4
-rw-r--r--app/src/main/assets/css/core/_core_text.scss2
-rw-r--r--app/src/main/assets/css/core/core.css8
-rw-r--r--app/src/main/assets/css/themes/custom.css8
-rw-r--r--app/src/main/assets/css/themes/material_amoled.css8
-rw-r--r--app/src/main/assets/css/themes/material_dark.css8
-rw-r--r--app/src/main/assets/css/themes/material_glass.css8
-rw-r--r--app/src/main/assets/css/themes/material_light.css8
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt190
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt172
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt40
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt97
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt2
-rw-r--r--app/src/main/res/values/strings.xml2
-rw-r--r--app/src/main/res/values/strings_errors.xml1
-rw-r--r--app/src/main/res/values/strings_no_translate.xml1
-rw-r--r--app/src/main/res/values/strings_pref_notifications.xml2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt3
22 files changed, 259 insertions, 316 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 3c9ceaa0..ef771b16 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -223,6 +223,7 @@ dependencies {
implementation "com.sothree.slidinguppanel:library:${SLIDING_PANEL}"
//Reactive Libs
+ implementation "io.reactivex.rxjava2:rxjava:${RX_JAVA}"
implementation "io.reactivex.rxjava2:rxkotlin:${RX_KOTLIN}"
implementation "io.reactivex.rxjava2:rxandroid:${RX_ANDROID}"
implementation "com.github.pwittchen:reactivenetwork-rx2:${RX_NETWORK}"
diff --git a/app/src/main/assets/css/core/_core_bg.scss b/app/src/main/assets/css/core/_core_bg.scss
index 3df96ae6..3ba4e7c8 100644
--- a/app/src/main/assets/css/core/_core_bg.scss
+++ b/app/src/main/assets/css/core/_core_bg.scss
@@ -16,9 +16,9 @@ body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9
._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5,
._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl,
.acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01,
-._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel,
+._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3bmj, ._5zmb, ._2x2s, ._3kac, ._3kad,
._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu,
-._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp,
+._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._5zma,
._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy,
._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x {
background: $bg_transparent !important;
diff --git a/app/src/main/assets/css/core/_core_border.scss b/app/src/main/assets/css/core/_core_border.scss
index 8aba6d1e..a6152437 100644
--- a/app/src/main/assets/css/core/_core_border.scss
+++ b/app/src/main/assets/css/core/_core_border.scss
@@ -31,7 +31,7 @@
border-bottom: 1px solid $divider !important;
}
-.item a.primary.touched .primarywrap, ._4dwt ._5y33,
+.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._1ih_,
._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq {
border-top: 1px solid $divider !important;
border-bottom: 1px solid $divider !important;
@@ -80,7 +80,7 @@
border-right: 10px solid $bg_transparent !important;
}
-._2cir.selected, ._42rv {
+._2cir.selected, ._42rv, ._5zma, ._2x2s {
border-bottom: 3px solid $text !important;
}
diff --git a/app/src/main/assets/css/core/_core_text.scss b/app/src/main/assets/css/core/_core_text.scss
index be25066c..e5c2c7f7 100644
--- a/app/src/main/assets/css/core/_core_text.scss
+++ b/app/src/main/assets/css/core/_core_text.scss
@@ -15,7 +15,7 @@ textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782,
._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions,
._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g,
._2new, .appCenterCategorySelectorButton,
-div.sharerSelector, .footer, ._4pv_, ._1dbp,
+div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad,
.mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw,
._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4,
._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs,
diff --git a/app/src/main/assets/css/core/core.css b/app/src/main/assets/css/core/core.css
index aae5de3a..1fb7b9eb 100644
--- a/app/src/main/assets/css/core/core.css
+++ b/app/src/main/assets/css/core/core.css
@@ -1,4 +1,4 @@
-[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #d7b0d7 !important; }
+[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #d7b0d7 !important; }
strong > a, ._15ks ._2q8z._2q8z, ._1e3e { color: #3b5998 !important; }
@@ -8,7 +8,7 @@ a, ._5fpq { color: #d59ed5 !important; }
#viewport { background: #451515 !important; }
-body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: rgba(255, 0, 255, 0.02) !important; }
+body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3bmj, ._5zmb, ._2x2s, ._3kac, ._3kad, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._5zma, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: rgba(255, 0, 255, 0.02) !important; }
._31nf, ._2v9s, ._d4i, article._55wo, ._10c_, ._2jl2, ._55wo, ._6150 { background: #239645 !important; }
@@ -38,7 +38,7 @@ button ._v89 ._54k8._1fl1 { background: #3b5998 !important; }
._15ny::after, ._z-w, ._8i2, ._2nk0, ._22_8, ._1t4h, ._37fd, ._1ha, ._3bg5 ._56do, ._8he, ._400s, ._5hoc, ._1bhn, ._5ag6, ._4pvz, ._301x, ._x08 ._x0a:after, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, ._2bdc, ._3ci9, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .error, ._35--, ._1wev, .jx-result, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child { border-bottom: 1px solid rgba(215, 176, 215, 0.3) !important; }
-.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(215, 176, 215, 0.3) !important; border-bottom: 1px solid rgba(215, 176, 215, 0.3) !important; }
+.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._1ih_, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(215, 176, 215, 0.3) !important; border-bottom: 1px solid rgba(215, 176, 215, 0.3) !important; }
._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, .sharerAttachment, .mToken, #addMembersTypeahead .mToken.mTokenWeakReference, .mQuestionsPollResultsBar, ._15q7, ._2q7v, ._4dwt ._16ii, ._3qdi::after, ._2q7w, .acy, ._58ak, ._3t_l, ._4msa, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._50uu, ._50uw, ._31yd, ._1e3d, ._3xz7, ._1xoz, ._4kcb, ._2lut, .jewel .touchable-notification.touched, .touchable-notification .touchable.touched, .home-notification .touchable.touched, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(215, 176, 215, 0.3) !important; }
@@ -54,7 +54,7 @@ button ._v89 ._54k8._1fl1 { background: #3b5998 !important; }
._2cis { border-left: 10px solid rgba(255, 0, 255, 0.02) !important; border-right: 10px solid rgba(255, 0, 255, 0.02) !important; }
-._2cir.selected, ._42rv { border-bottom: 3px solid #d7b0d7 !important; }
+._2cir.selected, ._42rv, ._5zma, ._2x2s { border-bottom: 3px solid #d7b0d7 !important; }
._1ss6 { border-left: 2px solid #d7b0d7 !important; }
diff --git a/app/src/main/assets/css/themes/custom.css b/app/src/main/assets/css/themes/custom.css
index 4fbfa2c3..b7bb1d21 100644
--- a/app/src/main/assets/css/themes/custom.css
+++ b/app/src/main/assets/css/themes/custom.css
@@ -1,4 +1,4 @@
-[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: $T$ !important; }
+[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: $T$ !important; }
strong > a, ._15ks ._2q8z._2q8z, ._1e3e { color: $A$ !important; }
@@ -8,7 +8,7 @@ a, ._5fpq { color: $TT$ !important; }
#viewport { background: $B$ !important; }
-body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: $BT$ !important; }
+body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3bmj, ._5zmb, ._2x2s, ._3kac, ._3kad, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._5zma, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: $BT$ !important; }
._31nf, ._2v9s, ._d4i, article._55wo, ._10c_, ._2jl2, ._55wo, ._6150 { background: $C$ !important; }
@@ -38,7 +38,7 @@ button ._v89 ._54k8._1fl1 { background: $A$ !important; }
._15ny::after, ._z-w, ._8i2, ._2nk0, ._22_8, ._1t4h, ._37fd, ._1ha, ._3bg5 ._56do, ._8he, ._400s, ._5hoc, ._1bhn, ._5ag6, ._4pvz, ._301x, ._x08 ._x0a:after, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, ._2bdc, ._3ci9, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .error, ._35--, ._1wev, .jx-result, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child { border-bottom: 1px solid $D$ !important; }
-.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid $D$ !important; border-bottom: 1px solid $D$ !important; }
+.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._1ih_, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid $D$ !important; border-bottom: 1px solid $D$ !important; }
._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, .sharerAttachment, .mToken, #addMembersTypeahead .mToken.mTokenWeakReference, .mQuestionsPollResultsBar, ._15q7, ._2q7v, ._4dwt ._16ii, ._3qdi::after, ._2q7w, .acy, ._58ak, ._3t_l, ._4msa, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._50uu, ._50uw, ._31yd, ._1e3d, ._3xz7, ._1xoz, ._4kcb, ._2lut, .jewel .touchable-notification.touched, .touchable-notification .touchable.touched, .home-notification .touchable.touched, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid $D$ !important; }
@@ -54,7 +54,7 @@ button ._v89 ._54k8._1fl1 { background: $A$ !important; }
._2cis { border-left: 10px solid $BT$ !important; border-right: 10px solid $BT$ !important; }
-._2cir.selected, ._42rv { border-bottom: 3px solid $T$ !important; }
+._2cir.selected, ._42rv, ._5zma, ._2x2s { border-bottom: 3px solid $T$ !important; }
._1ss6 { border-left: 2px solid $T$ !important; }
diff --git a/app/src/main/assets/css/themes/material_amoled.css b/app/src/main/assets/css/themes/material_amoled.css
index 8ba7341e..cebaed7e 100644
--- a/app/src/main/assets/css/themes/material_amoled.css
+++ b/app/src/main/assets/css/themes/material_amoled.css
@@ -1,4 +1,4 @@
-[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; }
+[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; }
strong > a, ._15ks ._2q8z._2q8z, ._1e3e { color: #5d86dd !important; }
@@ -8,7 +8,7 @@ a, ._5fpq { color: #eee !important; }
#viewport { background: #000 !important; }
-body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: #000 !important; }
+body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3bmj, ._5zmb, ._2x2s, ._3kac, ._3kad, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._5zma, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: #000 !important; }
._31nf, ._2v9s, ._d4i, article._55wo, ._10c_, ._2jl2, ._55wo, ._6150 { background: rgba(0, 0, 0, 0.35) !important; }
@@ -38,7 +38,7 @@ button ._v89 ._54k8._1fl1 { background: #5d86dd !important; }
._15ny::after, ._z-w, ._8i2, ._2nk0, ._22_8, ._1t4h, ._37fd, ._1ha, ._3bg5 ._56do, ._8he, ._400s, ._5hoc, ._1bhn, ._5ag6, ._4pvz, ._301x, ._x08 ._x0a:after, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, ._2bdc, ._3ci9, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .error, ._35--, ._1wev, .jx-result, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child { border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
-.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(255, 255, 255, 0.3) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
+.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._1ih_, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(255, 255, 255, 0.3) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, .sharerAttachment, .mToken, #addMembersTypeahead .mToken.mTokenWeakReference, .mQuestionsPollResultsBar, ._15q7, ._2q7v, ._4dwt ._16ii, ._3qdi::after, ._2q7w, .acy, ._58ak, ._3t_l, ._4msa, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._50uu, ._50uw, ._31yd, ._1e3d, ._3xz7, ._1xoz, ._4kcb, ._2lut, .jewel .touchable-notification.touched, .touchable-notification .touchable.touched, .home-notification .touchable.touched, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; }
@@ -54,7 +54,7 @@ button ._v89 ._54k8._1fl1 { background: #5d86dd !important; }
._2cis { border-left: 10px solid #000 !important; border-right: 10px solid #000 !important; }
-._2cir.selected, ._42rv { border-bottom: 3px solid #fff !important; }
+._2cir.selected, ._42rv, ._5zma, ._2x2s { border-bottom: 3px solid #fff !important; }
._1ss6 { border-left: 2px solid #fff !important; }
diff --git a/app/src/main/assets/css/themes/material_dark.css b/app/src/main/assets/css/themes/material_dark.css
index ad520709..703bb68f 100644
--- a/app/src/main/assets/css/themes/material_dark.css
+++ b/app/src/main/assets/css/themes/material_dark.css
@@ -1,4 +1,4 @@
-[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; }
+[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; }
strong > a, ._15ks ._2q8z._2q8z, ._1e3e { color: #5d86dd !important; }
@@ -8,7 +8,7 @@ a, ._5fpq { color: #eee !important; }
#viewport { background: #303030 !important; }
-body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: #303030 !important; }
+body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3bmj, ._5zmb, ._2x2s, ._3kac, ._3kad, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._5zma, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: #303030 !important; }
._31nf, ._2v9s, ._d4i, article._55wo, ._10c_, ._2jl2, ._55wo, ._6150 { background: #353535 !important; }
@@ -38,7 +38,7 @@ button ._v89 ._54k8._1fl1 { background: #5d86dd !important; }
._15ny::after, ._z-w, ._8i2, ._2nk0, ._22_8, ._1t4h, ._37fd, ._1ha, ._3bg5 ._56do, ._8he, ._400s, ._5hoc, ._1bhn, ._5ag6, ._4pvz, ._301x, ._x08 ._x0a:after, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, ._2bdc, ._3ci9, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .error, ._35--, ._1wev, .jx-result, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child { border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
-.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(255, 255, 255, 0.3) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
+.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._1ih_, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(255, 255, 255, 0.3) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, .sharerAttachment, .mToken, #addMembersTypeahead .mToken.mTokenWeakReference, .mQuestionsPollResultsBar, ._15q7, ._2q7v, ._4dwt ._16ii, ._3qdi::after, ._2q7w, .acy, ._58ak, ._3t_l, ._4msa, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._50uu, ._50uw, ._31yd, ._1e3d, ._3xz7, ._1xoz, ._4kcb, ._2lut, .jewel .touchable-notification.touched, .touchable-notification .touchable.touched, .home-notification .touchable.touched, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; }
@@ -54,7 +54,7 @@ button ._v89 ._54k8._1fl1 { background: #5d86dd !important; }
._2cis { border-left: 10px solid #303030 !important; border-right: 10px solid #303030 !important; }
-._2cir.selected, ._42rv { border-bottom: 3px solid #fff !important; }
+._2cir.selected, ._42rv, ._5zma, ._2x2s { border-bottom: 3px solid #fff !important; }
._1ss6 { border-left: 2px solid #fff !important; }
diff --git a/app/src/main/assets/css/themes/material_glass.css b/app/src/main/assets/css/themes/material_glass.css
index c5e093e6..61575a9c 100644
--- a/app/src/main/assets/css/themes/material_glass.css
+++ b/app/src/main/assets/css/themes/material_glass.css
@@ -1,4 +1,4 @@
-[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; }
+[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #fff !important; }
strong > a, ._15ks ._2q8z._2q8z, ._1e3e { color: #5d86dd !important; }
@@ -8,7 +8,7 @@ a, ._5fpq { color: #eee !important; }
#viewport { background: rgba(0, 0, 0, 0.1) !important; }
-body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: transparent !important; }
+body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3bmj, ._5zmb, ._2x2s, ._3kac, ._3kad, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._5zma, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: transparent !important; }
._31nf, ._2v9s, ._d4i, article._55wo, ._10c_, ._2jl2, ._55wo, ._6150 { background: rgba(0, 0, 0, 0.25) !important; }
@@ -38,7 +38,7 @@ button ._v89 ._54k8._1fl1 { background: #5d86dd !important; }
._15ny::after, ._z-w, ._8i2, ._2nk0, ._22_8, ._1t4h, ._37fd, ._1ha, ._3bg5 ._56do, ._8he, ._400s, ._5hoc, ._1bhn, ._5ag6, ._4pvz, ._301x, ._x08 ._x0a:after, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, ._2bdc, ._3ci9, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .error, ._35--, ._1wev, .jx-result, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child { border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
-.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(255, 255, 255, 0.3) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
+.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._1ih_, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(255, 255, 255, 0.3) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important; }
._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, .sharerAttachment, .mToken, #addMembersTypeahead .mToken.mTokenWeakReference, .mQuestionsPollResultsBar, ._15q7, ._2q7v, ._4dwt ._16ii, ._3qdi::after, ._2q7w, .acy, ._58ak, ._3t_l, ._4msa, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._50uu, ._50uw, ._31yd, ._1e3d, ._3xz7, ._1xoz, ._4kcb, ._2lut, .jewel .touchable-notification.touched, .touchable-notification .touchable.touched, .home-notification .touchable.touched, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(255, 255, 255, 0.3) !important; }
@@ -54,7 +54,7 @@ button ._v89 ._54k8._1fl1 { background: #5d86dd !important; }
._2cis { border-left: 10px solid transparent !important; border-right: 10px solid transparent !important; }
-._2cir.selected, ._42rv { border-bottom: 3px solid #fff !important; }
+._2cir.selected, ._42rv, ._5zma, ._2x2s { border-bottom: 3px solid #fff !important; }
._1ss6 { border-left: 2px solid #fff !important; }
diff --git a/app/src/main/assets/css/themes/material_light.css b/app/src/main/assets/css/themes/material_light.css
index 750ae5e1..f5d48dcf 100644
--- a/app/src/main/assets/css/themes/material_light.css
+++ b/app/src/main/assets/css/themes/material_light.css
@@ -1,4 +1,4 @@
-[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #000 !important; }
+[style*="color"], body, input, ._42rv, ._4qau, ._dwm .descArea, ._eu5, ._1tcc, ._3g9-, ._29z_, ._3xz7, ._ib-, ._3bg5 ._56dq, ._477i, ._2vxk, .touched *, ._1_yj, ._1_yl, ._4pj9, ._2bdc, ._3qdh ._3qdn ._3qdk, ._3qdk ._48_q, ._z-z, ._z-v, ._1e8d, ._36nl, ._36nm, ._2_11, ._2_rf, ._2ip_, ._403p, ._5xu2, ._3ml8, ._3mla, ._50vk, ._1m2u, ._31y7, ._4kcb, ._1lf6, ._1lf5, ._1lf4, ._1hiz, ._xod, ._5ag5, ._zmk, ._3t_h, ._5lm6, ._43mh, .touch .btn, p, span, .fcg, button, ._52j9, ._52jb, ._52ja, ._5j35, ._rnk, ._24u0, ._1g06, ._14ye, .fcb, ._56cz._56c_, ._1gk_, ._55fj, ._45fu, ._18qg, ._1_ac, ._529p, ._4dwt ._1vh3, ._4a5f, ._23_t, ._2rzc, ._23_s, ._2rzd, ._5aga, ._5ag9, ._537a, .acy, ._5ro_, ._6-l ._2us7, ._4mp, ._2b08, ._14v5 ._14v8, ._1440, ._1442, ._1448, ._4ks_, .mCount, ._27vc, ._24e1, ._2rbw, textarea, ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._5780, ._5781, ._5782, ._3u9u, ._3u9_, ._3u9s, ._1hcx, ._2066, ._1_-1, ._cv_, ._1nbx, ._2cuh, ._4ms9, ._4ms5, ._4ms6, ._31b4, ._31b5, ._5q_r, ._idb, ._27vp, ._4nwe, ._4nw9, ._27vi, .appCenterAppInfo, .appCenterPermissions, ._3c9l, ._3c9m, ._4jn_, ._32qt, ._3mom, ._3moo, ._-7o, ._d00, ._d01, ._559g, ._2new, .appCenterCategorySelectorButton, div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad, .mentions-input, .mentions-placeholder, .largeStatusBox .placeHolder, .fcw, ._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4, ._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs, h1, h2, h3, h4, h5, h6 { color: #000 !important; }
strong > a, ._15ks ._2q8z._2q8z, ._1e3e { color: #3b5998 !important; }
@@ -8,7 +8,7 @@ a, ._5fpq { color: #111 !important; }
#viewport { background: #fafafa !important; }
-body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: #fafafa !important; }
+body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9, ._5pz4, ._5lp4, ._5lp5, .container, .subpage, ._5n_f, #static_templates, ._22_8, ._1t4h, ._uoq, ._3qdh, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._4pvz, ._1g05, .acy, ._51-g, ._533c, ._ib-, .sharerAttachmentEmpty, .sharerBottomWrapper, ._24e1, ._3bg5 ._56do, ._5hfh, ._52e-, .mQuestionsPollResultsBar, ._5hoc, ._5oxw, ._32_4, ._1hiz, .tlBody, #timelineBody, .timelineX, .timeline, .feed, .tlPrelude, .tlFeedPlaceholder, ._4_d0, .al, ._1gkq, ._5c5b, ._1qxg, ._5luf, ._2new, ._cld, ._3zvb, ._2nk0, .btnD, .btnI, ._2bdb, ._3ci9, ._11ub, ._5p7j, ._55wm, ._5rgs, ._5xuj, ._1sv1, ._45fu, ._18qg, ._1_ac, ._5w3g, ._3e18, ._5q_r, ._5yt8, ._idb, ._2ip_, ._f6s, ._2l5v, ._8i2, ._kr5, ._2q7u, ._2q7v, ._5xp2, div.fullwidthMore, ._577z, ._2u4w, ._3u9p, ._3u9t, ._cw4, ._5_y-, ._5_y_, ._5_z3, ._cwy, ._5_z0, ._voz, ._vos, ._5_z1, ._5_z2, ._2mtc, ._206a, ._1_-1, ._1ybg, .appCenterCategorySelectorButton, ._5_ee, ._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5, ._55wm, ._2om3, ._2ol-, ._1f9d, ._vee, ._31a-, ._3r8b, ._3r9d, ._5vq5, ._3tl8, ._65wz, ._4edl, .acw, ._4_xl, ._1p70, ._1p70, ._1ih_, ._51v6, ._u2c, ._484w, ._3ils, ._rm7, ._32qk, ._d01, ._2y60, ._5fu3, ._2foa, ._2y5_, ._38o9, ._1kb, .mAppCenterFatLabel, ._3bmj, ._5zmb, ._2x2s, ._3kac, ._3kad, ._3f50, .mentions-placeholder, .mentions, .mentions-shadow, .mentions-measurer, .acg, ._59tu, ._4l9b, ._4gj3, .groupChromeView, ._i3g, ._3jcf, .error, ._1dbp, ._5zma, ._uww, textarea, ._15n_, ._skt, ._5f28, ._14_j, ._3bg5, ._53_-, ._52x1, ._35au, ._cwy, ._1rfn ._1rfk ._4vc-, ._1rfk, ._1rfk ._2v9s, ._301x { background: #fafafa !important; }
._31nf, ._2v9s, ._d4i, article._55wo, ._10c_, ._2jl2, ._55wo, ._6150 { background: #fff !important; }
@@ -38,7 +38,7 @@ button ._v89 ._54k8._1fl1 { background: #3b5998 !important; }
._15ny::after, ._z-w, ._8i2, ._2nk0, ._22_8, ._1t4h, ._37fd, ._1ha, ._3bg5 ._56do, ._8he, ._400s, ._5hoc, ._1bhn, ._5ag6, ._4pvz, ._301x, ._x08 ._x0a:after, ._577z:not(:last-child) ._ygd, ._3u9u, ._3mgz, ._52x6, ._2066, ._5luf, ._2bdc, ._3ci9, .mAppCenterFatLabel, .appCenterCategorySelectorButton, ._1q6v, ._5q_r, ._5yt8, ._ap1, ._52x1, ._59tu, ._usq, ._13e_, ._59f6._55so::before, ._4gj3, .error, ._35--, ._1wev, .jx-result, ._1f9d, ._vef, ._55x2 > *, .al, ._44qk, ._5rgs, ._5xuj, ._1sv1, ._idb, ._5lp5, ._3-2-, ._3to6, ._ir5, ._4nw6, ._4nwh, ._27ve, div._51v6::before, ._3c9h::before, ._2s20, ._gui, ._5jku, ._2foa, ._2y60, ._5fu3, ._4en9, ._1kb:not(:last-child) ._1kc, ._5pz4, ._5lp4, ._5lp5, ._5h6z, ._5h6x, ._2om4, ._5fjw > div, ._5fjv > :first-child, ._5fjw > :first-child { border-bottom: 1px solid rgba(0, 0, 0, 0.3) !important; }
-.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(0, 0, 0, 0.3) !important; border-bottom: 1px solid rgba(0, 0, 0, 0.3) !important; }
+.item a.primary.touched .primarywrap, ._4dwt ._5y33, ._1ih_, ._5fjv, ._3on6, ._2u4w, ._2om3, ._2ol-, ._5fjw, ._4z83, ._1gkq { border-top: 1px solid rgba(0, 0, 0, 0.3) !important; border-bottom: 1px solid rgba(0, 0, 0, 0.3) !important; }
._d4i, ._f6s, .mentions-suggest-item, .mentions-suggest, .sharerAttachment, .mToken, #addMembersTypeahead .mToken.mTokenWeakReference, .mQuestionsPollResultsBar, ._15q7, ._2q7v, ._4dwt ._16ii, ._3qdi::after, ._2q7w, .acy, ._58ak, ._3t_l, ._4msa, ._1_y5, ._lr0, ._5hgt, ._2cpp, ._50uu, ._50uw, ._31yd, ._1e3d, ._3xz7, ._1xoz, ._4kcb, ._2lut, .jewel .touchable-notification.touched, .touchable-notification .touchable.touched, .home-notification .touchable.touched, ._4e8n, ._uww, .mentions-placeholder, .mentions-shadow, .mentions-measurer, ._5whq, ._59tt, ._41ft::after, .jx-tokenizer, ._3uqf, ._4756, ._1rrd, ._5n_f { border: 1px solid rgba(0, 0, 0, 0.3) !important; }
@@ -54,7 +54,7 @@ button ._v89 ._54k8._1fl1 { background: #3b5998 !important; }
._2cis { border-left: 10px solid #fafafa !important; border-right: 10px solid #fafafa !important; }
-._2cir.selected, ._42rv { border-bottom: 3px solid #000 !important; }
+._2cir.selected, ._42rv, ._5zma, ._2x2s { border-bottom: 3px solid #000 !important; }
._1ss6 { border-left: 2px solid #000 !important; }
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
index bb9c45c0..36b51753 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
@@ -77,10 +77,10 @@ class FrostApp : Application() {
super.onCreate()
- applicationContext.scheduleNotifications(Prefs.notificationFreq)
-
setupNotificationChannels(applicationContext)
+ applicationContext.scheduleNotifications(Prefs.notificationFreq)
+
/**
* Drawer profile loading logic
* Reload the image on every version update
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
index 8000c106..d9edda78 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
@@ -30,7 +30,6 @@ class WebFragment : BaseFragment() {
}
override fun updateFab(contract: MainFabContract) {
- L.e { "Update fab" }
val web = core as? WebView
if (web == null) {
L.e { "Webview not found in fragment $baseEnum" }
@@ -40,7 +39,6 @@ class WebFragment : BaseFragment() {
contract.showFab(GoogleMaterial.Icon.gmd_edit) {
JsActions.CREATE_POST.inject(web)
}
- L.e { "UPP" }
return
}
super.updateFab(contract)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt
deleted file mode 100644
index 25f10398..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.pitchedapps.frost.services
-
-import android.annotation.SuppressLint
-import android.app.IntentService
-import android.app.Notification
-import android.app.PendingIntent
-import android.app.Service
-import android.content.Context
-import android.content.Intent
-import android.support.v4.app.NotificationCompat
-import android.support.v4.app.NotificationManagerCompat
-import ca.allanwang.kau.utils.copyFromInputStream
-import ca.allanwang.kau.utils.string
-import com.pitchedapps.frost.R
-import com.pitchedapps.frost.utils.L
-import com.pitchedapps.frost.utils.createMediaFile
-import com.pitchedapps.frost.utils.frostUriFromFile
-import okhttp3.MediaType
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.ResponseBody
-import okio.*
-import org.jetbrains.anko.toast
-import java.io.File
-
-/**
- * Created by Allan Wang on 2017-08-08.
- *
- * Not in use
- *
- * Background file downloader
- * All we are given is a link and a mime type
- *
- * With reference to the <a href="https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/Progress.java">OkHttp3 sample</a>
- */
-@SuppressLint("Registered")
-class DownloadService : IntentService("FrostVideoDownloader") {
-
- companion object {
- const val EXTRA_URL = "download_url"
- private const val MAX_PROGRESS = 1000
- private const val DOWNLOAD_GROUP = "frost_downloads"
- }
-
- val client: OkHttpClient by lazy { initClient() }
-
- val start = System.currentTimeMillis()
- var totalSize = 0L
- val downloaded = mutableSetOf<String>()
-
- private lateinit var notifBuilder: NotificationCompat.Builder
- private var notifId: Int = -1
-
- override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- if (intent != null && intent.flags == PendingIntent.FLAG_CANCEL_CURRENT) {
- L.i { "Cancelling download service" }
- cancelDownload()
- return Service.START_NOT_STICKY
- }
- return super.onStartCommand(intent, flags, startId)
- }
-
- override fun onHandleIntent(intent: Intent?) {
- val url: String = intent?.getStringExtra(EXTRA_URL) ?: return
-
- if (downloaded.contains(url)) return
-
- val request: Request = Request.Builder()
- .url(url)
- .build()
-
- notifBuilder = frostNotification
- notifId = Math.abs(url.hashCode() + System.currentTimeMillis().toInt())
- val cancelIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
-
- notifBuilder.setContentTitle(string(R.string.downloading_video))
- .setCategory(Notification.CATEGORY_PROGRESS)
- .setWhen(System.currentTimeMillis())
- .setProgress(MAX_PROGRESS, 0, false)
- .setOngoing(true)
- .addAction(R.drawable.ic_action_cancel, string(R.string.kau_cancel), cancelIntent)
- .setGroup(DOWNLOAD_GROUP)
-
- client.newCall(request).execute().use { response ->
- if (!response.isSuccessful) {
- L.e { "Video download failed" }
- toast("Video download failed")
- return@use
- }
-
- val stream = response.body()?.byteStream() ?: return@use
- val extension = response.request().body()?.contentType()?.subtype()
- val destination = createMediaFile(if (extension == null) "" else ".$extension")
- destination.copyFromInputStream(stream)
-
- notifBuilder.setContentIntent(getPendingIntent(this, destination))
- notifBuilder.show()
- }
- }
-
- private fun NotificationCompat.Builder.show() {
- NotificationManagerCompat.from(this@DownloadService).notify(DOWNLOAD_GROUP, notifId, build())
- }
-
-
- private fun getPendingIntent(context: Context, file: File): PendingIntent {
- val uri = context.frostUriFromFile(file)
- val type = context.contentResolver.getType(uri)
- L.i { "DownloadType: retrieved pending intent" }
- L._i { "Contents: $uri $type" }
- val intent = Intent(Intent.ACTION_VIEW, uri)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
- .setDataAndType(uri, type)
- return PendingIntent.getActivity(context, 0, intent, 0)
- }
-
- /**
- * Adds url to downloaded list and modifies the notif builder for the finished state
- * Does not show the new notification
- */
- private fun finishDownload(url: String) {
- L.i { "Video download finished" }
- downloaded.add(url)
- notifBuilder.setContentTitle(string(R.string.downloaded_video))
- .setProgress(0, 0, false).setOngoing(false).setAutoCancel(true)
- .apply { mActions.clear() }
- }
-
- private fun cancelDownload() {
- client.dispatcher().cancelAll()
- NotificationManagerCompat.from(this).cancel(DOWNLOAD_GROUP, notifId)
- }
-
- private fun onProgressUpdate(url: String, type: MediaType?, percentage: Float, done: Boolean) {
- L.v { "Download request progress $percentage for $url" }
- notifBuilder.setProgress(MAX_PROGRESS, (percentage * MAX_PROGRESS).toInt(), false)
- if (done) finishDownload(url)
- notifBuilder.show()
- }
-
- override fun onTaskRemoved(rootIntent: Intent?) {
- super.onTaskRemoved(rootIntent)
- }
-
- private fun initClient(): OkHttpClient = OkHttpClient.Builder()
- .addNetworkInterceptor { chain ->
- val original = chain.proceed(chain.request())
- val body = original.body() ?: return@addNetworkInterceptor original
- if (body.contentLength() > 0L) totalSize += body.contentLength()
- return@addNetworkInterceptor original.newBuilder()
- .body(ProgressResponseBody(
- original.request().url().toString(),
- body,
- this@DownloadService::onProgressUpdate))
- .build()
- }
- .build()
-
- private class ProgressResponseBody(
- val url: String,
- val responseBody: ResponseBody,
- val listener: (url: String, type: MediaType?, percentage: Float, done: Boolean) -> Unit) : ResponseBody() {
-
- private val bufferedSource: BufferedSource by lazy { Okio.buffer(source(responseBody.source())) }
-
- override fun contentLength(): Long = responseBody.contentLength()
-
- override fun contentType(): MediaType? = responseBody.contentType()
-
- override fun source(): BufferedSource = bufferedSource
-
- private fun source(source: Source): Source = object : ForwardingSource(source) {
-
- private var totalBytesRead = 0L
-
- override fun read(sink: Buffer, byteCount: Long): Long {
- val bytesRead = super.read(sink, byteCount)
- // read() returns the number of bytes read, or -1 if this source is exhausted.
- totalBytesRead += if (bytesRead != -1L) bytesRead else 0
- listener(
- url,
- contentType(),
- totalBytesRead.toFloat() / responseBody.contentLength(),
- bytesRead == -1L
- )
- return bytesRead
- }
- }
- }
-} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
index 08cf321c..b6427e5b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
@@ -1,5 +1,6 @@
package com.pitchedapps.frost.services
+import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
@@ -13,12 +14,13 @@ import android.net.Uri
import android.os.BaseBundle
import android.os.Build
import android.os.Bundle
+import android.os.PersistableBundle
+import android.support.annotation.RequiresApi
import android.support.v4.app.NotificationCompat
import android.support.v4.app.NotificationManagerCompat
import ca.allanwang.kau.utils.color
import ca.allanwang.kau.utils.dpToPx
import ca.allanwang.kau.utils.string
-import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.R
import com.pitchedapps.frost.activities.FrostWebActivity
import com.pitchedapps.frost.dbflow.CookieModel
@@ -43,32 +45,66 @@ import java.util.*
*
* Logic for build notifications, scheduling notifications, and showing notifications
*/
+const val NOTIF_CHANNEL_GENERAL = "general"
+const val NOTIF_CHANNEL_MESSAGES = "messages"
+
fun setupNotificationChannels(c: Context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
val manager = c.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
- val mainChannel = NotificationChannel(BuildConfig.APPLICATION_ID, c.getString(R.string.frost_name), NotificationManager.IMPORTANCE_DEFAULT)
- mainChannel.lightColor = c.color(R.color.facebook_blue)
- mainChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
- manager.createNotificationChannel(mainChannel)
+ val appName = c.string(R.string.frost_name)
+ val msg = c.string(R.string.messages)
+ manager.notificationChannels
+ .filter { it.id != NOTIF_CHANNEL_GENERAL && it.id != NOTIF_CHANNEL_MESSAGES }
+ .forEach { manager.deleteNotificationChannel(it.id) }
+ manager.createNotificationChannel(NOTIF_CHANNEL_GENERAL, appName)
+ manager.createNotificationChannel(NOTIF_CHANNEL_MESSAGES, "$appName: $msg")
+ L.d { "Created notification channels: ${manager.notificationChannels.size} channels, ${manager.notificationChannelGroups.size} groups" }
}
-inline val Context.frostNotification: NotificationCompat.Builder
- get() = NotificationCompat.Builder(this, BuildConfig.APPLICATION_ID).apply {
- setSmallIcon(R.drawable.frost_f_24)
- setAutoCancel(true)
- setStyle(NotificationCompat.BigTextStyle())
- color = color(R.color.frost_notification_accent)
- }
+@RequiresApi(Build.VERSION_CODES.O)
+private fun NotificationManager.createNotificationChannel(id: String, name: String): NotificationChannel {
+ val channel = NotificationChannel(id,
+ name, NotificationManager.IMPORTANCE_DEFAULT)
+ channel.enableLights(true)
+ channel.lightColor = Prefs.accentColor
+ channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
+ createNotificationChannel(channel)
+ return channel
+}
-fun NotificationCompat.Builder.withDefaults(ringtone: String = Prefs.notificationRingtone) = apply {
- var defaults = 0
- if (Prefs.notificationVibrate) defaults = defaults or Notification.DEFAULT_VIBRATE
- if (Prefs.notificationSound) {
- if (ringtone.isNotBlank()) setSound(Uri.parse(ringtone))
- else defaults = defaults or Notification.DEFAULT_SOUND
+fun Context.frostNotification(id: String) =
+ NotificationCompat.Builder(this, id)
+ .apply {
+ setSmallIcon(R.drawable.frost_f_24)
+ setAutoCancel(true)
+ setOnlyAlertOnce(true)
+ setStyle(NotificationCompat.BigTextStyle())
+ color = color(R.color.frost_notification_accent)
+ }
+
+/**
+ * Dictates whether a notification should have sound/vibration/lights or not
+ * Delegates to channels if Android O and up
+ * Otherwise uses our provided preferences
+ */
+fun NotificationCompat.Builder.setFrostAlert(enable: Boolean, ringtone: String): NotificationCompat.Builder {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ setGroupAlertBehavior(
+ if (enable) Notification.GROUP_ALERT_CHILDREN
+ else Notification.GROUP_ALERT_SUMMARY)
+ } else if (!enable) {
+ setDefaults(0)
+ } else {
+ var defaults = 0
+ if (Prefs.notificationVibrate) defaults = defaults or Notification.DEFAULT_VIBRATE
+ if (Prefs.notificationSound) {
+ if (ringtone.isNotBlank()) setSound(Uri.parse(ringtone))
+ else defaults = defaults or Notification.DEFAULT_SOUND
+ }
+ if (Prefs.notificationLights) defaults = defaults or Notification.DEFAULT_LIGHTS
+ setDefaults(defaults)
}
- if (Prefs.notificationLights) defaults = defaults or Notification.DEFAULT_LIGHTS
- setDefaults(defaults)
+ return this
}
private val _40_DP = 40.dpToPx
@@ -77,6 +113,7 @@ private val _40_DP = 40.dpToPx
* Enum to handle notification creations
*/
enum class NotificationType(
+ private val channelId: String,
private val overlayContext: OverlayContext,
private val fbItem: FbItem,
private val parser: FrostParser<ParseNotification>,
@@ -84,7 +121,8 @@ enum class NotificationType(
private val putTime: (notif: NotificationModel, time: Long) -> NotificationModel,
private val ringtone: () -> String) {
- GENERAL(OverlayContext.NOTIFICATION,
+ GENERAL(NOTIF_CHANNEL_GENERAL,
+ OverlayContext.NOTIFICATION,
FbItem.NOTIFICATIONS,
NotifParser,
NotificationModel::epoch,
@@ -95,7 +133,8 @@ enum class NotificationType(
FrostRunnable.prepareMarkNotificationRead(content.id, cookie)
},
- MESSAGE(OverlayContext.MESSAGE,
+ MESSAGE(NOTIF_CHANNEL_MESSAGES,
+ OverlayContext.MESSAGE,
FbItem.MESSAGES,
MessageParser,
NotificationModel::epochIm,
@@ -121,36 +160,48 @@ enum class NotificationType(
* Get unread data from designated parser
* Display notifications for those after old epoch
* Save new epoch
+ *
+ * Returns the number of notifications generated,
+ * or -1 if an error occurred
*/
- fun fetch(context: Context, data: CookieModel) {
+ fun fetch(context: Context, data: CookieModel): Int {
val response = parser.parse(data.cookie)
- ?: return L.v { "$name notification data not found" }
- val notifs = response.data.getUnreadNotifications(data).filter {
+ if (response == null) {
+ L.v { "$name notification data not found" }
+ return -1
+ }
+ val notifContents = response.data.getUnreadNotifications(data).filter {
val text = it.text
Prefs.notificationKeywords.none { text.contains(it, true) }
}
- if (notifs.isEmpty()) return
- var notifCount = 0
+ if (notifContents.isEmpty()) return 0
val userId = data.id
val prevNotifTime = lastNotificationTime(userId)
val prevLatestEpoch = getTime(prevNotifTime)
L.v { "Notif $name prev epoch $prevLatestEpoch" }
var newLatestEpoch = prevLatestEpoch
- notifs.forEach { notif ->
+ val notifs = mutableListOf<FrostNotification>()
+ notifContents.forEach { notif ->
L.v { "Notif timestamp ${notif.timestamp}" }
if (notif.timestamp <= prevLatestEpoch) return@forEach
- createNotification(context, notif, notifCount == 0)
+ notifs.add(createNotification(context, notif))
if (notif.timestamp > newLatestEpoch)
newLatestEpoch = notif.timestamp
- notifCount++
}
if (newLatestEpoch > prevLatestEpoch)
putTime(prevNotifTime, newLatestEpoch).save()
L.d { "Notif $name new epoch ${getTime(lastNotificationTime(userId))}" }
- summaryNotification(context, userId, notifCount)
+ frostAnswersCustom("Notifications", "Type" to name, "Count" to notifs.size)
+ if (notifs.size > 1)
+ summaryNotification(context, userId, notifs.size).notify(context)
+ val ringtone = ringtone()
+ notifs.forEachIndexed { i, notif ->
+ notif.withAlert(i < 2, ringtone).notify(context)
+ }
+ return notifs.size
}
- private fun debugNotification(context: Context, data: CookieModel) {
+ fun debugNotification(context: Context, data: CookieModel) {
val content = NotificationContent(data,
System.currentTimeMillis(),
"https://github.com/AllanWang/Frost-for-Facebook",
@@ -158,15 +209,13 @@ enum class NotificationType(
"Test 123",
System.currentTimeMillis() / 1000,
"https://www.iconexperience.com/_img/v_collection_png/256x256/shadow/dog.png")
- createNotification(context, content, true)
+ createNotification(context, content).notify(context)
}
/**
* Create and submit a new notification with the given [content]
- * If [withDefaults] is set, it will also add the appropriate sound, vibration, and light
- * Note that when we have multiple notifications coming in at once, we don't want to have defaults for all of them
*/
- private fun createNotification(context: Context, content: NotificationContent, withDefaults: Boolean) {
+ private fun createNotification(context: Context, content: NotificationContent): FrostNotification {
with(content) {
val intent = Intent(context, FrostWebActivity::class.java)
intent.data = Uri.parse(href)
@@ -176,7 +225,7 @@ enum class NotificationType(
val group = "${groupPrefix}_${data.id}"
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
- val notifBuilder = context.frostNotification
+ val notifBuilder = context.frostNotification(channelId)
.setContentTitle(title ?: context.string(R.string.frost_name))
.setContentText(text)
.setContentIntent(pendingIntent)
@@ -184,9 +233,6 @@ enum class NotificationType(
.setSubText(data.name)
.setGroup(group)
- if (withDefaults)
- notifBuilder.withDefaults(ringtone())
-
if (timestamp != -1L) notifBuilder.setWhen(timestamp * 1000)
L.v { "Notif load $content" }
@@ -204,32 +250,37 @@ enum class NotificationType(
}
}
- NotificationManagerCompat.from(context).notify(group, notifId, notifBuilder.build())
+ return FrostNotification(group, notifId, notifBuilder)
}
}
+
/**
* Create a summary notification to wrap the previous ones
* This will always produce sound, vibration, and lights based on preferences
* and will only show if we have at least 2 notifications
*/
- private fun summaryNotification(context: Context, userId: Long, count: Int) {
- frostAnswersCustom("Notifications", "Type" to name, "Count" to count)
- if (count <= 1) return
+ private fun summaryNotification(context: Context, userId: Long, count: Int): FrostNotification {
val intent = Intent(context, FrostWebActivity::class.java)
intent.data = Uri.parse(fbItem.url)
intent.putExtra(ARG_USER_ID, userId)
+ val group = "${groupPrefix}_$userId"
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
- val notifBuilder = context.frostNotification.withDefaults(ringtone())
+ val notifBuilder = context.frostNotification(channelId)
.setContentTitle(context.string(R.string.frost_name))
.setContentText("$count ${context.string(fbItem.titleId)}")
- .setGroup("${groupPrefix}_$userId")
+ .setGroup(group)
.setGroupSummary(true)
.setContentIntent(pendingIntent)
.setCategory(Notification.CATEGORY_SOCIAL)
- NotificationManagerCompat.from(context).notify("${groupPrefix}_$userId", userId.toInt(), notifBuilder.build())
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ notifBuilder.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
+ }
+
+ return FrostNotification(group, 1, notifBuilder)
}
+
}
/**
@@ -247,6 +298,31 @@ data class NotificationContent(val data: CookieModel,
}
+/**
+ * Wrapper for a complete notification builder and identifier
+ * which can be immediately notified when given a [Context]
+ */
+data class FrostNotification(private val tag: String,
+ private val id: Int,
+ val notif: NotificationCompat.Builder) {
+
+ fun withAlert(enable: Boolean, ringtone: String): FrostNotification {
+ notif.setFrostAlert(enable, ringtone)
+ return this
+ }
+
+ fun notify(context: Context) =
+ NotificationManagerCompat.from(context).notify(tag, id, notif.build())
+}
+
+const val NOTIFICATION_PARAM_ID = "notif_param_id"
+
+private fun JobInfo.Builder.setExtras(id: Int): JobInfo.Builder {
+ val bundle = PersistableBundle()
+ bundle.putInt(NOTIFICATION_PARAM_ID, id)
+ return setExtras(bundle)
+}
+
const val NOTIFICATION_PERIODIC_JOB = 7
/**
@@ -260,6 +336,7 @@ fun Context.scheduleNotifications(minutes: Long): Boolean {
val serviceComponent = ComponentName(this, NotificationService::class.java)
val builder = JobInfo.Builder(NOTIFICATION_PERIODIC_JOB, serviceComponent)
.setPeriodic(minutes * 60000)
+ .setExtras(NOTIFICATION_PERIODIC_JOB)
.setPersisted(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) //TODO add options
val result = scheduler.schedule(builder.build())
@@ -280,6 +357,7 @@ fun Context.fetchNotifications(): Boolean {
val serviceComponent = ComponentName(this, NotificationService::class.java)
val builder = JobInfo.Builder(NOTIFICATION_JOB_NOW, serviceComponent)
.setMinimumLatency(0L)
+ .setExtras(NOTIFICATION_JOB_NOW)
.setOverrideDeadline(2000L)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
val result = scheduler.schedule(builder.build())
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 fc946772..6ba968e7 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
@@ -2,11 +2,11 @@ package com.pitchedapps.frost.services
import android.app.job.JobParameters
import android.app.job.JobService
-import android.content.Context
import android.support.v4.app.NotificationManagerCompat
import ca.allanwang.kau.utils.string
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.R
+import com.pitchedapps.frost.dbflow.CookieModel
import com.pitchedapps.frost.dbflow.loadFbCookiesSync
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
@@ -24,9 +24,9 @@ import java.util.concurrent.Future
*/
class NotificationService : JobService() {
- var future: Future<Unit>? = null
+ private var future: Future<Unit>? = null
- val startTime = System.currentTimeMillis()
+ private val startTime = System.currentTimeMillis()
override fun onStopJob(params: JobParameters?): Boolean {
val time = System.currentTimeMillis() - startTime
@@ -59,31 +59,51 @@ class NotificationService : JobService() {
?: return@doAsync L.eThrow("NotificationService had null weakRef to self")
val currentId = Prefs.userId
val cookies = loadFbCookiesSync()
+ val jobId = params?.extras?.getInt(NOTIFICATION_PARAM_ID, -1) ?: -1
+ var notifCount = 0
cookies.forEach {
val current = it.id == currentId
if (Prefs.notificationsGeneral
&& (current || Prefs.notificationAllAccounts))
- NotificationType.GENERAL.fetch(context, it)
+ notifCount += fetch(jobId, NotificationType.GENERAL, it)
if (Prefs.notificationsInstantMessages
&& (current || Prefs.notificationsImAllAccounts))
- NotificationType.MESSAGE.fetch(context, it)
+ notifCount += fetch(jobId, NotificationType.MESSAGE, it)
}
+
+ if (notifCount == 0 && jobId == NOTIFICATION_JOB_NOW)
+ generalNotification(665, R.string.no_new_notifications, BuildConfig.DEBUG)
+
finish(params)
}
return true
}
+ /**
+ * Implemented fetch to also notify when an error occurs
+ * Also normalized the output to return the number of notifications received
+ */
+ private fun fetch(jobId: Int, type: NotificationType, cookie: CookieModel): Int {
+ val count = type.fetch(this, cookie)
+ if (count < 0) {
+ if (jobId == NOTIFICATION_JOB_NOW)
+ generalNotification(666, R.string.error_notification, BuildConfig.DEBUG)
+ return 0
+ }
+ return count
+ }
+
private fun logNotif(text: String): NotificationContent? {
L.eThrow("NotificationService: $text")
return null
}
- private fun Context.debugNotification(text: String = string(R.string.kau_lorem_ipsum)) {
- if (!BuildConfig.DEBUG) return
- val notifBuilder = frostNotification.withDefaults()
+ private fun generalNotification(id: Int, textRes: Int, withDefaults: Boolean) {
+ val notifBuilder = frostNotification(NOTIF_CHANNEL_GENERAL)
+ .setFrostAlert(withDefaults, Prefs.notificationRingtone)
.setContentTitle(string(R.string.frost_name))
- .setContentText(text)
- NotificationManagerCompat.from(this).notify(999, notifBuilder.build())
+ .setContentText(string(textRes))
+ NotificationManagerCompat.from(this).notify(id, notifBuilder.build())
}
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt
index 2ee086c0..962e60ae 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt
@@ -1,14 +1,20 @@
package com.pitchedapps.frost.settings
+import android.annotation.SuppressLint
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
+import android.os.Build
+import android.provider.Settings
import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder
import ca.allanwang.kau.kpref.activity.items.KPrefText
import ca.allanwang.kau.utils.minuteToText
import ca.allanwang.kau.utils.string
+import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.R
import com.pitchedapps.frost.activities.SettingsActivity
+import com.pitchedapps.frost.dbflow.NotificationModel
+import com.pitchedapps.frost.dbflow.loadFbCookiesAsync
import com.pitchedapps.frost.services.fetchNotifications
import com.pitchedapps.frost.services.scheduleNotifications
import com.pitchedapps.frost.utils.Prefs
@@ -20,6 +26,7 @@ import com.pitchedapps.frost.views.Keywords
/**
* Created by Allan Wang on 2017-06-29.
*/
+@SuppressLint("InlinedApi")
fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = {
text(R.string.notification_frequency, Prefs::notificationFreq, { Prefs.notificationFreq = it }) {
@@ -90,47 +97,69 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = {
enabler = Prefs::notificationsInstantMessages
}
- checkbox(R.string.notification_sound, Prefs::notificationSound, {
- Prefs.notificationSound = it
- reloadByTitle(R.string.notification_ringtone,
- R.string.message_ringtone)
- })
-
- fun KPrefText.KPrefTextContract<String>.ringtone(code: Int) {
- enabler = Prefs::notificationSound
- textGetter = {
- if (it.isBlank()) string(R.string.kau_default)
- else RingtoneManager.getRingtone(this@getNotificationPrefs, Uri.parse(it))
- ?.getTitle(this@getNotificationPrefs) ?: "---" //todo figure out why this happens
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ plainText(R.string.notification_channel) {
+ descRes = R.string.notification_channel_desc
+ onClick = {
+ val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
+ .putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
+ startActivity(intent)
+ }
}
- onClick = {
- val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
- putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, string(R.string.select_ringtone))
- putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false)
- putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true)
- putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)
- if (item.pref.isNotBlank())
- putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(item.pref))
+ } else {
+ checkbox(R.string.notification_sound, Prefs::notificationSound, {
+ Prefs.notificationSound = it
+ reloadByTitle(R.string.notification_ringtone,
+ R.string.message_ringtone)
+ })
+
+ fun KPrefText.KPrefTextContract<String>.ringtone(code: Int) {
+ enabler = Prefs::notificationSound
+ textGetter = {
+ if (it.isBlank()) string(R.string.kau_default)
+ else RingtoneManager.getRingtone(this@getNotificationPrefs, Uri.parse(it))
+ ?.getTitle(this@getNotificationPrefs)
+ ?: "---" //todo figure out why this happens
+ }
+ onClick = {
+ val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
+ putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, string(R.string.select_ringtone))
+ putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false)
+ putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true)
+ putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)
+ if (item.pref.isNotBlank())
+ putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(item.pref))
+ }
+ startActivityForResult(intent, code)
}
- startActivityForResult(intent, code)
}
- }
- text(R.string.notification_ringtone, Prefs::notificationRingtone,
- { Prefs.notificationRingtone = it }) {
- ringtone(SettingsActivity.REQUEST_NOTIFICATION_RINGTONE)
- }
+ text(R.string.notification_ringtone, Prefs::notificationRingtone,
+ { Prefs.notificationRingtone = it }) {
+ ringtone(SettingsActivity.REQUEST_NOTIFICATION_RINGTONE)
+ }
- text(R.string.message_ringtone, Prefs::messageRingtone,
- { Prefs.messageRingtone = it }) {
- ringtone(SettingsActivity.REQUEST_MESSAGE_RINGTONE)
- }
+ text(R.string.message_ringtone, Prefs::messageRingtone,
+ { Prefs.messageRingtone = it }) {
+ ringtone(SettingsActivity.REQUEST_MESSAGE_RINGTONE)
+ }
+
+ checkbox(R.string.notification_vibrate, Prefs::notificationVibrate,
+ { Prefs.notificationVibrate = it })
- checkbox(R.string.notification_vibrate, Prefs::notificationVibrate,
- { Prefs.notificationVibrate = it })
+ checkbox(R.string.notification_lights, Prefs::notificationLights,
+ { Prefs.notificationLights = it })
+ }
- checkbox(R.string.notification_lights, Prefs::notificationLights,
- { Prefs.notificationLights = it })
+ if (BuildConfig.DEBUG) {
+ plainText(R.string.reset_notif_epoch) {
+ onClick = {
+ loadFbCookiesAsync {
+ it.map { NotificationModel(it.id) }.forEach { it.save() }
+ }
+ }
+ }
+ }
plainText(R.string.notification_fetch_now) {
descRes = R.string.notification_fetch_now_desc
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 f9f471df..6db3f83c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
@@ -41,7 +41,7 @@ object Prefs : KPref() {
var exitConfirmation: Boolean by kpref("exit_confirmation", true)
- var notificationFreq: Long by kpref("notification_freq", 60L)
+ var notificationFreq: Long by kpref("notification_freq", 15L)
var versionCode: Int by kpref("version_code", -1)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e39e91ed..16b55b79 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -59,4 +59,6 @@
<string name="options">Options</string>
<string name="tab_customizer_instructions">Long press and drag to rearrange the top icons.</string>
+ <string name="no_new_notifications">No new notifications found</string>
+
</resources>
diff --git a/app/src/main/res/values/strings_errors.xml b/app/src/main/res/values/strings_errors.xml
index cc51699a..71d147f7 100644
--- a/app/src/main/res/values/strings_errors.xml
+++ b/app/src/main/res/values/strings_errors.xml
@@ -8,4 +8,5 @@
<string name="no_download_manager_desc">The download manager is not enabled. Would you like to enable it to allow downloads?</string>
<string name="error_generic">An error occurred.</string>
<string name="video_load_failed">Failed to load video</string>
+ <string name="error_notification">An error occurred when fetching notifications</string>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/strings_no_translate.xml b/app/src/main/res/values/strings_no_translate.xml
index 13dc9f1c..17e6c8f7 100644
--- a/app/src/main/res/values/strings_no_translate.xml
+++ b/app/src/main/res/values/strings_no_translate.xml
@@ -14,4 +14,5 @@
<string name="debug_report" translatable="false">Debug Report</string>
<string name="theme_issue" translatable="false">Theme Issue</string>
<string name="feature_request" translatable="false">Feature Request</string>
+ <string name="reset_notif_epoch" translatable="false">Reset Notif Epoch</string>
</resources>
diff --git a/app/src/main/res/values/strings_pref_notifications.xml b/app/src/main/res/values/strings_pref_notifications.xml
index 8db493b8..aea7ada9 100644
--- a/app/src/main/res/values/strings_pref_notifications.xml
+++ b/app/src/main/res/values/strings_pref_notifications.xml
@@ -21,6 +21,8 @@
<string name="notification_fetch_success">Fetching Notifications…</string>
<string name="notification_fetch_fail">Couldn\'t fetch notifications</string>
<string name="notification_sound">Notification sound</string>
+ <string name="notification_channel">Customize notification channels</string>
+ <string name="notification_channel_desc">Modify sound, vibration, priority, etc</string>
<string name="notification_ringtone">Notification Ringtone</string>
<string name="message_ringtone">Message Ringtone</string>
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt
index 63c11bac..9fbb6069 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt
@@ -14,7 +14,8 @@ class OfflineWebsiteTest {
@Test
fun basic() {
val countdown = CountDownLatch(1)
- OfflineWebsite(FB_URL_BASE, COOKIE, File("app/build/offline_test"))
+ val buildPath = if (File(".").parentFile?.name == "app") "build/offline_test" else "app/build/offline_test"
+ OfflineWebsite(FB_URL_BASE, COOKIE, File(buildPath))
.loadAndZip("test") {
println("Outcome $it")
countdown.countDown()