From 35185958b077880465696d686bd797895cd3ebd4 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 3 Jun 2017 13:22:06 -0700 Subject: setup login activity --- app/src/main/assets/core/_base.scss | 17 ++++ app/src/main/assets/core/login.compact.css | 12 ++- app/src/main/assets/core/login.scss | 23 +++-- .../kotlin/com/pitchedapps/frost/LoginActivity.kt | 100 ++++++++++++++++----- .../kotlin/com/pitchedapps/frost/MainActivity.kt | 2 +- .../com/pitchedapps/frost/dbflow/CookiesDb.kt | 4 +- .../com/pitchedapps/frost/events/FbAccountEvent.kt | 12 +-- .../com/pitchedapps/frost/facebook/FbCookie.kt | 40 +++------ .../pitchedapps/frost/facebook/UsernameFetcher.kt | 19 ++-- .../com/pitchedapps/frost/views/AnimUtils.kt | 14 ++- .../com/pitchedapps/frost/views/ViewUtils.kt | 1 + .../pitchedapps/frost/web/FrostWebViewClient.kt | 11 ++- .../com/pitchedapps/frost/web/LoginWebView.kt | 4 +- app/src/main/res/layout/login_webview.xml | 8 +- app/src/main/res/values/strings.xml | 2 + 15 files changed, 185 insertions(+), 84 deletions(-) create mode 100644 app/src/main/assets/core/_base.scss (limited to 'app/src/main') diff --git a/app/src/main/assets/core/_base.scss b/app/src/main/assets/core/_base.scss new file mode 100644 index 00000000..344b6696 --- /dev/null +++ b/app/src/main/assets/core/_base.scss @@ -0,0 +1,17 @@ +@mixin placeholder { + ::-webkit-input-placeholder { + @content + } + + :-moz-placeholder { + @content + } + + ::-moz-placeholder { + @content + } + + :-ms-input-placeholder { + @content + } +} diff --git a/app/src/main/assets/core/login.compact.css b/app/src/main/assets/core/login.compact.css index 765ac466..d0aa315e 100644 --- a/app/src/main/assets/core/login.compact.css +++ b/app/src/main/assets/core/login.compact.css @@ -1,3 +1,5 @@ +[data-sigil="m_login_upsell"] { display: none !important; } + body, #root, #header, .aclb, ._55wo, ._1upc, input { background: #000 !important; } button::before, ._56be::before, .btnS, .touch::before { background: #111 !important; } @@ -6,7 +8,15 @@ button::before, ._56be::before, .btnS, .touch::before { background: #111 !import .touch .btnS { box-shadow: none !important; } -input, ._43mh, .touch .btn, a, .fcg, button, ._52j9, ::-webkit-input-placeholder, ::-moz-placeholder, ::-ms-input-placeholder { color: #fff !important; } +input, ._43mh, .touch .btn, a, .fcg, button, ._52j9 { color: #fff !important; } + +::-webkit-input-placeholder { color: #fff !important; } + +:-moz-placeholder { color: #fff !important; } + +::-moz-placeholder { color: #fff !important; } + +:-ms-input-placeholder { color: #fff !important; } ._43mh::before, ._43mh::after { background: #fff !important; } diff --git a/app/src/main/assets/core/login.scss b/app/src/main/assets/core/login.scss index 81cb4c73..427640fc 100644 --- a/app/src/main/assets/core/login.scss +++ b/app/src/main/assets/core/login.scss @@ -1,11 +1,17 @@ @import "colors"; +@import "base"; -body, #root,#header,.aclb,._55wo,._1upc,input { +//Get Android banner +[data-sigil="m_login_upsell"] { + display: none !important; +} + +body, #root, #header, .aclb, ._55wo, ._1upc, input { background: $background !important; } button::before, ._56be::before, .btnS, .touch::before { - background: $background2 !important; + background: $background2 !important; } ._56bf, .touch .btn { @@ -17,16 +23,21 @@ button::before, ._56be::before, .btnS, .touch::before { box-shadow: none !important; } -input,._43mh, .touch .btn,a, .fcg, button, ._52j9, ::-webkit-input-placeholder,::-moz-placeholder ,::-ms-input-placeholder { - color: $text !important +input, ._43mh, .touch .btn, a, .fcg, button, ._52j9 { + color: $text !important; } +@include placeholder { + color: $text !important; +} + + // divider lines ._43mh::before, ._43mh::after { - background: $text !important + background: $text !important; } ._1rrd { border: 1px solid $text !important; - color: $text !important; + color: $text !important; } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt index 03c40aaf..410e2e1d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt @@ -18,12 +18,24 @@ import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target import com.pitchedapps.frost.dbflow.CookieModel +import com.pitchedapps.frost.dbflow.saveFbCookie +import com.pitchedapps.frost.facebook.FACEBOOK_COM +import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.PROFILE_PICTURE_URL +import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.bindView +import com.pitchedapps.frost.views.fadeIn +import com.pitchedapps.frost.views.fadeOut +import com.pitchedapps.frost.views.setTextWithFade import com.pitchedapps.frost.web.LoginWebView +import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.BiFunction +import io.reactivex.internal.operators.single.SingleToObservable import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.SingleSubject +import org.jsoup.Jsoup +import kotlin.concurrent.thread /** @@ -33,21 +45,33 @@ class LoginActivity : AppCompatActivity() { val toolbar: Toolbar by bindView(R.id.toolbar) val web: LoginWebView by bindView(R.id.login_webview) - val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh) + val swipeRefresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh) val textview: AppCompatTextView by bindView(R.id.textview) val profile: ImageView by bindView(R.id.profile) - val loginObservable = SingleSubject.create() - val progressObservable = BehaviorSubject.create() + val loginObservable = SingleSubject.create()!! + val progressObservable = BehaviorSubject.create()!! + val profileObservable = SingleSubject.create()!! + val usernameObservable = SingleSubject.create()!! companion object { fun newInstance(context: Context) { val intent = Intent(context, LoginActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) val bundle = ActivityOptionsCompat.makeCustomAnimation(context, R.anim.slide_in_right, R.anim.slide_out_right).toBundle() ContextCompat.startActivity(context, intent, bundle) } } + // Helper to set and enable swipeRefresh + var refresh: Boolean + get() = swipeRefresh.isRefreshing + set(value) { + if (value) swipeRefresh.isEnabled = true + swipeRefresh.isRefreshing = value + if (!value) swipeRefresh.isEnabled = false + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) @@ -56,26 +80,62 @@ class LoginActivity : AppCompatActivity() { web.loginObservable = loginObservable web.progressObservable = progressObservable loginObservable.observeOn(AndroidSchedulers.mainThread()).subscribe { - cookieModel -> - Glide.with(this@LoginActivity).load(PROFILE_PICTURE_URL(cookieModel.id)).listener(object : RequestListener { - override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { - return false - } - - override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { - return false - } - - }).into(profile) - } - progressObservable.observeOn(AndroidSchedulers.mainThread()).subscribe { - val loading = it != 100 - if (loading) refresh.isEnabled = true - refresh.isRefreshing = loading - if (!loading) refresh.isEnabled = false + cookie -> + web.fadeOut(onFinish = { + profile.fadeIn() + textview.fadeIn() + loadInfo(cookie) + }) } + progressObservable.observeOn(AndroidSchedulers.mainThread()).subscribe { refresh = it != 100 } web.loadLogin() } + fun loadInfo(cookie: CookieModel) { + refresh = true + Observable.zip(SingleToObservable(profileObservable), SingleToObservable(usernameObservable), + BiFunction> { foundImage, name -> Pair(foundImage, name) }) + .observeOn(AndroidSchedulers.mainThread()).subscribe { + (foundImage, name) -> + refresh = false + L.d("Zip done") + if (!foundImage) L.e("Could not get profile photo; Invalid id?\n\t$cookie") + textview.setTextWithFade(String.format(getString(R.string.welcome), name), duration = 500) + } + loadProfile(cookie.id) + loadUsername(cookie) + } + + fun loadProfile(id: Long) { + Glide.with(this@LoginActivity).load(PROFILE_PICTURE_URL(id)).listener(object : RequestListener { + override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { + profileObservable.onSuccess(true) + return false + } + + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + profileObservable.onSuccess(false) + return false + } + }).into(profile) + } + + fun loadUsername(cookie: CookieModel) { + thread { + var name = "" + try { + name = Jsoup.connect(FbTab.PROFILE.url) + .cookie(FACEBOOK_COM, cookie.cookie) + .get().title() + L.d("User name found: $name") + } catch (e: Exception) { + L.e("User name fetching failed: ${e.message}") + } finally { + cookie.name = name + saveFbCookie(cookie) + usernameObservable.onSuccess(name) + } + } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt index 8b01e0c3..223384c1 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt @@ -145,7 +145,7 @@ class MainActivity : AppCompatActivity() { // finish() } R.id.action_changelog -> Changelog.show(this) - R.id.action_call -> WebOverlayActivity.newInstance(this, "https://www.google.ca") + R.id.action_call -> LoginActivity.newInstance(this) R.id.action_db -> adapter.pages.saveAsync(this) R.id.action_restart -> { finish(); diff --git a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt index 28ad0800..bb5b0115 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt @@ -42,12 +42,12 @@ fun loadFbCookiesAsync(callback: (cookies: List) -> Unit) { fun saveFbCookie(cookie: CookieModel) { cookie.async save { - L.d("Fb cookie saved") + L.d("Fb cookie $cookie saved") } } fun removeCookie(id: Long) { loadFbCookie(id)?.async?.delete({ - L.d("Fb cookie deleted") + L.d("Fb cookie $id deleted") }) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/events/FbAccountEvent.kt b/app/src/main/kotlin/com/pitchedapps/frost/events/FbAccountEvent.kt index 538a7919..10173de2 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/events/FbAccountEvent.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/events/FbAccountEvent.kt @@ -32,10 +32,10 @@ class FbAccountEvent(val data: CookieModel, val sender: Int, val flag: Int) { } fun execute(webView: FrostWebViewCore) { - if (sender != -1 && sender == webView.position) return - when (flag) { - FLAG_LOGOUT, FLAG_RESET, FLAG_NEW, FLAG_SWITCH -> webView.loadBaseUrl() - } +// if (sender != -1 && sender == webView.position) return +// when (flag) { +// FLAG_LOGOUT, FLAG_RESET, FLAG_NEW, FLAG_SWITCH -> webView.loadBaseUrl() +// } } /** @@ -51,8 +51,8 @@ class FbAccountEvent(val data: CookieModel, val sender: Int, val flag: Int) { .withIcon(PROFILE_PICTURE_URL(data.id)) accountHeader.addProfile(profile, 0) accountHeader.setActiveProfile(profile, true) - if (data.name == null) - UsernameFetcher.fetch(data, sender) +// if (data.name == null) +// UsernameFetcher.fetch(data, sender) } FLAG_USER_NAME -> { if (accountHeader.activeProfile.name == null) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt index 7829998f..038eb1a6 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt @@ -32,57 +32,37 @@ object FbCookie { } } - private val userMatcher: Regex by lazy { Regex("c_user=([0-9]*);") } - - fun hasLoggedIn(url: String, cookie: String?):Boolean { - if (cookie == null || !url.contains("facebook") || !cookie.contains(userMatcher)) return false - L.d("Checking cookie for $url\n\t$cookie") - val id = userMatcher.find(cookie)?.groups?.get(1)?.value - if (id != null) { - try { - save(id.toLong(), -1) - return true - } catch (e: NumberFormatException) { - //todo send report that id has changed - } - } - return false - } - - fun save(id: Long, sender: Int) { + fun save(id: Long) { L.d("New cookie found for $id") Prefs.userId = id CookieManager.getInstance().flush() val cookie = CookieModel(Prefs.userId, "", webCookie) - EventBus.getDefault().post(FbAccountEvent(cookie, sender, FbAccountEvent.FLAG_NEW)) saveFbCookie(cookie) } - //TODO reset when new account is added; reset and clear when account is logged out - fun reset(loggedOut: Boolean = false, sender: Int) { + fun reset() { Prefs.userId = Prefs.userIdDefault with(CookieManager.getInstance()) { removeAllCookies(null) flush() } - EventBus.getDefault().post(FbAccountEvent(CookieModel(), sender, if (loggedOut) FbAccountEvent.FLAG_LOGOUT else FbAccountEvent.FLAG_RESET)) } - fun switchUser(id: Long, sender: Int) = switchUser(loadFbCookie(id), sender) + fun switchUser(id: Long) = switchUser(loadFbCookie(id)) - fun switchUser(name: String, sender: Int) = switchUser(loadFbCookie(name), sender) + fun switchUser(name: String) = switchUser(loadFbCookie(name)) - fun switchUser(cookie: CookieModel?, sender: Int) { + fun switchUser(cookie: CookieModel?) { if (cookie == null) return Prefs.userId = cookie.id dbCookie = cookie.cookie webCookie = dbCookie - EventBus.getDefault().post(FbAccountEvent(cookie, sender, FbAccountEvent.FLAG_SWITCH)) + //TODO add webview refresh event } - fun logout(sender: Int) { - L.d("Logging out user ${Prefs.userId}") - removeCookie(Prefs.userId) - reset(true, sender) + fun logout(id:Long) { + L.d("Logging out user $id") + removeCookie(id) + reset() } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt index da244ba3..5bc58fa9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt @@ -2,9 +2,8 @@ package com.pitchedapps.frost.facebook import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.dbflow.saveFbCookie -import com.pitchedapps.frost.events.FbAccountEvent import com.pitchedapps.frost.utils.L -import org.greenrobot.eventbus.EventBus +import io.reactivex.subjects.SingleSubject import org.jsoup.Jsoup import kotlin.concurrent.thread @@ -13,22 +12,20 @@ import kotlin.concurrent.thread */ object UsernameFetcher { - fun fetch(data: CookieModel, sender: Int) { + fun fetch(data: CookieModel, callback: SingleSubject) { thread { + var name = "" try { - val title = Jsoup.connect(FbTab.PROFILE.url) + name = Jsoup.connect(FbTab.PROFILE.url) .cookie(FACEBOOK_COM, data.cookie) .get().title() - L.d("User name found: $title") - data.name = title + L.d("User name found: $name") } catch (e: Exception) { L.e("User name fetching failed: ${e.message}") - data.name = "" } finally { - if (data.name != null) { - saveFbCookie(data) - EventBus.getDefault().post(FbAccountEvent(data, sender, FbAccountEvent.FLAG_USER_NAME)) - } + data.name = name + saveFbCookie(data) + callback.onSuccess(name) } } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt index a2a0dcff..3d212cc0 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt @@ -2,11 +2,13 @@ package com.pitchedapps.frost.views import android.animation.Animator import android.animation.AnimatorListenerAdapter +import android.support.annotation.StringRes import android.view.View import android.view.ViewAnimationUtils import android.view.animation.Animation import android.view.animation.AnimationUtils import android.view.animation.DecelerateInterpolator +import android.widget.TextView /** @@ -104,4 +106,14 @@ fun View.fadeOut(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit) } }) startAnimation(anim) -} \ No newline at end of file +} + +fun TextView.setTextWithFade(text: String, duration: Long = 200, onFinish: (() -> Unit)? = null) { + fadeOut(duration = duration, onFinish = { + setText(text) + fadeIn(duration = duration, onFinish = onFinish) + }) +} + +fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = setTextWithFade(context.getString(textId), duration, onFinish) + diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt index 8dc3f01f..474889ba 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt @@ -9,6 +9,7 @@ import android.support.v4.content.ContextCompat import android.view.View import android.view.ViewGroup import android.widget.ProgressBar +import android.widget.TextView /** diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt index 4dcf0d9e..03bb5a60 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt @@ -3,10 +3,12 @@ package com.pitchedapps.frost.web import android.graphics.Bitmap import android.view.KeyEvent import android.webkit.* +import com.pitchedapps.frost.LoginActivity import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.injectors.CssAssets import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.views.circularReveal import com.pitchedapps.frost.views.fadeOut @@ -28,14 +30,19 @@ class FrostWebViewClient(val position: () -> Int) : WebViewClient() { super.onPageStarted(view, url, favicon) L.i("FWV Loading $url") if (!url.contains(FACEBOOK_COM)) return - if (url.contains("logout.php")) FbCookie.logout(position.invoke()) + if (url.contains("logout.php")) { + FbCookie.logout(Prefs.userId) + LoginActivity.newInstance(view.context) + } else if (url.contains("login.php")) { + FbCookie.reset() + LoginActivity.newInstance(view.context) + } view.fadeOut(duration = 200L) } override fun onPageFinished(view: WebView, url: String) { super.onPageFinished(view, url) if (!url.contains(FACEBOOK_COM)) return - FbCookie.checkUserId(url, CookieManager.getInstance().getCookie(url), position.invoke()) CssAssets.HEADER.inject(view, { view.circularReveal(offset = 150L) }) 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 6e0cf201..aa40f1f1 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt @@ -39,6 +39,7 @@ class LoginWebView @JvmOverloads constructor( lateinit var progressObservable: Subject init { + FbCookie.reset() cookieObservable.filter { (_, cookie) -> cookie?.contains(userMatcher) ?: false } .subscribe { (url, cookie) -> @@ -46,9 +47,10 @@ class LoginWebView @JvmOverloads constructor( val id = userMatcher.find(cookie!!)?.groups?.get(1)?.value if (id != null) { try { - FbCookie.save(id.toLong(), -1) + FbCookie.save(id.toLong()) //TODO proceed to next view cookieObservable.onComplete() + loginObservable.onSuccess(CookieModel(id.toLong(), "", cookie)) } catch (e: NumberFormatException) { //todo send report that id has changed } diff --git a/app/src/main/res/layout/login_webview.xml b/app/src/main/res/layout/login_webview.xml index 35b5f681..681ccaa5 100644 --- a/app/src/main/res/layout/login_webview.xml +++ b/app/src/main/res/layout/login_webview.xml @@ -15,15 +15,17 @@ android:layout_centerInParent="true" android:layout_marginBottom="8dp" android:contentDescription="Profile Picture" - android:scaleType="centerInside"/> + android:scaleType="centerInside" + android:visibility="invisible" /> + android:layout_centerHorizontal="true" + android:text="@string/loading_account" + android:visibility="invisible" /> Birthdays Chat Photos + Getting everything ready… + Welcome %s -- cgit v1.2.3