diff options
author | Allan Wang <me@allanwang.ca> | 2017-05-31 17:11:46 -0700 |
---|---|---|
committer | Allan Wang <me@allanwang.ca> | 2017-05-31 17:11:46 -0700 |
commit | 8618670b82641d5fbaec9c333f1290bab429ce27 (patch) | |
tree | 737c9a04f108ea68547eef2db1ae6e96caa64df6 /app | |
parent | 9a41937a33539dbfaae4d072361caaec79865c29 (diff) | |
download | frost-8618670b82641d5fbaec9c333f1290bab429ce27.tar.gz frost-8618670b82641d5fbaec9c333f1290bab429ce27.tar.bz2 frost-8618670b82641d5fbaec9c333f1290bab429ce27.zip |
add more cookie handling
Diffstat (limited to 'app')
25 files changed, 339 insertions, 253 deletions
diff --git a/app/build.gradle b/app/build.gradle index 4fffb72c..1acfb528 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,6 +30,7 @@ android { } sourceSets { main.java.srcDirs += 'src/main/kotlin' + test.java.srcDirs += 'src/test/kotlin' } } @@ -41,6 +42,7 @@ dependencies { testCompile 'junit:junit:4.12' compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" compile "com.android.support:appcompat-v7:${ANDROID_SUPPORT_LIBS}" compile "com.android.support:support-v4:${ANDROID_SUPPORT_LIBS}" @@ -83,6 +85,8 @@ dependencies { compile "com.jakewharton.rxbinding2:rxbinding:${RX_BINDING}" compile "com.jakewharton.rxbinding2:rxbinding-appcompat-v7:${RX_BINDING}" + compile "org.greenrobot:eventbus:${EVENT_BUS}" + compile "com.facebook.stetho:stetho-okhttp3:${STETHO}" compile "com.lapism:searchview:${SEARCH_VIEW}" @@ -104,6 +108,8 @@ dependencies { compile "com.google.auto.value:auto-value:${AUTO}" annotationProcessor "com.google.auto.value:auto-value:${AUTO}" annotationProcessor "com.ryanharter.auto.value:auto-value-parcel:${AUTO_VALUE_PARCEL}" + + compile "com.f2prateek.rx.preferences2:rx-preferences:${RX_PREFS}" } kapt { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 793e3983..d44aa950 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" package="com.pitchedapps.frost"> <!-- To auto-complete the email text field in the login form with the user's emails --> @@ -92,37 +91,17 @@ android:scheme="https" /> </intent-filter> </activity> - <activity android:name=".LoginActivity" /> - <activity - android:name="com.facebook.FacebookActivity" - android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" - android:label="@string/app_name" - android:theme="@android:style/Theme.Translucent.NoTitleBar" - tools:replace="android:theme" /> - <activity - android:name="com.facebook.CustomTabActivity" - android:exported="true"> - <intent-filter> - <action android:name="android.intent.action.VIEW" /> - - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - <data android:scheme="@string/fb_login_protocol_scheme" /> + <receiver + android:name=".services.NotificationReceiver" + android:enabled="true" + android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> + <intent-filter> + <action android:name="android.intent.action.PACKAGE_REPLACED" /> + <action android:name="android.intent.action.BOOT_COMPLETED" /> + <action android:name="com.pitchedapps.frost.NOTIFICATIONS" /> </intent-filter> - </activity> - - <meta-data - android:name="com.facebook.sdk.ApplicationId" - android:value="@string/facebook_app_id" /> - <meta-data - android:name="com.facebook.sdk.ApplicationName" - android:value="@string/facebook_app_name" /> - - <provider - android:name="com.facebook.FacebookContentProvider" - android:authorities="@string/facebook_authorities" - android:exported="true" /> + </receiver> </application> </manifest>
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt index 0ad5259d..b5e7f5df 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt @@ -4,6 +4,7 @@ import android.app.Application import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.retro.FrostApi import com.pitchedapps.frost.utils.CrashReportingTree +import com.pitchedapps.frost.utils.GlideUtils import com.pitchedapps.frost.utils.Prefs import com.raizlabs.android.dbflow.config.FlowConfig import com.raizlabs.android.dbflow.config.FlowManager @@ -21,8 +22,9 @@ class FrostApp : Application() { else Timber.plant(CrashReportingTree()) FlowManager.init(FlowConfig.Builder(this).build()) Prefs(this) + GlideUtils(this) FrostApi(this) - FbCookie.init() + FbCookie() super.onCreate() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt index 5c7c3a9e..7bff3b58 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt @@ -24,9 +24,7 @@ import com.pitchedapps.frost.utils.* import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject -class MainActivity : AppCompatActivity(), KeyPairObservable { - - override val observable: Subject<Pair<Int, Int>> = PublishSubject.create<Pair<Int, Int>>() +class MainActivity : AppCompatActivity() { lateinit var adapter: SectionsPagerAdapter val toolbar: Toolbar by bindView(R.id.toolbar) @@ -75,7 +73,7 @@ class MainActivity : AppCompatActivity(), KeyPairObservable { finish() } R.id.action_changelog -> Changelog.show(this) - R.id.action_call -> frostApi.me().enqueueFrost { _, response -> L.e(response.toString())} + R.id.action_call -> frostApi.me().enqueueFrost { _, response -> L.e(response.toString()) } 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 d8f349a0..12443cf1 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt @@ -1,6 +1,5 @@ package com.pitchedapps.frost.dbflow -import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.raizlabs.android.dbflow.annotation.ConflictAction @@ -23,10 +22,16 @@ object CookiesDb { @Table(database = CookiesDb::class, allFields = true, primaryKeyConflict = ConflictAction.REPLACE) data class CookieModel(@PrimaryKey var id: Long = Prefs.userIdDefault, var cookie: String? = null) : BaseModel() -fun loadFbCookie(): CookieModel? = (select from CookieModel::class where (CookieModel_Table.id eq Prefs.userId)).querySingle() +fun loadFbCookie(id: Long): CookieModel? = (select from CookieModel::class where (CookieModel_Table.id eq id)).querySingle() -fun saveFbCookie() { - CookieModel(FbCookie.userId, FbCookie.webCookie).async save { +fun saveFbCookie(id: Long, cookie: String?) { + CookieModel(id, cookie).async save { L.d("Fb cookie saved") } +} + +fun removeCookie(id: Long) { + loadFbCookie(id)?.async?.delete({ + L.d("Fb cookie deleted") + }) }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/DbUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/DbUtils.kt index 32d232b7..bb2627a5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/DbUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/DbUtils.kt @@ -1,10 +1,9 @@ -package com.pitchedapps.frost.utils +package com.pitchedapps.frost.dbflow import android.content.Context +import com.pitchedapps.frost.utils.L import com.raizlabs.android.dbflow.config.FlowManager -import com.raizlabs.android.dbflow.kotlinextensions.* import com.raizlabs.android.dbflow.structure.database.transaction.FastStoreModelTransaction -import com.raizlabs.android.dbflow.structure.database.transaction.Transaction /** * Created by Allan Wang on 2017-05-30. diff --git a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt index 067a07bf..bfd0b0fe 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt @@ -7,9 +7,7 @@ import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.typeface.IIcon import com.mikepenz.material_design_iconic_typeface_library.MaterialDesignIconic import com.pitchedapps.frost.R -import com.pitchedapps.frost.facebook.FB_KEY import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.replace import com.raizlabs.android.dbflow.annotation.Database import com.raizlabs.android.dbflow.annotation.ForeignKey import com.raizlabs.android.dbflow.annotation.PrimaryKey @@ -66,7 +64,7 @@ enum class FbUrl(@StringRes val titleId: Int, val icon: IIcon, relativeUrl: Stri PROFILE(R.string.profile, CommunityMaterial.Icon.cmd_account, "me"), EVENTS(R.string.events, GoogleMaterial.Icon.gmd_event, "events/upcoming"), FRIENDS(R.string.friends, GoogleMaterial.Icon.gmd_people, "friends/center/requests"), - MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "messages"), + MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "messages?disable_interstitial=1"), NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "notifications"); val url = "$FB_URL_BASE$relativeUrl" diff --git a/app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt b/app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt new file mode 100644 index 00000000..64c91955 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt @@ -0,0 +1,22 @@ +package com.pitchedapps.frost.events + +import com.pitchedapps.frost.web.FrostWebView + +/** + * Created by Allan Wang on 2017-05-31. + */ +class WebEvent(val key: Int, val urlMatch: String? = null) { + + companion object { + const val REFRESH = 0 + const val REFRESH_BASE = 1 + } + + fun execute(webView: FrostWebView) { + if (urlMatch != null && !webView.url.contains(urlMatch)) return + when (key) { + REFRESH -> webView.reload() + REFRESH_BASE -> webView.loadUrl(webView.baseUrl) + } + } +}
\ No newline at end of file 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 80fc3b72..3316bb65 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt @@ -3,24 +3,30 @@ package com.pitchedapps.frost.facebook import android.webkit.CookieManager import com.pitchedapps.frost.dbflow.FB_URL_BASE import com.pitchedapps.frost.dbflow.loadFbCookie +import com.pitchedapps.frost.dbflow.removeCookie import com.pitchedapps.frost.dbflow.saveFbCookie +import com.pitchedapps.frost.events.WebEvent +import com.pitchedapps.frost.utils.GlideUtils import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs +import org.greenrobot.eventbus.EventBus /** * Created by Allan Wang on 2017-05-30. */ object FbCookie { - var userId: Long = Prefs.userIdDefault var dbCookie: String? = null var webCookie: String? get() = CookieManager.getInstance().getCookie(FB_URL_BASE) - set(value) = CookieManager.getInstance().setCookie(FB_URL_BASE, value) + set(value) { + CookieManager.getInstance().setCookie(FB_URL_BASE, value) + CookieManager.getInstance().flush() + } - fun init() { - userId = Prefs.userId - dbCookie = loadFbCookie()?.cookie + operator fun invoke() { + L.d("User ${Prefs.userId}") + dbCookie = loadFbCookie(Prefs.userId)?.cookie if (dbCookie != null && webCookie == null) { L.d("DbCookie found & WebCookie is null; setting webcookie") webCookie = dbCookie @@ -30,34 +36,47 @@ object FbCookie { private val userMatcher: Regex by lazy { Regex("c_user=([0-9]*);") } fun checkUserId(url: String, cookie: String?) { - if (userId != Prefs.userIdDefault || cookie == null) return + if (Prefs.userId != Prefs.userIdDefault || cookie == null) return L.d("Checking cookie for $url\n\t$cookie") if (!url.contains("facebook") || !cookie.contains(userMatcher)) return val id = userMatcher.find(cookie)?.groups?.get(1)?.value if (id != null) { try { - userId = id.toLong() - save() + save(id.toLong()) } catch (e: NumberFormatException) { //todo send report that id has changed } } } - fun save() { - L.d("New cookie found for $userId") - Prefs.userId = userId + fun save(id: Long) { + L.d("New cookie found for $id") + Prefs.userId = id CookieManager.getInstance().flush() - saveFbCookie() + EventBus.getDefault().post(WebEvent(WebEvent.REFRESH_BASE)) + saveFbCookie(Prefs.userId, webCookie) + GlideUtils.downloadProfile(id) } //TODO reset when new account is added; reset and clear when account is logged out fun reset() { Prefs.userId = Prefs.userIdDefault - userId = Prefs.userIdDefault with(CookieManager.getInstance()) { removeAllCookies(null) flush() } } + + fun switchUser(id: Long) { + val cookie = loadFbCookie(id) ?: return + Prefs.userId = id + dbCookie = cookie.cookie + webCookie = dbCookie + } + + fun logout() { + L.d("Logging out user ${Prefs.userId}") + removeCookie(Prefs.userId) + reset() + } }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/UrlData.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/UrlData.kt deleted file mode 100644 index c5c2a86b..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/UrlData.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.pitchedapps.frost.facebook - -import android.content.Context -import android.support.annotation.StringRes -import com.mikepenz.community_material_typeface_library.CommunityMaterial -import com.mikepenz.google_material_typeface_library.GoogleMaterial -import com.mikepenz.iconics.typeface.IIcon -import com.mikepenz.material_design_iconic_typeface_library.MaterialDesignIconic -import com.pitchedapps.frost.R -import com.pitchedapps.frost.dbflow.FbTab - -/** - * Created by Allan Wang on 2017-05-29. - */ -enum class FbUrl(@StringRes val titleId: Int, val icon: IIcon, val url: String) { - LOGIN(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, "https://www.facebook.com/v2.9/dialog/oauth?client_id=$FB_KEY&redirect_uri=https://touch.facebook.com/&response_type=token,granted_scopes"), - FEED(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, "https://touch.facebook.com/"), - PROFILE(R.string.profile, CommunityMaterial.Icon.cmd_account, "https://touch.facebook.com/me/"), - EVENTS(R.string.events, GoogleMaterial.Icon.gmd_event, "https://touch.facebook.com/events/upcoming"), - FRIENDS(R.string.friends, GoogleMaterial.Icon.gmd_people, "https://touch.facebook.com/friends/center/requests/"), - MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "https://touch.facebook.com/messages"), - NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "https://touch.facebook.com/notifications"); - - fun tabInfo(c: Context) = FbTab(c.getString(titleId), icon, url) -} - -//BOOKMARKS("https://touch.facebook.com/bookmarks"), -//SEARCH("https://touch.facebook.com/search"),
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt index 435b87a2..cb3bb713 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt @@ -12,12 +12,10 @@ import io.reactivex.functions.Consumer * Created by Allan Wang on 2017-05-29. */ interface BaseFragmentContract { - fun onActivityEvent(position: Int, key: Int) fun onBackPressed(): Boolean } -abstract class BaseFragment : Fragment(), Consumer<Pair<Int, Int>>, BaseFragmentContract { - var disposable: Disposable? = null +abstract class BaseFragment : Fragment(), BaseFragmentContract { val position: Int by lazy { arguments.getInt(ARG_POSITION) } companion object { @@ -29,21 +27,4 @@ abstract class BaseFragment : Fragment(), Consumer<Pair<Int, Int>>, BaseFragment } } - override fun onAttach(context: Context?) { - super.onAttach(context) - if (activity is KeyPairObservable && disposable == null) - disposable = (activity as KeyPairObservable).observable.subscribe(this, Consumer { - t: Throwable -> - L.e(t.message ?: "Observable error") - }) - } - - override fun onDestroyView() { - disposable?.dispose() - disposable = null - super.onDestroyView() - } - - override fun accept(t: Pair<Int, Int>) = onActivityEvent(t.first, t.second) - }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt index d7bf4061..ba9584eb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt @@ -8,13 +8,10 @@ import android.view.ViewGroup import butterknife.ButterKnife import butterknife.Unbinder import com.pitchedapps.frost.R -import com.pitchedapps.frost.facebook.FbUrl -import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.bindView import com.pitchedapps.frost.utils.putString -import com.pitchedapps.frost.views.FrostWebView -import com.pitchedapps.frost.views.SwipeRefreshBase -import com.pitchedapps.frost.views.WebStatus +import com.pitchedapps.frost.web.FrostWebView +import com.pitchedapps.frost.web.WebStatus /** * Created by Allan Wang on 2017-05-29. @@ -23,10 +20,6 @@ import com.pitchedapps.frost.views.WebStatus class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { - override fun onActivityEvent(position: Int, key: Int) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - override fun onRefresh() { web.reload() } @@ -34,10 +27,9 @@ class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { companion object { private val ARG_URL = "arg_url" fun newInstance(position: Int, url: String) = BaseFragment.newInstance(WebFragment(), position).putString(ARG_URL, url) - fun newInstance(position: Int, url: FbUrl = FbUrl.FEED) = newInstance(position, url.url) } - val refresh: SwipeRefreshBase by bindView(R.id.swipe_refresh) + val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh) val web: FrostWebView by bindView(R.id.frost_webview) lateinit var url: String private lateinit var unbinder: Unbinder @@ -56,6 +48,7 @@ class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + web.baseUrl = url web.observable.subscribe { t: WebStatus -> when (t) { @@ -64,10 +57,10 @@ class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { } } refresh.setOnRefreshListener(this) - refresh.shouldSwipe = { - L.e("Y ${web.scrollY}") - SwipeRefreshBase.shouldScroll(web) - } +// refresh.shouldSwipe = { +// L.e("Y ${web.scrollY}") +// SwipeRefreshBase.shouldScroll(web) +// } web.loadUrl(url) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsBuilder.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsBuilder.kt new file mode 100644 index 00000000..9844e5d5 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsBuilder.kt @@ -0,0 +1,36 @@ +package com.pitchedapps.frost.injectors + +import android.webkit.WebView + +/** + * Created by Allan Wang on 2017-05-31. + */ +class JsBuilder { + private val builder = StringBuilder() + + init { + builder.append("javascript:(function(){") + } + + private fun getElementById(id: String) = "document.getElementById(\"$id\")" + + private fun hideElementById(id: String) { + builder.append(getElementById(id)).append(".style.display=\"none\";") + } + + fun hideElementById(vararg ids: String) { + ids.forEach { hideElementById(it) } + } + + fun build() = builder.toString() + "})()" + + fun inject(webView: WebView) { + webView.loadUrl(build()) + } + + fun removeAllStyles() { + + } + + override fun toString() = build() +}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt index e7a9df5a..2d1659cc 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt @@ -5,28 +5,8 @@ import android.webkit.WebView /** * Created by Allan Wang on 2017-05-31. */ -class JsInjector { - private val builder = StringBuilder() - - init { - builder.append("javascript:(function(){") - } - - private fun getElementById(id: String) = "document.getElementById(\"$id\")" - - private fun hideElementById(id: String) { - builder.append(getElementById(id)).append(".style.display=\"none\";") - } - - fun hideElementById(vararg ids: String) { - ids.forEach { hideElementById(it) } - } - - fun build() = builder.toString() + "})()" - +object JsInjector { fun inject(webView: WebView) { - webView.loadUrl(build()) - } - override fun toString() = build() + } }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationReceiver.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationReceiver.kt new file mode 100644 index 00000000..b37ca1f8 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationReceiver.kt @@ -0,0 +1,20 @@ +package com.pitchedapps.frost.services + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent + +/** + * Created by Allan Wang on 2017-05-31. + */ +class NotificationReceiver : BroadcastReceiver() { + + companion object { + const val ACTION = "com.pitchedapps.frost.NOTIFICATIONS" + } + + override fun onReceive(context: Context, intent: Intent) { + if (intent.action != ACTION) return + } + +}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/GlideUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/GlideUtils.kt new file mode 100644 index 00000000..6fbcced1 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/GlideUtils.kt @@ -0,0 +1,26 @@ +package com.pitchedapps.frost.utils + +import android.content.Context +import com.bumptech.glide.Glide + +/** + * Created by Allan Wang on 2017-05-31. + */ +object GlideUtils { + + lateinit var applicationContext: Context + + operator fun invoke(applicationContext: Context) { + this.applicationContext = applicationContext + } + + fun downloadForLater(url: String) { + Glide.with(applicationContext).download(url) + } + + fun downloadProfile(id: Long) { + L.d("Downloading profile photo") + downloadForLater("http://graph.facebook.com/$id/picture?type=large") + } + +}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt index fe1fdc7c..49cc2f9b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt @@ -8,7 +8,7 @@ import timber.log.Timber * Created by Allan Wang on 2017-05-28. */ object L { - val TAG = "Frost: %s" + const val TAG = "Frost: %s" fun e(s: String) = Timber.e(TAG, s) fun d(s: String) = Timber.d(TAG, s) } 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 52a75929..d99e8417 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -5,6 +5,8 @@ import android.content.SharedPreferences /** * Created by Allan Wang on 2017-05-28. + * + * Shared Preference object with lazy cached retrievals */ private val PREFERENCE_NAME = "${com.pitchedapps.frost.BuildConfig.APPLICATION_ID}.prefs" @@ -13,6 +15,8 @@ private val USER_ID = "user_id" object Prefs { + private const val prefDefaultLong = -2L + lateinit private var c: Context operator fun invoke(c: Context) { this.c = c @@ -21,17 +25,36 @@ object Prefs { private val sp: SharedPreferences by lazy { c.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE) } - var lastActive: Long - get() = sp.getLong(LAST_ACTIVE, -1) - set(value) = set(LAST_ACTIVE, System.currentTimeMillis()) + var lastActive: Long = prefDefaultLong + get() { + if (field == prefDefaultLong) field = sp.getLong(LAST_ACTIVE, -1) + return field + } + set(value) { + field = value + if (value != prefDefaultLong) set(LAST_ACTIVE, System.currentTimeMillis()) + } const val userIdDefault = -1L - var userId: Long - get() = sp.getLong(USER_ID, userIdDefault) - set(value) = set(USER_ID, value) + var userId: Long = prefDefaultLong + get() { + if (field == prefDefaultLong) field = sp.getLong(USER_ID, userIdDefault) + return field + } + set(value) { + field = value + if (value != prefDefaultLong) set(USER_ID, value) + } private fun set(key: String, value: Boolean) = sp.edit().putBoolean(key, value).apply() private fun set(key: String, value: Int) = sp.edit().putInt(key, value).apply() private fun set(key: String, value: Long) = sp.edit().putLong(key, value).apply() private fun set(key: String, value: String) = sp.edit().putString(key, value).apply() -}
\ No newline at end of file + + fun clear() { + L.d("Clearing Prefs") + sp.edit().clear().apply() + lastActive = prefDefaultLong + userId = prefDefaultLong + } +} diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/LoginWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/LoginWebView.kt deleted file mode 100644 index 17557b4d..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/LoginWebView.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.pitchedapps.frost.views - -import android.annotation.SuppressLint -import android.content.Context -import android.graphics.Bitmap -import android.net.UrlQuerySanitizer -import android.util.AttributeSet -import android.view.View -import android.webkit.WebResourceError -import android.webkit.WebResourceRequest -import android.webkit.WebView -import android.webkit.WebViewClient -import com.facebook.AccessToken -import com.pitchedapps.frost.facebook.FB_KEY -import com.pitchedapps.frost.facebook.retro.FrostApi.frostApi -import com.pitchedapps.frost.facebook.retro.Me -import com.pitchedapps.frost.facebook.retro.enqueueFrost -import com.pitchedapps.frost.utils.L -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response - -/** - * Created by Allan Wang on 2017-05-29. - */ -class LoginWebView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : WebView(context, attrs, defStyleAttr) { - - init { - setupWebview() - } - - @SuppressLint("SetJavaScriptEnabled") - fun setupWebview() { - settings.javaScriptEnabled = true - setLayerType(View.LAYER_TYPE_HARDWARE, null) - setWebViewClient(object : WebViewClient() { - override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { - super.onReceivedError(view, request, error) - L.e("Error ${request}") - } - - override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { - super.onPageStarted(view, url, favicon) - L.d("Loading $url") - } - - override fun onPageFinished(view: WebView?, url: String?) { - super.onPageFinished(view, url) - if (url == null) return - val sanitizer = UrlQuerySanitizer(url) - val accessToken = sanitizer.getValue("access_token") - val expiresIn = sanitizer.getValue("expires_in") - val grantedScopes = sanitizer.getValue("granted_scopes") - val deniedScopes = sanitizer.getValue("deniedScopes") - - - L.d("Loaded $url") - } - }) - } - - fun saveAccessToken(accessToken: String, expiresIn: String, grantedScopes: String?, deniedScopes: String?) { - L.d("Granted $grantedScopes") - L.d("Denied $deniedScopes") - frostApi.me().enqueueFrost { call, response -> - - } - - } - -} diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt index d537d623..27312763 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt @@ -1,8 +1,7 @@ -package com.pitchedapps.frost.views +package com.pitchedapps.frost.web import android.annotation.SuppressLint import android.content.Context -import android.graphics.Bitmap import android.support.v4.view.MotionEventCompat import android.support.v4.view.NestedScrollingChild import android.support.v4.view.NestedScrollingChildHelper @@ -10,12 +9,13 @@ import android.support.v4.view.ViewCompat import android.util.AttributeSet import android.view.MotionEvent import android.view.View -import android.webkit.* -import com.pitchedapps.frost.facebook.FbCookie -import com.pitchedapps.frost.utils.L +import android.webkit.WebView +import com.pitchedapps.frost.events.WebEvent import com.pitchedapps.frost.utils.ObservableContainer import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe enum class WebStatus { LOADING, LOADED, ERROR @@ -37,7 +37,8 @@ class FrostWebView @JvmOverloads constructor( private val scrollOffset = IntArray(2) private val scrollConsumed = IntArray(2) private var nestedOffsetY: Int = 0 - override val observable: Subject<WebStatus> + override val observable: Subject<WebStatus> //TODO see if we need this + var baseUrl: String? = null init { isNestedScrollingEnabled = true @@ -49,25 +50,12 @@ class FrostWebView @JvmOverloads constructor( fun setupWebview() { settings.javaScriptEnabled = true setLayerType(View.LAYER_TYPE_HARDWARE, null) - setWebViewClient(object : WebViewClient() { - override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { - super.onReceivedError(view, request, error) - observable.onNext(WebStatus.ERROR) - L.e("FWV Error ${request}") - } - - override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) { - super.onPageStarted(view, url, favicon) - observable.onNext(WebStatus.LOADING) - L.d("FWV Loading $url") - } + setWebViewClient(FrostWebViewClient(observable)) + } - override fun onPageFinished(view: WebView, url: String) { - super.onPageFinished(view, url) - observable.onNext(WebStatus.LOADED) - FbCookie.checkUserId(url, CookieManager.getInstance().getCookie(url)) - } - }) + override fun loadUrl(url: String?) { + if (url != null) + super.loadUrl(url) } override fun onTouchEvent(ev: MotionEvent): Boolean { @@ -110,6 +98,19 @@ class FrostWebView @JvmOverloads constructor( return returnValue } + override fun onAttachedToWindow() { + super.onAttachedToWindow() + EventBus.getDefault().register(this); + } + + override fun onDetachedFromWindow() { + EventBus.getDefault().unregister(this) + super.onDetachedFromWindow() + } + + @Subscribe + fun webEvent(event: WebEvent) = event.execute(this) + // Nested Scroll implements override fun setNestedScrollingEnabled(enabled: Boolean) { childHelper.isNestedScrollingEnabled = enabled diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt new file mode 100644 index 00000000..14fcc22a --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt @@ -0,0 +1,48 @@ +package com.pitchedapps.frost.web + +import android.graphics.Bitmap +import android.webkit.* +import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.utils.L +import io.reactivex.subjects.Subject + +/** + * Created by Allan Wang on 2017-05-31. + */ +class FrostWebViewClient(val observable: Subject<WebStatus>) : WebViewClient() { + + private var injectionCount: Int = 0 + + companion object { + //Collections of jewels mapped with url match -> id + val jewelMap: Map<String, String> = mapOf("a" to "b") + fun test() { + + } + } + + override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { + super.onReceivedError(view, request, error) + observable.onNext(WebStatus.ERROR) + L.e("FWV Error ${request}") + } + + override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) { + super.onPageStarted(view, url, favicon) + injectionCount = 0 + observable.onNext(WebStatus.LOADING) + L.d("FWV Loading $url") + if (url.contains("logout.php")) FbCookie.logout() + } + + override fun onPageFinished(view: WebView, url: String) { + super.onPageFinished(view, url) + observable.onNext(WebStatus.LOADED) + FbCookie.checkUserId(url, CookieManager.getInstance().getCookie(url)) + } + + fun logout() { + + } + +}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/SwipeRefreshBase.kt index 59d42722..0e303e49 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshBase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/SwipeRefreshBase.kt @@ -1,11 +1,10 @@ -package com.pitchedapps.frost.views +package com.pitchedapps.frost.web import android.content.Context import android.support.v4.widget.SwipeRefreshLayout import android.util.AttributeSet import android.view.MotionEvent import android.webkit.WebView -import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Utils diff --git a/app/src/main/res/layout/swipe_webview.xml b/app/src/main/res/layout/swipe_webview.xml index 87df67b2..4873b6cc 100644 --- a/app/src/main/res/layout/swipe_webview.xml +++ b/app/src/main/res/layout/swipe_webview.xml @@ -1,15 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> -<com.pitchedapps.frost.views.SwipeRefreshBase xmlns:android="http://schemas.android.com/apk/res/android" +<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent"> - <com.pitchedapps.frost.views.FrostWebView + <com.pitchedapps.frost.web.FrostWebView android:id="@+id/frost_webview" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="true" android:focusableInTouchMode="true" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> -</com.pitchedapps.frost.views.SwipeRefreshBase> +</android.support.v4.widget.SwipeRefreshLayout> diff --git a/app/src/test/kotlin/com/pitchedapps/frost/BaseUnitTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/BaseUnitTest.kt index 55208aae..43d6bbf9 100644 --- a/app/src/test/kotlin/com/pitchedapps/frost/BaseUnitTest.kt +++ b/app/src/test/kotlin/com/pitchedapps/frost/BaseUnitTest.kt @@ -7,6 +7,7 @@ import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment import org.robolectric.annotation.Config +import timber.log.Timber /** * Created by Allan Wang on 2017-05-30. @@ -22,4 +23,14 @@ abstract class BaseUnitTest { val context: Context get() = RuntimeEnvironment.application + + init { + Timber.plant(TestTree()) + } + + internal class TestTree : Timber.Tree() { + override fun log(priority: Int, tag: String, message: String, t: Throwable?) { + System.out.println("$tag-$priority: $message") + } + } } diff --git a/app/src/test/kotlin/com/pitchedapps/frost/utils/PrefsTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/utils/PrefsTest.kt new file mode 100644 index 00000000..56ec4c02 --- /dev/null +++ b/app/src/test/kotlin/com/pitchedapps/frost/utils/PrefsTest.kt @@ -0,0 +1,41 @@ +package com.pitchedapps.frost.utils + +import org.junit.Before +import org.junit.Test +import kotlin.test.assertEquals + +/** + * Created by Allan Wang on 2017-05-31. + */ +class PrefsTest { + + //Replicate logic + var test: Long = -1L + get() { + if (field == -1L) field = file + return field + } + set(value) { + field = value + if (value != -1L) file = value + } + + var file: Long = -1L + + @Before + fun verify() { + test = -1L + file = -1L + } + + @Test + fun laziness() { + assertEquals(-1L, test) + file = 2L + assertEquals(2L, test) + file = -3L + assertEquals(2L, test) + test = 3L + assertEquals(3L, file) + } +}
\ No newline at end of file |