aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/build.gradle6
-rw-r--r--app/src/main/AndroidManifest.xml39
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/dbflow/DbUtils.kt (renamed from app/src/main/kotlin/com/pitchedapps/frost/utils/DbUtils.kt)5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt22
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt45
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/UrlData.kt28
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt21
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt23
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsBuilder.kt36
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt24
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/NotificationReceiver.kt20
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/GlideUtils.kt26
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt37
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/LoginWebView.kt73
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt (renamed from app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt)49
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt48
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/SwipeRefreshBase.kt (renamed from app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshBase.kt)3
-rw-r--r--app/src/main/res/layout/swipe_webview.xml6
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/BaseUnitTest.kt11
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/utils/PrefsTest.kt41
-rw-r--r--gradle.properties12
26 files changed, 346 insertions, 258 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
diff --git a/gradle.properties b/gradle.properties
index 00849d8a..39557759 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -21,18 +21,18 @@ VERSION_NAME=0.1
ANDROID_SUPPORT_LIBS=25.3.1
TIMBER=4.5.1
MD=0.9.4.3
-ICONICS=2.8.3
+ICONICS=2.8.5
IICON_GOOGLE=3.0.1.0
IICON_MATERIAL=2.2.0.2
IICON_COMMUNITY=1.9.32.1
-BUTTERKNIFE=8.5.1
+BUTTERKNIFE=8.6.0
SEARCH_VIEW=4.0
-RX_JAVA=2.0.7
+RX_JAVA=2.1.0
RX_ANDROID=2.0.1
RX_BINDING=2.0.0
JSOUP=1.10.2
FB_SDK=[4,5)
-STETHO=1.4.2
+STETHO=1.5.0
ANKO=0.10.0
GLIDE=4.0.0-RC0
RETROFIT=2.2.0
@@ -41,4 +41,6 @@ SQL_CIPHER=3.5.7
OKHTTP_INTERCEPTOR=3.6.0
ROBOELECTRIC=3.3.2
AUTO=1.4.1
-AUTO_VALUE_PARCEL=0.2.5 \ No newline at end of file
+AUTO_VALUE_PARCEL=0.2.5
+RX_PREFS=2.0.0-RC2
+EVENT_BUS=3.0.0 \ No newline at end of file