aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2018-02-02 21:05:26 -0500
committerGitHub <noreply@github.com>2018-02-02 21:05:26 -0500
commitd68ea6d7eb8cadf687308fa3204386b79df0556b (patch)
tree0797c5c53e09b6af5eb996ab42e1f814ee615561 /app
parentf36e0fff23abb5c892b40d1a9fb70776078976c4 (diff)
downloadfrost-d68ea6d7eb8cadf687308fa3204386b79df0556b.tar.gz
frost-d68ea6d7eb8cadf687308fa3204386b79df0556b.tar.bz2
frost-d68ea6d7eb8cadf687308fa3204386b79df0556b.zip
Feature/post (#696)v1.8.1
* Reorder final override * Add initial fab bindings * Update scripts * Optimize and use js header hider * Remove old header hider * Use method for generating clicker
Diffstat (limited to 'app')
-rw-r--r--app/src/main/assets/css/core/_core_bg.scss2
-rw-r--r--app/src/main/assets/css/core/core.css2
-rw-r--r--app/src/main/assets/css/themes/custom.css2
-rw-r--r--app/src/main/assets/css/themes/material_amoled.css2
-rw-r--r--app/src/main/assets/css/themes/material_dark.css2
-rw-r--r--app/src/main/assets/css/themes/material_glass.css2
-rw-r--r--app/src/main/assets/css/themes/material_light.css2
-rw-r--r--app/src/main/assets/js/header_hider.coffee11
-rw-r--r--app/src/main/assets/js/header_hider.js19
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt50
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt8
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt24
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt8
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt21
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt9
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/EnumUtils.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt3
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt20
-rw-r--r--app/src/main/res/layout/view_main_fab.xml3
-rw-r--r--app/src/main/res/xml/frost_changelog.xml7
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/MiscTest.kt5
29 files changed, 188 insertions, 56 deletions
diff --git a/app/src/main/assets/css/core/_core_bg.scss b/app/src/main/assets/css/core/_core_bg.scss
index f26e585b..82d1442e 100644
--- a/app/src/main/assets/css/core/_core_bg.scss
+++ b/app/src/main/assets/css/core/_core_bg.scss
@@ -10,7 +10,7 @@ body, #root, #header, [style*="background-color"], ._1upc, input, ._2f9r, ._59e9
.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,
+._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,
._5c9u, div._5y57::before, ._59f6._55so::before, .structuredPublisher, ._94v, ._vqv, ._5lp5,
diff --git a/app/src/main/assets/css/core/core.css b/app/src/main/assets/css/core/core.css
index 4a6acd6c..59830a56 100644
--- a/app/src/main/assets/css/core/core.css
+++ b/app/src/main/assets/css/core/core.css
@@ -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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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, ._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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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; }
diff --git a/app/src/main/assets/css/themes/custom.css b/app/src/main/assets/css/themes/custom.css
index 37db1d41..9cc32650 100644
--- a/app/src/main/assets/css/themes/custom.css
+++ b/app/src/main/assets/css/themes/custom.css
@@ -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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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, ._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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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; }
diff --git a/app/src/main/assets/css/themes/material_amoled.css b/app/src/main/assets/css/themes/material_amoled.css
index 450e877b..1e9a494e 100644
--- a/app/src/main/assets/css/themes/material_amoled.css
+++ b/app/src/main/assets/css/themes/material_amoled.css
@@ -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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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, ._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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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; }
diff --git a/app/src/main/assets/css/themes/material_dark.css b/app/src/main/assets/css/themes/material_dark.css
index a3268b9e..364cf137 100644
--- a/app/src/main/assets/css/themes/material_dark.css
+++ b/app/src/main/assets/css/themes/material_dark.css
@@ -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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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, ._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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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; }
diff --git a/app/src/main/assets/css/themes/material_glass.css b/app/src/main/assets/css/themes/material_glass.css
index be12b099..749cd7c6 100644
--- a/app/src/main/assets/css/themes/material_glass.css
+++ b/app/src/main/assets/css/themes/material_glass.css
@@ -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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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, ._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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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; }
diff --git a/app/src/main/assets/css/themes/material_light.css b/app/src/main/assets/css/themes/material_light.css
index e61ac2d0..37561ed2 100644
--- a/app/src/main/assets/css/themes/material_light.css
+++ b/app/src/main/assets/css/themes/material_light.css
@@ -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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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, ._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, ._6-l ._2us7, ._6-l ._6-p, ._333v, div.sharerSelector, ._529j, ._305j, ._1pph, ._3t_l, ._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, ._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, ._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; }
diff --git a/app/src/main/assets/js/header_hider.coffee b/app/src/main/assets/js/header_hider.coffee
new file mode 100644
index 00000000..40510c79
--- /dev/null
+++ b/app/src/main/assets/js/header_hider.coffee
@@ -0,0 +1,11 @@
+header = document.querySelector('#header')
+
+if !header
+ return
+
+jewel = header.querySelector('#mJewelNav')
+
+if !jewel
+ return
+
+header.style.display = 'none' \ No newline at end of file
diff --git a/app/src/main/assets/js/header_hider.js b/app/src/main/assets/js/header_hider.js
new file mode 100644
index 00000000..f29887ee
--- /dev/null
+++ b/app/src/main/assets/js/header_hider.js
@@ -0,0 +1,19 @@
+'use strict';
+
+(function () {
+ var header, jewel;
+
+ header = document.querySelector('#header');
+
+ if (!header) {
+ return;
+ }
+
+ jewel = header.querySelector('#mJewelNav');
+
+ if (!jewel) {
+ return;
+ }
+
+ header.style.display = 'none';
+}).call(undefined); \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
index c5e1fbce..267a07a2 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
@@ -17,7 +17,7 @@ abstract class BaseActivity : KauBaseActivity() {
*/
protected open fun backConsumer(): Boolean = false
- override final fun onBackPressed() {
+ final override fun onBackPressed() {
if (this is SearchViewHolder && searchViewOnBackPress()) return
if (this is VideoViewHolder && videoOnBackPress()) return
if (backConsumer()) return
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
index 743ac474..54fa0b8c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
@@ -6,6 +6,7 @@ import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
+import android.content.res.ColorStateList
import android.graphics.PointF
import android.graphics.drawable.ColorDrawable
import android.net.Uri
@@ -40,6 +41,7 @@ import co.zsmb.materialdrawerkt.draweritems.profile.profileSetting
import com.crashlytics.android.answers.ContentViewEvent
import com.mikepenz.google_material_typeface_library.GoogleMaterial
import com.mikepenz.iconics.IconicsDrawable
+import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.materialdrawer.AccountHeader
import com.mikepenz.materialdrawer.Drawer
import com.pitchedapps.frost.BuildConfig
@@ -94,7 +96,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
private val searchViewCache = mutableMapOf<String, List<SearchItem>>()
private var controlWebview: WebView? = null
- override final fun onCreate(savedInstanceState: Bundle?) {
+ final override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val start = System.currentTimeMillis()
setFrameContentView(Prefs.mainActivityLayout.layoutRes)
@@ -104,13 +106,10 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
header(appBar)
background(viewPager)
}
- L.i { "Main AAA ${System.currentTimeMillis() - start} ms" }
setSupportActionBar(toolbar)
adapter = SectionsPagerAdapter(loadFbTabs())
viewPager.adapter = adapter
viewPager.offscreenPageLimit = TAB_COUNT
- L.i { "Main BBB ${System.currentTimeMillis() - start} ms" }
- L.i { "Main CCC ${System.currentTimeMillis() - start} ms" }
tabs.setBackgroundColor(Prefs.mainActivityLayout.backgroundColor())
onNestedCreate(savedInstanceState)
L.i { "Main finished loading UI in ${System.currentTimeMillis() - start} ms" }
@@ -131,6 +130,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
}
setupDrawer(savedInstanceState)
L.i { "Main started in ${System.currentTimeMillis() - start} ms" }
+ initFab()
}
/**
@@ -138,6 +138,45 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
*/
protected abstract fun onNestedCreate(savedInstanceState: Bundle?)
+ private var hasFab = false
+ private var shouldShow = false
+
+ private fun initFab() {
+ hasFab = false
+ shouldShow = false
+ fab.backgroundTintList = ColorStateList.valueOf(Prefs.headerColor.withMinAlpha(200))
+ fab.hide()
+ appBar.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
+ if (!hasFab) return@addOnOffsetChangedListener
+ val percent = Math.abs(verticalOffset.toFloat() / appBarLayout.totalScrollRange)
+ val shouldShow = percent < 0.2
+ if (this.shouldShow != shouldShow) {
+ this.shouldShow = shouldShow
+ fab.showIf(shouldShow)
+ }
+ }
+ }
+
+ override fun showFab(iicon: IIcon, clickEvent: () -> Unit) {
+ hasFab = true
+ fab.setOnClickListener { clickEvent() }
+ if (shouldShow) {
+ if (fab.isShown) {
+ fab.fadeScaleTransition {
+ setIcon(iicon, Prefs.iconColor)
+ }
+ return
+ }
+ }
+ fab.setIcon(iicon, Prefs.iconColor)
+ fab.showIf(shouldShow)
+ }
+
+ override fun hideFab() {
+ hasFab = false
+ fab.setOnClickListener(null)
+ fab.hide()
+ }
fun tabsForEachView(action: (position: Int, view: BadgedIcon) -> Unit) {
(0 until tabs.tabCount).asSequence().forEach { i ->
@@ -195,7 +234,8 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
} else {
materialDialogThemed {
title(R.string.kau_logout)
- content(String.format(string(R.string.kau_logout_confirm_as_x), currentCookie.name ?: Prefs.userId.toString()))
+ content(String.format(string(R.string.kau_logout_confirm_as_x), currentCookie.name
+ ?: Prefs.userId.toString()))
positiveText(R.string.kau_yes)
negativeText(R.string.kau_no)
onPositive { _, _ -> FbCookie.logout(this@BaseMainActivity) }
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt b/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt
index 559c2d0f..7dce6c6e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt
@@ -1,5 +1,6 @@
package com.pitchedapps.frost.contracts
+import com.mikepenz.iconics.typeface.IIcon
import com.pitchedapps.frost.fragments.BaseFragment
import io.reactivex.subjects.PublishSubject
@@ -8,10 +9,15 @@ import io.reactivex.subjects.PublishSubject
*/
interface ActivityContract : FileChooserActivityContract
-interface MainActivityContract : ActivityContract {
+interface MainActivityContract : ActivityContract, MainFabContract {
val fragmentSubject: PublishSubject<Int>
fun setTitle(res: Int)
fun setTitle(text: CharSequence)
fun collapseAppBar()
fun reloadFragment(fragment: BaseFragment)
+}
+
+interface MainFabContract {
+ fun showFab(iicon: IIcon, clickEvent: () -> Unit)
+ fun hideFab()
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt
index 462fae79..a02cbe59 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt
@@ -45,6 +45,12 @@ enum class FbItem(
val url = "$FB_URL_BASE$relativeUrl"
+ val isFeed: Boolean
+ get() = when (this) {
+ FEED, FEED_MOST_RECENT, FEED_TOP_STORIES -> true
+ else -> false
+ }
+
override val bundleContract: EnumBundleCompanion<FbItem>
get() = Companion
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt
index 0aaeaa6d..b77847de 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt
@@ -2,14 +2,19 @@ package com.pitchedapps.frost.fragments
import android.content.Context
import android.os.Bundle
+import android.support.design.widget.FloatingActionButton
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import ca.allanwang.kau.utils.fadeScaleTransition
+import ca.allanwang.kau.utils.setIcon
import ca.allanwang.kau.utils.withArguments
+import com.mikepenz.iconics.typeface.IIcon
import com.pitchedapps.frost.contracts.DynamicUiContract
import com.pitchedapps.frost.contracts.FrostContentParent
import com.pitchedapps.frost.contracts.MainActivityContract
+import com.pitchedapps.frost.contracts.MainFabContract
import com.pitchedapps.frost.enums.FeedSort
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.utils.*
@@ -70,7 +75,7 @@ abstract class BaseFragment : Fragment(), FragmentContract, DynamicUiContract {
throw IllegalArgumentException("${this::class.java.simpleName} is not attached to a context implementing MainActivityContract")
}
- override final fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ final override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(layoutRes, container, false)
val content = view as? FrostContentParent
?: throw IllegalArgumentException("layoutRes for fragment must return view implementing FrostContentParent")
@@ -118,6 +123,7 @@ abstract class BaseFragment : Fragment(), FragmentContract, DynamicUiContract {
}
position -> {
contract.setTitle(baseEnum.titleId)
+ updateFab(contract)
core?.active = true
}
-(position + 1) -> {
@@ -129,6 +135,22 @@ abstract class BaseFragment : Fragment(), FragmentContract, DynamicUiContract {
}
}
+ override fun updateFab(contract: MainFabContract) {
+ contract.hideFab() // default
+ }
+
+ protected fun FloatingActionButton.update(iicon: IIcon, click: () -> Unit) {
+ if (isShown) {
+ fadeScaleTransition {
+ setIcon(iicon, Prefs.iconColor)
+ }
+ } else {
+ setIcon(iicon, Prefs.iconColor)
+ show()
+ }
+ setOnClickListener { click() }
+ }
+
override fun detachMainObservable() {
activityDisposable?.dispose()
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt
index 98a081e6..e683b056 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt
@@ -1,9 +1,7 @@
package com.pitchedapps.frost.fragments
-import com.pitchedapps.frost.contracts.FrostContentContainer
-import com.pitchedapps.frost.contracts.FrostContentCore
-import com.pitchedapps.frost.contracts.FrostContentParent
-import com.pitchedapps.frost.contracts.MainActivityContract
+import android.support.design.widget.FloatingActionButton
+import com.pitchedapps.frost.contracts.*
import com.pitchedapps.frost.views.FrostRecyclerView
import io.reactivex.disposables.Disposable
@@ -48,6 +46,8 @@ interface FragmentContract : FrostContentContainer {
*/
fun firstLoadRequest()
+ fun updateFab(contract: MainFabContract)
+
/**
* Single callable action to be executed upon creation
* Note that this call is not guaranteed
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt
index cdeaa3c1..51df4606 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt
@@ -31,7 +31,7 @@ abstract class RecyclerFragment : BaseFragment(), RecyclerContentContract {
}
}
- override final fun reload(progress: (Int) -> Unit, callback: (Boolean) -> Unit) {
+ final override fun reload(progress: (Int) -> Unit, callback: (Boolean) -> Unit) {
reloadImpl(progress) {
if (it)
callback(it)
@@ -49,7 +49,7 @@ abstract class GenericRecyclerFragment<T, Item : IItem<*, *>> : RecyclerFragment
val adapter: ModelAdapter<T, Item> = ModelAdapter(this::mapper)
- override final fun bind(recyclerView: FrostRecyclerView) {
+ final override fun bind(recyclerView: FrostRecyclerView) {
recyclerView.adapter = getAdapter()
recyclerView.onReloadClear = { adapter.clear() }
bindImpl(recyclerView)
@@ -81,7 +81,7 @@ abstract class FrostParserFragment<T : Any, Item : IItem<*, *>> : RecyclerFragme
val adapter: ItemAdapter<Item> = ItemAdapter()
- override final fun bind(recyclerView: FrostRecyclerView) {
+ final override fun bind(recyclerView: FrostRecyclerView) {
recyclerView.adapter = getAdapter()
recyclerView.onReloadClear = { adapter.clear() }
bindImpl(recyclerView)
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 cdeea064..8000c106 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragments.kt
@@ -1,7 +1,12 @@
package com.pitchedapps.frost.fragments
+import android.webkit.WebView
+import com.mikepenz.google_material_typeface_library.GoogleMaterial
import com.pitchedapps.frost.R
+import com.pitchedapps.frost.contracts.MainFabContract
import com.pitchedapps.frost.facebook.FbItem
+import com.pitchedapps.frost.injectors.JsActions
+import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.views.FrostWebView
import com.pitchedapps.frost.web.FrostWebViewClient
import com.pitchedapps.frost.web.FrostWebViewClientMenu
@@ -24,4 +29,20 @@ class WebFragment : BaseFragment() {
else -> FrostWebViewClient(web)
}
+ 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" }
+ return super.updateFab(contract)
+ }
+ if (baseEnum.isFeed) {
+ contract.showFab(GoogleMaterial.Icon.gmd_edit) {
+ JsActions.CREATE_POST.inject(web)
+ }
+ L.e { "UPP" }
+ return
+ }
+ super.updateFab(contract)
+ }
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
index 4a390d9a..637a5092 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
@@ -9,8 +9,8 @@ import android.webkit.WebView
*/
enum class CssHider(vararg val items: String) : InjectorContract {
CORE("[data-sigil=m_login_upsell]", "role=progressbar"),
- HEADER("#header", "[data-sigil=MTopBlueBarHeader]",
- "#header-notices", "[data-sigil*=m-promo-jewel-header]"),
+// HEADER("#header", "[data-sigil=MTopBlueBarHeader]",
+// "#header-notices", "[data-sigil*=m-promo-jewel-header]"),
ADS("article[data-xt*=sponsor]",
"article[data-store*=sponsor]"),
PEOPLE_YOU_MAY_KNOW("article._d2r"),
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt
index 53eb9ede..7be8cd3c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt
@@ -16,6 +16,8 @@ enum class JsActions(body: String) : InjectorContract {
LOGIN_CHECK("document.getElementById('signup-button')&&Frost.loadLogin();"),
BASE_HREF("""document.write("<base href='$FB_URL_BASE'/>");"""),
FETCH_BODY("""setTimeout(function(){var e=document.querySelector("main");e||(e=document.querySelector("body")),Frost.handleHtml(e.outerHTML)},1e2);"""),
+ CREATE_POST(clickBySelector("button[name=view_overview]")),
+// CREATE_MSG(clickBySelector("a[rel=dialog]")),
/**
* Used as a pseudoinjector for maybe functions
*/
@@ -25,4 +27,9 @@ enum class JsActions(body: String) : InjectorContract {
override fun inject(webView: WebView, callback: (() -> Unit)?) =
JsInjector(function).inject(webView, callback)
-} \ No newline at end of file
+
+}
+
+@Suppress("NOTHING_TO_INLINE")
+private inline fun clickBySelector(selector: String): String =
+ """document.querySelector("$selector").click()""" \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
index 9ff129d4..21d660b8 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
@@ -12,7 +12,7 @@ import java.util.*
* The enum name must match the css file name
*/
enum class JsAssets : InjectorContract {
- MENU, MENU_DEBUG, CLICK_A, CONTEXT_A, MEDIA, HEADER_BADGES, TEXTAREA_LISTENER, NOTIF_MSG,
+ MENU, MENU_DEBUG, CLICK_A, CONTEXT_A, MEDIA, HEADER_BADGES, HEADER_HIDER, TEXTAREA_LISTENER, NOTIF_MSG,
DOCUMENT_WATCHER
;
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt
index d5730e16..03e6209e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt
@@ -82,16 +82,16 @@ internal fun <T> List<T>.toJsonString(tag: String, indent: Int) = StringBuilder(
*/
internal abstract class FrostParserBase<out T : Any>(private val redirectToText: Boolean) : FrostParser<T> {
- override final fun parse(cookie: String?) = parseFromUrl(cookie, url)
+ final override fun parse(cookie: String?) = parseFromUrl(cookie, url)
- override final fun parseFromData(cookie: String?, text: String): ParseResponse<T>? {
+ final override fun parseFromData(cookie: String?, text: String): ParseResponse<T>? {
cookie ?: return null
val doc = textToDoc(text) ?: return null
val data = parseImpl(doc) ?: return null
return ParseResponse(cookie, data)
}
- override final fun parseFromUrl(cookie: String?, url: String): ParseResponse<T>? =
+ final override fun parseFromUrl(cookie: String?, url: String): ParseResponse<T>? =
parse(cookie, frostJsoup(cookie, url))
override fun parse(cookie: String?, document: Document): ParseResponse<T>? {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/EnumUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/EnumUtils.kt
index d20d1573..2a562ba2 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/EnumUtils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/EnumUtils.kt
@@ -43,15 +43,15 @@ interface EnumBundleCompanion<E : Enum<E>> {
}
open class EnumCompanion<E : Enum<E>>(
- override final val argTag: String,
- override final val values: Array<E>) : EnumBundleCompanion<E> {
+ final override val argTag: String,
+ final override val values: Array<E>) : EnumBundleCompanion<E> {
- override final val valueMap: Map<String, E> = values.map { it.name to it }.toMap()
+ final override val valueMap: Map<String, E> = values.map { it.name to it }.toMap()
- override final fun get(name: String?) = super.get(name)
+ final override fun get(name: String?) = super.get(name)
- override final fun get(bundle: BaseBundle?) = super.get(bundle)
+ final override fun get(bundle: BaseBundle?) = super.get(bundle)
- override final fun get(intent: Intent?) = super.get(intent)
+ final override fun get(intent: Intent?) = super.get(intent)
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt
index f45e842d..cdfffb87 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt
@@ -44,7 +44,7 @@ abstract class IabBinder : FrostBilling {
val activity
get() = activityRef.get()
- override final fun Activity.onCreateBilling() {
+ final override fun Activity.onCreateBilling() {
activityRef = WeakReference(this)
doAsync {
bp = BillingProcessor.newBillingProcessor(this@onCreateBilling, PUBLIC_BILLING_KEY, this@IabBinder)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
index 4f36fdba..d4e1c103 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
@@ -65,7 +65,6 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() {
if (url.isFacebookUrl)
view.jsInject(
CssAssets.ROUND_ICONS.maybe(Prefs.showRoundedIcons),
- CssHider.HEADER,
CssHider.CORE,
CssHider.COMPOSER.maybe(!Prefs.showComposer),
CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends && IS_FROST_PRO),
@@ -77,6 +76,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() {
JsAssets.CLICK_A,
CssHider.ADS.maybe(!Prefs.showFacebookAds && IS_FROST_PRO),
JsAssets.CONTEXT_A,
+ JsAssets.HEADER_HIDER,
JsAssets.MEDIA)
else
refresh.onNext(false)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
index 44172416..1f22f303 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
@@ -14,6 +14,7 @@ import com.pitchedapps.frost.facebook.FB_USER_MATCHER
import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.facebook.get
import com.pitchedapps.frost.injectors.CssHider
+import com.pitchedapps.frost.injectors.JsAssets
import com.pitchedapps.frost.injectors.jsInject
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
@@ -72,7 +73,7 @@ class LoginWebView @JvmOverloads constructor(
L.d { "Login page commit visible" }
view.setBackgroundColor(Color.TRANSPARENT)
if (url.isFacebookUrl)
- view.jsInject(CssHider.HEADER,
+ view.jsInject(JsAssets.HEADER_HIDER,
CssHider.CORE,
Prefs.themeInjector)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
index f0bb6137..8fd4c0b4 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
@@ -41,7 +41,7 @@ open class NestedWebView @JvmOverloads constructor(
* https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java
*/
@SuppressLint("ClickableViewAccessibility")
- override final fun onTouchEvent(ev: MotionEvent): Boolean {
+ final override fun onTouchEvent(ev: MotionEvent): Boolean {
val event = MotionEvent.obtain(ev)
val action = event.action
if (action == MotionEvent.ACTION_DOWN)
@@ -87,27 +87,27 @@ open class NestedWebView @JvmOverloads constructor(
* ---------------------------------------------
*/
- override final fun setNestedScrollingEnabled(enabled: Boolean) {
+ final override fun setNestedScrollingEnabled(enabled: Boolean) {
childHelper.isNestedScrollingEnabled = enabled
}
- override final fun isNestedScrollingEnabled() = childHelper.isNestedScrollingEnabled
+ final override fun isNestedScrollingEnabled() = childHelper.isNestedScrollingEnabled
- override final fun startNestedScroll(axes: Int) = childHelper.startNestedScroll(axes)
+ final override fun startNestedScroll(axes: Int) = childHelper.startNestedScroll(axes)
- override final fun stopNestedScroll() = childHelper.stopNestedScroll()
+ final override fun stopNestedScroll() = childHelper.stopNestedScroll()
- override final fun hasNestedScrollingParent() = childHelper.hasNestedScrollingParent()
+ final override fun hasNestedScrollingParent() = childHelper.hasNestedScrollingParent()
- override final fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?)
+ final override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?)
= childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
- override final fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?)
+ final override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?)
= childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
- override final fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean)
+ final override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean)
= childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
- override final fun dispatchNestedPreFling(velocityX: Float, velocityY: Float)
+ final override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float)
= childHelper.dispatchNestedPreFling(velocityX, velocityY)
} \ No newline at end of file
diff --git a/app/src/main/res/layout/view_main_fab.xml b/app/src/main/res/layout/view_main_fab.xml
index 5e1fed77..7e3ec2aa 100644
--- a/app/src/main/res/layout/view_main_fab.xml
+++ b/app/src/main/res/layout/view_main_fab.xml
@@ -4,5 +4,4 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
- android:layout_margin="@dimen/kau_fab_margin"
- android:visibility="gone" /> \ No newline at end of file
+ android:layout_margin="@dimen/kau_fab_margin" /> \ No newline at end of file
diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml
index 26db730d..6eb8d795 100644
--- a/app/src/main/res/xml/frost_changelog.xml
+++ b/app/src/main/res/xml/frost_changelog.xml
@@ -6,11 +6,16 @@
<item text="" />
-->
+ <version title="v1.8.1" />
+ <item text="Theme new Facebook update" />
+ <item text="Fix layout issue for posting messages" />
+ <item text="Create FAB for posting" />
+ <item text="" />
+
<version title="v1.8.0" />
<item text="Add Chinese, Indonesian, Norwegian, Polish, Thai, and Turkish translations" />
<item text="Update theme to fix comments" />
<item text="Add option to disable pip (settings > behaviour)" />
- <item text="" />
<version title="v1.7.9" />
<item text="Fix image loading" />
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/MiscTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/MiscTest.kt
index a565aa7d..2be743a3 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/MiscTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/MiscTest.kt
@@ -10,11 +10,6 @@ import kotlin.test.assertTrue
*/
class MiscTest {
- @Test
- fun headerFunction() {
- print(CssHider.HEADER.injector.function)
- }
-
/**
* Spin off 15 threads
* Pause each for 1 - 2s