aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-06-01 00:21:04 -0700
committerAllan Wang <me@allanwang.ca>2017-06-01 00:21:04 -0700
commit4cbcabb122e4bdf5d8e3eb67213ec7270d7aa9f0 (patch)
tree93ed7ff19412da306c6e7abf7f38fe035ab88e10 /app
parent8618670b82641d5fbaec9c333f1290bab429ce27 (diff)
downloadfrost-4cbcabb122e4bdf5d8e3eb67213ec7270d7aa9f0.tar.gz
frost-4cbcabb122e4bdf5d8e3eb67213ec7270d7aa9f0.tar.bz2
frost-4cbcabb122e4bdf5d8e3eb67213ec7270d7aa9f0.zip
working injectors and redid tabs db
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle10
-rw-r--r--app/src/main/AndroidManifest.xml4
-rw-r--r--app/src/main/assets/facebook.scss11
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FbActivity.kt21
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt64
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt21
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt62
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt1
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTabs.kt24
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbToken.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostApi.kt64
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostData.kt8
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostInterceptor.kt29
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/IFrost.kt36
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt25
-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.kt71
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/SettingsFragment.kt31
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt83
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt14
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt13
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/injector/JsBuilderTest.kt14
25 files changed, 318 insertions, 356 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 1acfb528..362ac6b8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -93,14 +93,12 @@ dependencies {
compile "org.jsoup:jsoup:${JSOUP}"
- compile "com.facebook.android:facebook-android-sdk:${FB_SDK}"
-
compile "org.jetbrains.anko:anko:${ANKO}"
- compile "com.squareup.retrofit2:retrofit:${RETROFIT}"
- compile "com.squareup.retrofit2:adapter-rxjava2:${RETROFIT}"
- compile "com.squareup.retrofit2:converter-gson:${RETROFIT}"
- compile "com.squareup.okhttp3:logging-interceptor:${OKHTTP_INTERCEPTOR}"
+// compile "com.squareup.retrofit2:retrofit:${RETROFIT}"
+// compile "com.squareup.retrofit2:adapter-rxjava2:${RETROFIT}"
+// compile "com.squareup.retrofit2:converter-gson:${RETROFIT}"
+// compile "com.squareup.okhttp3:logging-interceptor:${OKHTTP_INTERCEPTOR}"
compile "com.github.bumptech.glide:glide:${GLIDE}"
annotationProcessor "com.github.bumptech.glide:compiler:${GLIDE}"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d44aa950..efda18a2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,10 +2,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pitchedapps.frost">
- <!-- To auto-complete the email text field in the login form with the user's emails -->
- <uses-permission android:name="android.permission.GET_ACCOUNTS" />
- <uses-permission android:name="android.permission.READ_PROFILE" />
- <uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
diff --git a/app/src/main/assets/facebook.scss b/app/src/main/assets/facebook.scss
new file mode 100644
index 00000000..0798eb8a
--- /dev/null
+++ b/app/src/main/assets/facebook.scss
@@ -0,0 +1,11 @@
+$text: #fff;
+$background: #000;
+$transparent: transparent;
+
+#header[data-sigil="MTopBlueBarHeader"], #header-notices {
+ display: None !important;
+}
+
+textarea, ._2gn4 {
+ background-color: $transparent !important;
+}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FbActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/FbActivity.kt
deleted file mode 100644
index 0132a4db..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/FbActivity.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.pitchedapps.frost
-
-import android.os.Bundle
-import android.support.annotation.CallSuper
-import android.support.v7.app.AppCompatActivity
-import com.facebook.AccessToken
-import com.pitchedapps.frost.utils.L
-
-/**
- * Created by Allan Wang on 2017-05-29.
- */
-open class FbActivity : AppCompatActivity() {
- var accessToken: AccessToken? = null
-
- @CallSuper
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- accessToken = AccessToken.getCurrentAccessToken()
- L.e("Access ${accessToken?.token}")
- }
-} \ 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 b5e7f5df..068cf739 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
@@ -2,7 +2,6 @@ package com.pitchedapps.frost
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
@@ -23,7 +22,6 @@ class FrostApp : Application() {
FlowManager.init(FlowConfig.Builder(this).build())
Prefs(this)
GlideUtils(this)
- FrostApi(this)
FbCookie()
super.onCreate()
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt
deleted file mode 100644
index 8ef60991..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.pitchedapps.frost
-
-import android.content.Intent
-import android.content.pm.PackageInstaller
-import android.os.Bundle
-import android.widget.Button
-import com.facebook.CallbackManager
-import com.facebook.FacebookCallback
-import com.facebook.FacebookException
-import com.facebook.login.LoginBehavior
-import com.facebook.login.LoginManager
-import com.facebook.login.LoginResult
-import com.facebook.login.widget.LoginButton
-import com.pitchedapps.frost.utils.L
-import java.util.*
-
-
-/**
- * Created by Allan Wang on 2017-05-29.
- */
-class LoginActivity : FbActivity() {
- lateinit var callback: CallbackManager
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.login_teest)
- val loginButton = findViewById(R.id.login_button) as LoginButton
- loginButton.loginBehavior = LoginBehavior.WEB_VIEW_ONLY
- loginButton.setReadPermissions("email")
- val switchh = findViewById(R.id.switchh) as Button
- switchh.setOnClickListener {
- startActivity(Intent(this, MainActivity::class.java))
- finish()
- }
- // If using in a fragment
-// loginButton.setFragment(this)
- // Other app specific specialization
-
- // Callback registration
- callback = CallbackManager.Factory.create()
- loginButton.registerCallback(callback, object : FacebookCallback<LoginResult> {
- override fun onSuccess(loginResult: LoginResult) {
- L.e("Success")
- L.e("Success ${loginResult.accessToken.token}")
- }
-
- override fun onCancel() {
- // App code
- L.e("Cancel")
- }
-
- override fun onError(exception: FacebookException) {
- // App code
- L.e("Error")
- }
- })
-
-// LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile"));
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- callback.onActivityResult(requestCode, resultCode, data)
- }
-} \ 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 7bff3b58..41de3578 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt
@@ -1,6 +1,5 @@
package com.pitchedapps.frost
-import android.content.Intent
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
@@ -13,16 +12,14 @@ import android.support.v7.widget.Toolbar
import android.view.Menu
import android.view.MenuItem
import butterknife.ButterKnife
-import com.pitchedapps.frost.dbflow.FbTab
import com.pitchedapps.frost.dbflow.loadFbTabs
import com.pitchedapps.frost.dbflow.saveAsync
-import com.pitchedapps.frost.facebook.retro.FrostApi.frostApi
-import com.pitchedapps.frost.facebook.retro.enqueueFrost
+import com.pitchedapps.frost.facebook.FbTab
import com.pitchedapps.frost.fragments.BaseFragment
import com.pitchedapps.frost.fragments.WebFragment
-import com.pitchedapps.frost.utils.*
-import io.reactivex.subjects.PublishSubject
-import io.reactivex.subjects.Subject
+import com.pitchedapps.frost.utils.Changelog
+import com.pitchedapps.frost.utils.bindView
+import com.pitchedapps.frost.utils.toDrawable
class MainActivity : AppCompatActivity() {
@@ -38,7 +35,7 @@ class MainActivity : AppCompatActivity() {
ButterKnife.bind(this)
setSupportActionBar(toolbar)
- adapter = SectionsPagerAdapter(supportFragmentManager, loadFbTabs(this@MainActivity))
+ adapter = SectionsPagerAdapter(supportFragmentManager, loadFbTabs())
viewPager.adapter = adapter
viewPager.offscreenPageLimit = 5
setupTabs()
@@ -69,11 +66,11 @@ class MainActivity : AppCompatActivity() {
// as you specify a parent activity in AndroidManifest.xml.
when (item.itemId) {
R.id.action_settings -> {
- startActivity(Intent(this, LoginActivity::class.java))
- finish()
+// startActivity(Intent(this, LoginActivity::class.java))
+// finish()
}
R.id.action_changelog -> Changelog.show(this)
- R.id.action_call -> frostApi.me().enqueueFrost { _, response -> L.e(response.toString()) }
+ R.id.action_call -> {}
R.id.action_db -> adapter.pages.saveAsync(this)
R.id.action_restart -> {
finish();
@@ -104,6 +101,6 @@ class MainActivity : AppCompatActivity() {
override fun getCount() = pages.size
- override fun getPageTitle(position: Int): CharSequence = pages[position].title
+ override fun getPageTitle(position: Int): CharSequence = getString(pages[position].titleId)
}
}
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 bfd0b0fe..bed50527 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/FbTabsDb.kt
@@ -1,15 +1,9 @@
package com.pitchedapps.frost.dbflow
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.facebook.FbTab
import com.pitchedapps.frost.utils.L
import com.raizlabs.android.dbflow.annotation.Database
-import com.raizlabs.android.dbflow.annotation.ForeignKey
import com.raizlabs.android.dbflow.annotation.PrimaryKey
import com.raizlabs.android.dbflow.annotation.Table
import com.raizlabs.android.dbflow.kotlinextensions.from
@@ -26,61 +20,21 @@ object FbTabsDb {
const val VERSION = 1
}
-data class FbTab(val title: String, val icon: IIcon, val url: String)
-
-@Table(database = FbTabsDb::class, allFields = true)
-data class FbTabModel(
- var title: String = "",
- @ForeignKey(saveForeignKeyModel = true, deleteForeignKeyModel = false) var icon: IIconModel = IIconModel(),
- @PrimaryKey var url: String = "") : BaseModel() {
- constructor(fbTab: FbTab) : this(fbTab.title, IIconModel(fbTab.icon), fbTab.url)
-
- fun toFbTab() = FbTab(title, icon.toIIcon(), url)
-}
-
@Table(database = FbTabsDb::class, allFields = true)
-data class IIconModel(var type: Int = -1, @PrimaryKey var name: String = "") {
- constructor(icon: IIcon) : this(when (icon) {
- is CommunityMaterial.Icon -> 0
- is GoogleMaterial.Icon -> 1
- is MaterialDesignIconic.Icon -> 2
- else -> -1
- }, icon.toString())
+data class FbTabModel(@PrimaryKey var position: Int = -1, var tab: FbTab = FbTab.FEED) : BaseModel()
- fun toIIcon(): IIcon = when (type) {
- 0 -> CommunityMaterial.Icon.valueOf(name)
- 1 -> GoogleMaterial.Icon.valueOf(name)
- 2 -> MaterialDesignIconic.Icon.valueOf(name)
- else -> CommunityMaterial.Icon.cmd_newspaper
- }
-}
-
-const val FB_URL_BASE = "https://m.facebook.com/"
//const val FB_URL_BASE = "https://touch.facebook.com/"
-enum class FbUrl(@StringRes val titleId: Int, val icon: IIcon, relativeUrl: 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, ""),
- 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?disable_interstitial=1"),
- NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "notifications");
-
- val url = "$FB_URL_BASE$relativeUrl"
- fun tabInfo(c: Context) = FbTab(c.getString(titleId), icon, url)
-}
-
//BOOKMARKS("https://touch.facebook.com/bookmarks"),
//SEARCH("https://touch.facebook.com/search"),
-fun loadFbTabs(c: Context): List<FbTab> {
- val tabs: List<FbTabModel>? = SQLite.select().from(FbTabModel::class).queryList()
- if (tabs?.isNotEmpty() ?: false) return tabs!!.map { it.toFbTab() }
- L.e("No tabs; loading default")
- return listOf(FbUrl.FEED, FbUrl.MESSAGES, FbUrl.FRIENDS, FbUrl.NOTIFICATIONS).map { it.tabInfo(c) }
+fun loadFbTabs(): List<FbTab> {
+ val tabs: List<FbTabModel>? = SQLite.select().from(FbTabModel::class).orderBy(FbTabModel_Table.position, true).queryList()
+ if (tabs?.isNotEmpty() ?: false) return tabs!!.map { it.tab }
+ L.d("No tabs; loading default")
+ return listOf(FbTab.FEED, FbTab.MESSAGES, FbTab.FRIENDS, FbTab.NOTIFICATIONS)
}
fun List<FbTab>.saveAsync(c: Context) {
- map { FbTabModel(it) }.replace(c, FbTabsDb.NAME)
+ mapIndexed { index, fbTab -> FbTabModel(index, fbTab) }.replace(c, FbTabsDb.NAME)
} \ 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 3316bb65..e44b872a 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
@@ -1,7 +1,6 @@
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
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTabs.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTabs.kt
new file mode 100644
index 00000000..d391d20f
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTabs.kt
@@ -0,0 +1,24 @@
+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
+
+enum class FbTab(@StringRes val titleId: Int, val icon: IIcon, relativeUrl: 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, ""),
+ 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?disable_interstitial=1&rdr"),
+ NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "notifications");
+
+ val url = "$FB_URL_BASE$relativeUrl"
+}
+
+const val FACEBOOK_COM = "facebook.com"
+const val FB_URL_BASE = "https://m.facebook.com/" \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbToken.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbToken.kt
deleted file mode 100644
index 22dc25f7..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbToken.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.pitchedapps.frost.facebook
-
-import com.facebook.AccessToken
-
-/**
- * Created by Allan Wang on 2017-05-30.
- */
-val token: String?
- get() = AccessToken.getCurrentAccessToken()?.token
-
-fun setToken() {
-
-} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostApi.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostApi.kt
deleted file mode 100644
index f82c041c..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostApi.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.pitchedapps.frost.facebook.retro
-
-import android.content.Context
-import com.facebook.stetho.okhttp3.StethoInterceptor
-import com.google.gson.GsonBuilder
-import com.pitchedapps.frost.BuildConfig
-import com.pitchedapps.frost.utils.L
-import io.reactivex.schedulers.Schedulers
-import okhttp3.*
-import okhttp3.logging.HttpLoggingInterceptor
-import retrofit2.Retrofit
-import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
-import retrofit2.converter.gson.GsonConverterFactory
-import java.io.File
-
-/**
- * Created by Allan Wang on 2017-05-30.
- *
- * API for data retrieval
- */
-object FrostApi {
-
- lateinit var frostApi: IFrost
-
- operator fun invoke(context: Context) {
- val cacheDir = File(context.cacheDir, "responses")
- val cacheSize = 5L * 1024 * 1024 //10MiB
- val cache = Cache(cacheDir, cacheSize)
-
- val client = OkHttpClient.Builder()
- .addInterceptor(FrostInterceptor(context))
- .cookieJar(object : CookieJar {
- override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
- L.e("COOKIES")
- L.e(url.toString())
- cookies.forEach { c -> L.e(c.toString()) }
- }
-
- override fun loadForRequest(url: HttpUrl): List<Cookie> {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
-
- })
- .cache(cache)
-
-
- //add logger and stetho last
-
- if (BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "releaseTest") { //log if not full release
- client.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
- client.addNetworkInterceptor(StethoInterceptor())
- }
-
- val gson = GsonBuilder().setLenient()
-
- val retrofit = Retrofit.Builder()
- .baseUrl("https://touch.facebook.com/")
- .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
- .addConverterFactory(GsonConverterFactory.create(gson.create()))
- .client(client.build())
- .build();
- frostApi = retrofit.create(IFrost::class.java)
- }
-} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostData.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostData.kt
deleted file mode 100644
index 07d686a7..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostData.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.pitchedapps.frost.facebook.retro
-
-/**
- * Created by Allan Wang on 2017-05-30.
- *
- * Collection of Graph API outputs
- */
-data class Me(val name: String, val id: String) \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostInterceptor.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostInterceptor.kt
deleted file mode 100644
index f745aedf..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/FrostInterceptor.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.pitchedapps.frost.facebook.retro
-
-import android.content.Context
-import com.pitchedapps.frost.facebook.token
-import com.pitchedapps.frost.utils.Utils
-import okhttp3.Interceptor
-import okhttp3.Response
-
-/**
- * Created by Allan Wang on 2017-05-30.
- */
-private val maxStale = 60 * 60 * 24 * 28 //maxAge to get from cache if online (4 weeks)
-const val ACCESS_TOKEN = "access_token"
-
-class FrostInterceptor(val context: Context) : Interceptor {
-
- override fun intercept(chain: Interceptor.Chain): Response? {
- val request = chain.request()
- val requestBuilder = request.newBuilder()
- val urlBase = request.url()
- val urlWithToken = urlBase.newBuilder()
- if (urlBase.queryParameter(ACCESS_TOKEN) == null && token != null)
- urlWithToken.addQueryParameter(ACCESS_TOKEN, token)
- requestBuilder.url(urlWithToken.build())
- if (!Utils.isNetworkAvailable(context)) requestBuilder.addHeader("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
- return chain.proceed(requestBuilder.build())
- }
-
-} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/IFrost.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/IFrost.kt
deleted file mode 100644
index b9048fe0..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/retro/IFrost.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.pitchedapps.frost.facebook.retro
-
-import com.pitchedapps.frost.facebook.token
-import com.pitchedapps.frost.utils.L
-import okhttp3.ResponseBody
-import retrofit2.Call
-import retrofit2.Callback
-import retrofit2.Response
-import retrofit2.http.GET
-import retrofit2.http.Query
-
-/**
- * Created by Allan Wang on 2017-05-30.
- */
-interface IFrost {
-
- @GET("me")
- fun me(): Call<ResponseBody>
-
-
-}
-
-fun <T> Call<T>.enqueueFrost(success: (call: Call<T>, response: Response<T>) -> Unit) {
- this.enqueue(object : Callback<T> {
- override fun onFailure(call: Call<T>?, t: Throwable?) {
- L.e("Frost enqueue error")
- }
-
- override fun onResponse(call: Call<T>, response: Response<T>) {
- if (response.isSuccessful && !call.isCanceled)
- success.invoke(call, response)
- else
- L.e("Frost response received but not successful")
- }
- })
-} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt
new file mode 100644
index 00000000..74a55888
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt
@@ -0,0 +1,25 @@
+package com.pitchedapps.frost.injectors
+
+import android.webkit.WebView
+import com.pitchedapps.frost.utils.L
+
+/**
+ * Created by Allan Wang on 2017-05-31.
+ */
+enum class CssAssets(val file: String) {
+ BASE("facebook.min.css");
+
+ var content: String? = null
+ var injector: JsInjector? = null
+
+ fun inject(webView: WebView, callback: ((String) -> Unit)?) {
+ if (injector == null) {
+ if (content == null)
+ content = webView.context.assets.open(file).bufferedReader().use { it.readText() }
+ injector = JsBuilder().css(content!!).build()
+ }
+ injector!!.inject(webView, callback)
+ L.d("CSS ${injector!!.function}")
+ }
+
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsBuilder.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsBuilder.kt
deleted file mode 100644
index 9844e5d5..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsBuilder.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-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 2d1659cc..c7b4eaf8 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
@@ -5,8 +5,73 @@ import android.webkit.WebView
/**
* Created by Allan Wang on 2017-05-31.
*/
-object JsInjector {
- fun inject(webView: WebView) {
+enum class JsActions(val function: String) {
+ HIDE("style.display='none'"),
+ REMOVE("remove()")
+}
+class VariableGenerator {
+
+ var count = 0
+
+ val next: String
+ get() {
+ var key = count
+ count++
+ if (key == 0) return "a"
+ val name = StringBuilder()
+ while (key > 0) {
+ name.append(((key % 26) + 'a'.toInt()).toChar())
+ key /= 26
+ }
+ return name.toString()
+ }
+
+ fun reset() {
+ count = 0
+ }
+}
+
+class JsBuilder {
+
+ private val map: MutableMap<String, MutableSet<JsActions>> = mutableMapOf()
+ private val v = VariableGenerator()
+ private val css: StringBuilder by lazy { StringBuilder() }
+
+ fun append(action: JsActions, vararg ids: String): JsBuilder {
+ ids.forEach { id -> map[id]?.add(action) ?: map.put(id, mutableSetOf(action)) }
+ return this
+ }
+
+ fun css(css: String): JsBuilder {
+ this.css.append(css.trim())
+ return this
+ }
+
+ fun build() = JsInjector(toString())
+
+ override fun toString(): String {
+ v.reset()
+ val builder = StringBuilder().append("!function(){")
+ map.forEach { id, actions ->
+ if (actions.size == 1) {
+ builder.append("document.getElementById('$id').${actions.first().function};")
+ } else {
+ val name = v.next
+ builder.append("var $name=document.getElementById('$id');")
+ actions.forEach { a -> builder.append("$name.${a.function};") }
+ }
+ }
+ if (css.isNotBlank()) {
+ val name = v.next
+ builder.append("var $name=document.createElement('style');$name.innerHTML='$css';document.head.appendChild($name);")
+ }
+ return builder.append("}()").toString()
+ }
+}
+
+class JsInjector(val function: String) {
+ fun inject(webView: WebView, callback: ((String) -> Unit)? = null) {
+ webView.evaluateJavascript(function, { value -> callback?.invoke(value) })
}
-} \ No newline at end of file
+}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/SettingsFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/SettingsFragment.kt
new file mode 100644
index 00000000..78ad324a
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/SettingsFragment.kt
@@ -0,0 +1,31 @@
+package com.pitchedapps.frost.settings
+
+import android.os.Bundle
+import android.support.v7.preference.AndroidResources
+import android.support.v7.preference.PreferenceFragmentCompat
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.pitchedapps.frost.views.RippleCanvas
+import com.pitchedapps.frost.views.matchParent
+
+/**
+ * Created by Allan Wang on 2017-05-31.
+ */
+class SettingsFragment : PreferenceFragmentCompat() {
+
+ lateinit var ripple: RippleCanvas
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ val view = super.onCreateView(inflater, container, savedInstanceState)!!
+ val frame = view.findViewById(AndroidResources.ANDROID_R_LIST_CONTAINER) as ViewGroup
+ ripple = RippleCanvas(frame.context)
+ ripple.matchParent()
+ frame.addView(ripple, 0)
+ return view
+ }
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt
new file mode 100644
index 00000000..719a01cc
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt
@@ -0,0 +1,83 @@
+package com.pitchedapps.frost.views
+
+import android.animation.ValueAnimator
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.View
+
+/**
+ * Created by Allan Wang on 2016-11-17.
+ *
+ *
+ * Canvas drawn ripples that keep the previous color
+ * Extends to view dimensions
+ * Supports multiple ripples from varying locations
+ */
+class RippleCanvas @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : View(context, attrs, defStyleAttr) {
+ val paint: Paint = Paint()
+ var baseColor = Color.TRANSPARENT
+ val ripples: MutableList<Ripple> = mutableListOf()
+
+ init {
+ paint.isAntiAlias = true
+ paint.style = Paint.Style.FILL
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ canvas.drawColor(baseColor)
+ val itr = ripples.iterator()
+ while (itr.hasNext()) {
+ val r = itr.next()
+ paint.color = r.color
+ canvas.drawCircle(r.x, r.y, r.radius, paint)
+ if (r.radius == r.maxRadius) {
+ itr.remove()
+ baseColor = r.color
+ }
+ }
+ }
+
+ @JvmOverloads fun ripple(color: Int, startX: Float = 0f, startY: Float = 0f, duration: Int = 1000) {
+ var x = startX
+ var y = startY
+ val w = width.toFloat()
+ val h = height.toFloat()
+ if (x == MIDDLE)
+ x = w / 2
+ else if (x > w) x = 0f
+ if (y == MIDDLE)
+ y = h / 2
+ else if (y > h) y = 0f
+ val maxRadius = Math.hypot(Math.max(x, w - x).toDouble(), Math.max(y, h - y).toDouble()).toFloat()
+ val ripple = Ripple(color, x, y, 0f, maxRadius)
+ ripples.add(ripple)
+ val animator = ValueAnimator.ofFloat(0f, maxRadius)
+ animator.duration = duration.toLong()
+ animator.addUpdateListener { animation ->
+ ripple.setRadius(animation.animatedValue as Float)
+ invalidate()
+ }
+ animator.start()
+ }
+
+ fun set(color: Int) {
+ baseColor = color
+ ripples.clear()
+ invalidate()
+ }
+
+ inner class Ripple internal constructor(val color: Int, val x: Float, val y: Float, var radius: Float, val maxRadius: Float) {
+ internal fun setRadius(r: Float) {
+ radius = r
+ }
+ }
+
+ companion object {
+ val MIDDLE = -1.0f
+ }
+}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt
new file mode 100644
index 00000000..513287ef
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt
@@ -0,0 +1,14 @@
+package com.pitchedapps.frost.views
+
+import android.view.View
+import android.view.ViewGroup
+
+/**
+ * Created by Allan Wang on 2017-05-31.
+ */
+fun View.matchParent() {
+ with (layoutParams) {
+ height = ViewGroup.LayoutParams.MATCH_PARENT
+ width = ViewGroup.LayoutParams.MATCH_PARENT
+ }
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt
new file mode 100644
index 00000000..8367255a
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt
@@ -0,0 +1,15 @@
+package com.pitchedapps.frost.web
+
+import android.webkit.ConsoleMessage
+import android.webkit.WebChromeClient
+import com.pitchedapps.frost.utils.L
+
+/**
+ * Created by Allan Wang on 2017-05-31.
+ */
+class FrostChromeClient:WebChromeClient() {
+ override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
+ L.d("Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}")
+ return super.onConsoleMessage(consoleMessage)
+ }
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt
index 27312763..de7860da 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt
@@ -49,8 +49,10 @@ class FrostWebView @JvmOverloads constructor(
@SuppressLint("SetJavaScriptEnabled")
fun setupWebview() {
settings.javaScriptEnabled = true
+ settings.domStorageEnabled = true
setLayerType(View.LAYER_TYPE_HARDWARE, null)
setWebViewClient(FrostWebViewClient(observable))
+ setWebChromeClient(FrostChromeClient())
}
override fun loadUrl(url: String?) {
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 14fcc22a..379bb22d 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt
@@ -1,8 +1,11 @@
package com.pitchedapps.frost.web
import android.graphics.Bitmap
+import android.view.View
import android.webkit.*
+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 io.reactivex.subjects.Subject
@@ -11,11 +14,10 @@ import io.reactivex.subjects.Subject
*/
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() {
}
@@ -29,16 +31,21 @@ class FrostWebViewClient(val observable: Subject<WebStatus>) : WebViewClient() {
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(FACEBOOK_COM)) return
if (url.contains("logout.php")) FbCookie.logout()
+ view.visibility = View.INVISIBLE
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
+ if (!url.contains(FACEBOOK_COM)) return
observable.onNext(WebStatus.LOADED)
FbCookie.checkUserId(url, CookieManager.getInstance().getCookie(url))
+ CssAssets.BASE.inject(view, {
+ view.visibility = View.VISIBLE
+ })
}
fun logout() {
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/injector/JsBuilderTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/injector/JsBuilderTest.kt
new file mode 100644
index 00000000..d5fcdc50
--- /dev/null
+++ b/app/src/test/kotlin/com/pitchedapps/frost/injector/JsBuilderTest.kt
@@ -0,0 +1,14 @@
+package com.pitchedapps.frost.injector
+
+import com.pitchedapps.frost.injectors.JsInjector
+import org.junit.Test
+
+/**
+ * Created by Allan Wang on 2017-05-31.
+ */
+class JsBuilderTest {
+ @Test
+ fun misc() {
+ println(JsInjector.idRemovals.function)
+ }
+} \ No newline at end of file