aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt11
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt117
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt124
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Menu.kt192
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt48
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Notifications.kt38
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt48
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/iitems/MenuIItem.kt87
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/FrostRequestService.kt200
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt7
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt4
-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.kt4
17 files changed, 8 insertions, 888 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
index 0322a4bb..2f49b235 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
@@ -61,7 +61,6 @@ import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.formattedFbUrl
import com.pitchedapps.frost.kotlin.subscribeDuringJob
-import com.pitchedapps.frost.services.FrostRunnable
import com.pitchedapps.frost.utils.ARG_URL
import com.pitchedapps.frost.utils.ARG_USER_ID
import com.pitchedapps.frost.utils.BiometricUtils
@@ -224,9 +223,6 @@ abstract class WebOverlayActivityBase : BaseActivity(),
}
}
- FrostRunnable.propagate(this, intent)
- L.v { "Done propagation" }
-
swipeBack = kauSwipeOnCreate {
if (!Prefs.overlayFullScreenSwipe) edgeSize = 20.dpToPx
transitionSystemBars = false
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt
index a09b5d39..6f726b5b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt
@@ -23,8 +23,6 @@ import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.material_design_iconic_typeface_library.MaterialDesignIconic
import com.pitchedapps.frost.R
import com.pitchedapps.frost.fragments.BaseFragment
-import com.pitchedapps.frost.fragments.MenuFragment
-import com.pitchedapps.frost.fragments.NotificationFragment
import com.pitchedapps.frost.fragments.WebFragment
import com.pitchedapps.frost.utils.EnumBundle
import com.pitchedapps.frost.utils.EnumBundleCompanion
@@ -47,15 +45,10 @@ enum class FbItem(
FRIENDS(R.string.friends, GoogleMaterial.Icon.gmd_person_add, "friends/center/requests"),
GROUPS(R.string.groups, GoogleMaterial.Icon.gmd_group, "groups"),
MARKETPLACE(R.string.marketplace, GoogleMaterial.Icon.gmd_store, "marketplace"),
- MENU(R.string.menu, GoogleMaterial.Icon.gmd_menu, "settings", ::MenuFragment),
+ MENU(R.string.menu, GoogleMaterial.Icon.gmd_menu, "settings"),
MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "messages"),
NOTES(R.string.notes, CommunityMaterial.Icon2.cmd_note, "notes"),
- NOTIFICATIONS(
- R.string.notifications,
- MaterialDesignIconic.Icon.gmi_globe,
- "notifications",
- ::NotificationFragment
- ),
+ NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "notifications"),
ON_THIS_DAY(R.string.on_this_day, GoogleMaterial.Icon.gmd_today, "onthisday"),
PAGES(R.string.pages, GoogleMaterial.Icon.gmd_flag, "pages"),
PHOTOS(R.string.photos, GoogleMaterial.Icon.gmd_photo, "me/photos"),
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt
index b948506f..7900534c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt
@@ -17,58 +17,11 @@
package com.pitchedapps.frost.facebook.requests
import com.pitchedapps.frost.BuildConfig
-import com.pitchedapps.frost.facebook.FB_DTSG_MATCHER
-import com.pitchedapps.frost.facebook.FB_JSON_URL_MATCHER
-import com.pitchedapps.frost.facebook.FB_REV_MATCHER
-import com.pitchedapps.frost.facebook.FB_URL_BASE
-import com.pitchedapps.frost.facebook.FB_USER_MATCHER
import com.pitchedapps.frost.facebook.USER_AGENT
-import com.pitchedapps.frost.facebook.get
-import com.pitchedapps.frost.kotlin.Flyweight
-import com.pitchedapps.frost.utils.L
-import kotlinx.coroutines.GlobalScope
import okhttp3.Call
-import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.logging.HttpLoggingInterceptor
-import org.apache.commons.text.StringEscapeUtils
-
-/**
- * Created by Allan Wang on 21/12/17.
- */
-val fbAuth = Flyweight<String, RequestAuth>(GlobalScope, 3600000 /* an hour */) {
- it.getAuth()
-}
-
-/**
- * Underlying container for all fb requests
- */
-data class RequestAuth(
- val userId: Long = -1,
- val cookie: String = "",
- val fb_dtsg: String = "",
- val rev: String = ""
-) {
- val isComplete
- get() = userId > 0 && cookie.isNotEmpty() && fb_dtsg.isNotEmpty() && rev.isNotEmpty()
-}
-
-/**
- * Request container with the execution call
- */
-class FrostRequest<out T : Any?>(val call: Call, private val invoke: (Call) -> T) {
- fun invoke() = invoke(call)
-}
-
-internal inline fun <T : Any?> RequestAuth.frostRequest(
- noinline invoke: (Call) -> T,
- builder: Request.Builder.() -> Request.Builder // to ensure we don't do anything extra at the end
-): FrostRequest<T> {
- val request = cookie.requestBuilder()
- request.builder()
- return FrostRequest(request.call(), invoke)
-}
val httpClient: OkHttpClient by lazy {
val builder = OkHttpClient.Builder()
@@ -80,21 +33,6 @@ val httpClient: OkHttpClient by lazy {
builder.build()
}
-internal fun List<Pair<String, Any?>>.toForm(): FormBody {
- val builder = FormBody.Builder()
- forEach { (key, value) ->
- val v = value?.toString() ?: ""
- builder.add(key, v)
- }
- return builder.build()
-}
-
-internal fun List<Pair<String, Any?>>.withEmptyData(vararg key: String): List<Pair<String, Any?>> {
- val newList = toMutableList()
- newList.addAll(key.map { it to null })
- return newList
-}
-
internal fun String?.requestBuilder(): Request.Builder {
val builder = Request.Builder()
.header("User-Agent", USER_AGENT)
@@ -105,58 +43,3 @@ internal fun String?.requestBuilder(): Request.Builder {
}
fun Request.Builder.call(): Call = httpClient.newCall(build())
-
-fun String.getAuth(): RequestAuth {
- L.v { "Getting auth for ${hashCode()}" }
- var auth = RequestAuth(cookie = this)
- val id = FB_USER_MATCHER.find(this)[1]?.toLong() ?: return auth
- auth = auth.copy(userId = id)
- val call = this.requestBuilder()
- .url(FB_URL_BASE)
- .get()
- .call()
- call.execute().body()?.charStream()?.useLines { lines ->
- lines.forEach {
- val text = try {
- StringEscapeUtils.unescapeEcmaScript(it)
- } catch (ignore: Exception) {
- return@forEach
- }
- val fb_dtsg = FB_DTSG_MATCHER.find(text)[1]
- if (fb_dtsg != null) {
- auth = auth.copy(fb_dtsg = fb_dtsg)
- if (auth.isComplete) return auth
- }
-
- val rev = FB_REV_MATCHER.find(text)[1]
- if (rev != null) {
- auth = auth.copy(rev = rev)
- if (auth.isComplete) return auth
- }
- }
- }
-
- return auth
-}
-
-/**
- * Execute the call and attempt to check validity
- * Valid = not blank & no "error" instance
- */
-fun executeForNoError(call: Call): Boolean {
- val body = call.execute().body() ?: return false
- var empty = true
- body.charStream().useLines { lines ->
- lines.forEach {
- if (it.contains("error")) return false
- if (empty && it.isNotEmpty()) empty = false
- }
- }
- return !empty
-}
-
-fun getJsonUrl(call: Call): String? {
- val body = call.execute().body() ?: return null
- val url = FB_JSON_URL_MATCHER.find(body.string())[1] ?: return null
- return StringEscapeUtils.unescapeEcmaScript(url)
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt
index 1b5e8b99..0115d6fc 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt
@@ -16,38 +16,17 @@
*/
package com.pitchedapps.frost.facebook.requests
-import com.bumptech.glide.Priority
-import com.bumptech.glide.RequestBuilder
-import com.bumptech.glide.load.DataSource
-import com.bumptech.glide.load.Options
-import com.bumptech.glide.load.data.DataFetcher
-import com.bumptech.glide.load.model.ModelLoader
-import com.bumptech.glide.load.model.ModelLoaderFactory
-import com.bumptech.glide.load.model.MultiModelLoaderFactory
-import com.bumptech.glide.request.RequestOptions
-import com.bumptech.glide.request.target.Target
-import com.bumptech.glide.signature.ObjectKey
-import com.pitchedapps.frost.facebook.FB_IMAGE_ID_MATCHER
import com.pitchedapps.frost.facebook.FB_REDIRECT_URL_MATCHER
-import com.pitchedapps.frost.facebook.FB_URL_BASE
import com.pitchedapps.frost.facebook.formattedFbUrl
import com.pitchedapps.frost.facebook.get
import com.pitchedapps.frost.utils.L
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
-import okhttp3.Call
-import java.io.IOException
-import java.io.InputStream
/**
* Created by Allan Wang on 29/12/17.
*/
-fun RequestAuth.getFullSizedImage(fbid: Long) = frostRequest(::getJsonUrl) {
- url("${FB_URL_BASE}photo/view_full_size/?fbid=$fbid&__ajax__=&__user=$userId")
- get()
-}
/**
* Attempts to get the fbcdn url of the supplied image redirect url
@@ -65,106 +44,3 @@ suspend fun String.getFullSizedImageUrl(url: String, timeout: Long = 3000): Stri
null
}
}
-
-/**
- * Request loader for a potentially hd version of a url
- * In this case, each url may potentially return an id,
- * which may potentially be used to fetch a higher res image url
- * The following aims to allow such loading while adhering to Glide's lifecycle
- */
-data class HdImageMaybe(val url: String, val cookie: String) {
-
- val id: Long by lazy { FB_IMAGE_ID_MATCHER.find(url)[1]?.toLongOrNull() ?: -1 }
-
- val isValid: Boolean by lazy {
- id != -1L && cookie.isNotBlank()
- }
-}
-
-/*
- * The following was a test to see if hd image loading would work
- *
- * It's working and tested, though the improvements aren't really worth the extra data use
- * and reload
- */
-
-class HdImageLoadingFactory : ModelLoaderFactory<HdImageMaybe, InputStream> {
-
- override fun build(multiFactory: MultiModelLoaderFactory) = HdImageLoading()
-
- override fun teardown() = Unit
-}
-
-fun <T> RequestBuilder<T>.loadWithPotentialHd(model: HdImageMaybe) =
- thumbnail(clone().load(model.url))
- .load(model)
- .apply(RequestOptions().override(Target.SIZE_ORIGINAL))
-
-class HdImageLoading : ModelLoader<HdImageMaybe, InputStream> {
-
- override fun buildLoadData(
- model: HdImageMaybe,
- width: Int,
- height: Int,
- options: Options
- ): ModelLoader.LoadData<InputStream>? =
- if (!model.isValid) null
- else ModelLoader.LoadData(ObjectKey(model), HdImageFetcher(model))
-
- override fun handles(model: HdImageMaybe) = model.isValid
-}
-
-class HdImageFetcher(private val model: HdImageMaybe) : DataFetcher<InputStream> {
-
- @Volatile
- private var cancelled: Boolean = false
- private var urlCall: Call? = null
- private var inputStream: InputStream? = null
-
- private fun DataFetcher.DataCallback<in InputStream>.fail(msg: String) {
- onLoadFailed(RuntimeException(msg))
- }
-
- override fun getDataClass(): Class<InputStream> = InputStream::class.java
-
- override fun getDataSource(): DataSource = DataSource.REMOTE
-
- override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
- if (!model.isValid) return callback.fail("Model is invalid")
- val result: Result<InputStream?> = runCatching {
- runBlocking {
- withTimeout(20000L) {
- val auth = fbAuth.fetch(model.cookie).await()
- if (cancelled) throw RuntimeException("Cancelled")
- val url = auth.getFullSizedImage(model.id).invoke()
- ?: throw RuntimeException("Null url")
- if (cancelled) throw RuntimeException("Cancelled")
- if (!url.contains("png") && !url.contains("jpg")) throw RuntimeException("Invalid format")
- urlCall?.execute()?.body()?.byteStream()
- }
- }
- }
- if (result.isSuccess)
- callback.onDataReady(result.getOrNull())
- else
- callback.onLoadFailed(
- result.exceptionOrNull() as? Exception ?: RuntimeException("Failed")
- )
- }
-
- override fun cleanup() {
- try {
- inputStream?.close()
- } catch (e: IOException) {
- } finally {
- inputStream = null
- }
- }
-
- override fun cancel() {
- cancelled = true
- urlCall?.cancel()
- urlCall = null
- cleanup()
- }
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Menu.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Menu.kt
deleted file mode 100644
index dcb0ce10..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Menu.kt
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.pitchedapps.frost.facebook.requests
-
-import com.fasterxml.jackson.annotation.JsonCreator
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.fasterxml.jackson.databind.MapperFeature
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.pitchedapps.frost.facebook.FB_URL_BASE
-import com.pitchedapps.frost.facebook.formattedFbUrl
-import com.pitchedapps.frost.utils.L
-import okhttp3.Call
-import org.apache.commons.text.StringEscapeUtils
-import org.jsoup.Jsoup
-import java.io.IOException
-
-/**
- * Created by Allan Wang on 29/12/17.
- */
-fun RequestAuth.getMenuData(): FrostRequest<MenuData?> {
-
- val body = listOf(
- "fb_dtsg" to fb_dtsg,
- "__user" to userId
- ).withEmptyData("m_sess", "__dyn", "__req", "__ajax__")
-
- return frostRequest(::parseMenu) {
- url("${FB_URL_BASE}bookmarks/flyout/body/?id=u_0_2")
- post(body.toForm())
- }
-}
-
-fun parseMenu(call: Call): MenuData? {
- val fullString = call.execute().body()?.string() ?: return null
- var jsonString = fullString.substringAfter("bookmarkGroups", "")
- .substringAfter("[", "")
-
- if (jsonString.isBlank()) return null
-
- jsonString = "{ \"data\" : [${StringEscapeUtils.unescapeEcmaScript(jsonString)}"
-
- val mapper = ObjectMapper()
- .disable(MapperFeature.AUTO_DETECT_SETTERS)
-
- return try {
- val data = mapper.readValue(jsonString, MenuData::class.java)
-
- // parse footer content
-
- val footer = fullString.substringAfter("footerMarkup", "")
- .substringAfter("{", "")
- .substringBefore("}", "")
-
- val doc = Jsoup.parseBodyFragment(
- StringEscapeUtils.unescapeEcmaScript(
- StringEscapeUtils.unescapeEcmaScript(footer)
- )
- )
- val footerData = mutableListOf<MenuFooterItem>()
- val footerSmallData = mutableListOf<MenuFooterItem>()
-
- doc.select("a[href]").forEach {
- val text = it.text()
- it.parent()
- if (text.isEmpty()) return@forEach
- val href = it.attr("href").formattedFbUrl
- val item = MenuFooterItem(name = text, url = href)
- if (it.parent().tag().name == "span")
- footerSmallData.add(item)
- else
- footerData.add(item)
- }
-
- return data.copy(footer = MenuFooter(footerData, footerSmallData))
- } catch (e: IOException) {
- L.e(e) { "Menu parse fail" }
- null
- }
-}
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-data class MenuData(
- val data: List<MenuHeader> = emptyList(),
- val footer: MenuFooter = MenuFooter()
-) {
-
- @JsonCreator
- constructor(
- @JsonProperty("data") data: List<MenuHeader>?
- ) : this(data ?: emptyList(), MenuFooter())
-
- fun flatMapValid(): List<MenuItemData> {
- val items = mutableListOf<MenuItemData>()
- data.forEach {
- if (it.isValid) items.add(it)
- items.addAll(it.visible.filter(MenuItem::isValid))
- }
-
- items.addAll(footer.data.filter(MenuFooterItem::isValid))
- items.addAll(footer.smallData.filter(MenuFooterItem::isValid))
-
- return items
- }
-}
-
-interface MenuItemData {
- val isValid: Boolean
-}
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-data class MenuHeader(
- val id: String? = null,
- val header: String? = null,
- val visible: List<MenuItem> = emptyList(),
- val all: List<MenuItem> = emptyList()
-) : MenuItemData {
-
- @JsonCreator
- constructor(
- @JsonProperty("id") id: String?,
- @JsonProperty("header") header: String?,
- @JsonProperty("visible") visible: List<MenuItem>?,
- @JsonProperty("all") all: List<MenuItem>?,
- @JsonProperty("fake") fake: Boolean?
- ) : this(id, header, visible ?: emptyList(), all ?: emptyList())
-
- override val isValid: Boolean
- get() = !header.isNullOrBlank()
-}
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-data class MenuItem(
- val id: String? = null,
- val name: String? = null,
- val pic: String? = null,
- val url: String? = null,
- val badge: String? = null,
- val countDetails: String? = null
-) : MenuItemData {
-
- @JsonCreator
- constructor(
- @JsonProperty("id") id: String?,
- @JsonProperty("name") name: String?,
- @JsonProperty("pic") pic: String?,
- @JsonProperty("url") url: String?,
- @JsonProperty("count") badge: String?,
- @JsonProperty("count_details") countDetails: String?,
- @JsonProperty("fake") fake: Boolean?
- ) : this(
- id, name, pic?.formattedFbUrl,
- url?.formattedFbUrl,
- if (badge == "0") null else badge,
- countDetails
- )
-
- override val isValid: Boolean
- get() = !name.isNullOrBlank() && !url.isNullOrBlank()
-}
-
-data class MenuFooter(
- val data: List<MenuFooterItem> = emptyList(),
- val smallData: List<MenuFooterItem> = emptyList()
-) {
-
- val hasContent
- get() = data.isNotEmpty() || smallData.isNotEmpty()
-}
-
-data class MenuFooterItem(
- val name: String? = null,
- val url: String? = null,
- val isSmall: Boolean = false
-) : MenuItemData {
- override val isValid: Boolean
- get() = name != null && url != null
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt
deleted file mode 100644
index f350c547..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.pitchedapps.frost.facebook.requests
-
-import com.pitchedapps.frost.facebook.FB_URL_BASE
-import okhttp3.Call
-
-/**
- * Created by Allan Wang on 07/01/18.
- */
-fun RequestAuth.sendMessage(group: String, content: String): FrostRequest<Boolean> {
-
- // todo test more; only tested against tids=cid...
- val body = listOf(
- "tids" to group,
- "body" to content,
- "fb_dtsg" to fb_dtsg,
- "__user" to userId
- ).withEmptyData("m_sess", "__dyn", "__req", "__ajax__")
-
- return frostRequest(::validateMessage) {
- url("${FB_URL_BASE}messages/send")
- post(body.toForm())
- }
-}
-
-/**
- * Messages are a bit weird with their responses
- */
-private fun validateMessage(call: Call): Boolean {
- val body = call.execute().body() ?: return false
- // todo
- return true
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Notifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Notifications.kt
deleted file mode 100644
index bf974034..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Notifications.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.pitchedapps.frost.facebook.requests
-
-import com.pitchedapps.frost.facebook.FB_URL_BASE
-
-/**
- * Created by Allan Wang on 29/12/17.
- */
-fun RequestAuth.markNotificationRead(notifId: Long): FrostRequest<Boolean> {
-
- val body = listOf(
- "click_type" to "notification_click",
- "id" to notifId,
- "target_id" to "null",
- "fb_dtsg" to fb_dtsg,
- "__user" to userId
- ).withEmptyData("m_sess", "__dyn", "__req", "__ajax__")
-
- return frostRequest(::executeForNoError) {
- url("${FB_URL_BASE}a/jewel_notifications_log.php")
- post(body.toForm())
- }
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt
index 50bae16c..e73acc97 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt
@@ -67,7 +67,7 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, Dyna
data: FbItem,
position: Int
): BaseFragment {
- val fragment = if (useFallback || !Prefs.nativeUi) WebFragment() else base()
+ val fragment = if (useFallback) WebFragment() else base()
val d = if (data == FbItem.FEED) FeedSort(Prefs.feedSort).item else data
fragment.withArguments(
ARG_URL to d.url,
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt
index 54ea388d..f45ffa6d 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt
@@ -16,32 +16,20 @@
*/
package com.pitchedapps.frost.fragments
-import com.mikepenz.fastadapter.IItem
-import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.parsers.FrostNotifs
import com.pitchedapps.frost.facebook.parsers.NotifParser
import com.pitchedapps.frost.facebook.parsers.ParseResponse
-import com.pitchedapps.frost.facebook.requests.MenuFooterItem
-import com.pitchedapps.frost.facebook.requests.MenuHeader
-import com.pitchedapps.frost.facebook.requests.MenuItem
-import com.pitchedapps.frost.facebook.requests.MenuItemData
-import com.pitchedapps.frost.facebook.requests.fbAuth
-import com.pitchedapps.frost.facebook.requests.getMenuData
-import com.pitchedapps.frost.iitems.ClickableIItemContract
-import com.pitchedapps.frost.iitems.MenuContentIItem
-import com.pitchedapps.frost.iitems.MenuFooterIItem
-import com.pitchedapps.frost.iitems.MenuFooterSmallIItem
-import com.pitchedapps.frost.iitems.MenuHeaderIItem
import com.pitchedapps.frost.iitems.NotificationIItem
import com.pitchedapps.frost.utils.frostJsoup
import com.pitchedapps.frost.views.FrostRecyclerView
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
/**
* Created by Allan Wang on 27/12/17.
+ *
+ * Retained as an example. Deletion made at https://github.com/AllanWang/Frost-for-Facebook/pull/1542
*/
+@Deprecated(message = "Retained as an example; currently does not support marking a notification as read")
class NotificationFragment : FrostParserFragment<FrostNotifs, NotificationIItem>() {
override val parser = NotifParser
@@ -55,33 +43,3 @@ class NotificationFragment : FrostParserFragment<FrostNotifs, NotificationIItem>
NotificationIItem.bindEvents(adapter)
}
}
-
-class MenuFragment : GenericRecyclerFragment<MenuItemData, IItem<*, *>>() {
-
- override fun mapper(data: MenuItemData): IItem<*, *> = when (data) {
- is MenuHeader -> MenuHeaderIItem(data)
- is MenuItem -> MenuContentIItem(data)
- is MenuFooterItem ->
- if (data.isSmall) MenuFooterSmallIItem(data)
- else MenuFooterIItem(data)
- else -> throw IllegalArgumentException("Menu item in fragment has invalid type ${data::class.java.simpleName}")
- }
-
- override fun bindImpl(recyclerView: FrostRecyclerView) {
- ClickableIItemContract.bindEvents(adapter)
- }
-
- override suspend fun reloadImpl(progress: (Int) -> Unit): List<MenuItemData>? =
- withContext(Dispatchers.IO) {
- val cookie = FbCookie.webCookie ?: return@withContext null
- progress(10)
- val auth = fbAuth.fetch(cookie).await()
- progress(30)
- val data = auth.getMenuData().invoke() ?: return@withContext null
- if (data.data.isEmpty()) return@withContext null
- progress(70)
- val items = data.flatMapValid()
- progress(90)
- return@withContext items
- }
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/iitems/MenuIItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/iitems/MenuIItem.kt
deleted file mode 100644
index ee0cd94c..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/MenuIItem.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.pitchedapps.frost.iitems
-
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import ca.allanwang.kau.iitems.KauIItem
-import ca.allanwang.kau.ui.createSimpleRippleDrawable
-import ca.allanwang.kau.utils.bindView
-import ca.allanwang.kau.utils.gone
-import ca.allanwang.kau.utils.visible
-import com.mikepenz.fastadapter.FastAdapter
-import com.pitchedapps.frost.R
-import com.pitchedapps.frost.facebook.requests.MenuFooterItem
-import com.pitchedapps.frost.facebook.requests.MenuHeader
-import com.pitchedapps.frost.facebook.requests.MenuItem
-import com.pitchedapps.frost.glide.FrostGlide
-import com.pitchedapps.frost.glide.GlideApp
-import com.pitchedapps.frost.utils.Prefs
-
-/**
- * Created by Allan Wang on 30/12/17.
- */
-class MenuContentIItem(val data: MenuItem) :
- KauIItem<MenuContentIItem, MenuContentIItem.ViewHolder>(R.layout.iitem_menu, ::ViewHolder),
- ClickableIItemContract {
-
- override val url: String?
- get() = data.url
-
- class ViewHolder(itemView: View) : FastAdapter.ViewHolder<MenuContentIItem>(itemView) {
-
- val frame: ViewGroup by bindView(R.id.item_frame)
- val icon: ImageView by bindView(R.id.item_icon)
- val content: TextView by bindView(R.id.item_content)
- val badge: TextView by bindView(R.id.item_badge)
-
- override fun bindView(item: MenuContentIItem, payloads: MutableList<Any>) {
- frame.background = createSimpleRippleDrawable(Prefs.textColor, Prefs.nativeBgColor)
- content.setTextColor(Prefs.textColor)
- badge.setTextColor(Prefs.textColor)
- val iconUrl = item.data.pic
- if (iconUrl != null)
- GlideApp.with(itemView)
- .load(iconUrl)
- .transform(FrostGlide.circleCrop)
- .into(icon.visible())
- else
- icon.gone()
- content.text = item.data.name
- badge.text = item.data.badge
- }
-
- override fun unbindView(item: MenuContentIItem) {
- GlideApp.with(itemView).clear(icon)
- content.text = null
- badge.text = null
- }
- }
-}
-
-class MenuHeaderIItem(val data: MenuHeader) : HeaderIItem(
- data.header,
- itemId = R.id.item_menu_header
-)
-
-class MenuFooterIItem(val data: MenuFooterItem) :
- TextIItem(data.name, data.url, R.id.item_menu_footer)
-
-class MenuFooterSmallIItem(val data: MenuFooterItem) :
- TextIItem(data.name, data.url, R.id.item_menu_footer_small)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt
index cfbb928b..1806d351 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt
@@ -34,7 +34,6 @@ import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.parsers.FrostNotif
import com.pitchedapps.frost.glide.FrostGlide
import com.pitchedapps.frost.glide.GlideApp
-import com.pitchedapps.frost.services.FrostRunnable
import com.pitchedapps.frost.utils.Prefs
import com.pitchedapps.frost.utils.isIndependent
import com.pitchedapps.frost.utils.launchWebOverlay
@@ -53,7 +52,6 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) :
.withOnClickListener { v, _, item, position ->
val notif = item.notification
if (notif.unread) {
- FrostRunnable.markNotificationRead(v!!.context, notif.id, item.cookie)
adapter.set(
position,
NotificationIItem(notif.copy(unread = false), item.cookie)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
index 6ff20bfb..e4d0b485 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
@@ -76,11 +76,7 @@ enum class NotificationType(
FbItem.NOTIFICATIONS,
NotifParser,
Prefs::notificationRingtone
- ) {
-
- override fun bindRequest(content: NotificationContent, cookie: String) =
- FrostRunnable.prepareMarkNotificationRead(content.id, cookie)
- },
+ ),
MESSAGE(
NOTIF_CHANNEL_MESSAGES,
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostRequestService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostRequestService.kt
deleted file mode 100644
index 77546971..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostRequestService.kt
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.pitchedapps.frost.services
-
-import android.app.job.JobInfo
-import android.app.job.JobParameters
-import android.app.job.JobScheduler
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.os.BaseBundle
-import android.os.PersistableBundle
-import com.pitchedapps.frost.facebook.requests.RequestAuth
-import com.pitchedapps.frost.facebook.requests.fbAuth
-import com.pitchedapps.frost.facebook.requests.markNotificationRead
-import com.pitchedapps.frost.utils.EnumBundle
-import com.pitchedapps.frost.utils.EnumBundleCompanion
-import com.pitchedapps.frost.utils.EnumCompanion
-import com.pitchedapps.frost.utils.L
-import com.pitchedapps.frost.utils.Prefs
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-
-/**
- * Created by Allan Wang on 28/12/17.
- */
-
-/**
- * Private helper data
- */
-private enum class FrostRequestCommands : EnumBundle<FrostRequestCommands> {
-
- NOTIF_READ {
-
- override fun invoke(auth: RequestAuth, bundle: PersistableBundle) {
- val id = bundle.getLong(ARG_0, -1L)
- val success = auth.markNotificationRead(id).invoke()
- L.d { "Marked notif $id as read: $success" }
- }
-
- override fun propagate(bundle: BaseBundle) =
- FrostRunnable.prepareMarkNotificationRead(
- bundle.getLong(ARG_0),
- bundle.getCookie()
- )
- };
-
- override val bundleContract: EnumBundleCompanion<FrostRequestCommands>
- get() = Companion
-
- /**
- * Call request with arguments inside bundle
- */
- abstract fun invoke(auth: RequestAuth, bundle: PersistableBundle)
-
- /**
- * Return bundle builder given arguments in the old bundle
- * Must not write to old bundle!
- */
- abstract fun propagate(bundle: BaseBundle): BaseBundle.() -> Unit
-
- companion object : EnumCompanion<FrostRequestCommands>("frost_arg_commands", values())
-}
-
-private const val ARG_COMMAND = "frost_request_command"
-private const val ARG_COOKIE = "frost_request_cookie"
-private const val ARG_0 = "frost_request_arg_0"
-private const val ARG_1 = "frost_request_arg_1"
-private const val ARG_2 = "frost_request_arg_2"
-private const val ARG_3 = "frost_request_arg_3"
-
-private fun BaseBundle.getCookie(): String = getString(ARG_COOKIE)!!
-private fun BaseBundle.putCookie(cookie: String) = putString(ARG_COOKIE, cookie)
-
-/**
- * Singleton handler for running requests in [FrostRequestService]
- * Requests are typically completely decoupled from the UI,
- * and are optional enhancers.
- *
- * Nothing guarantees the completion time, or whether it even executes at all
- *
- * Design:
- * prepare function - creates a bundle binder
- * actor function - calls the service with the given arguments
- *
- * Global:
- * propagator - given a bundle with a command, extracts and executes the requests
- */
-object FrostRunnable {
-
- fun prepareMarkNotificationRead(id: Long, cookie: String): BaseBundle.() -> Unit = {
- FrostRequestCommands.NOTIF_READ.put(this)
- putLong(ARG_0, id)
- putCookie(cookie)
- }
-
- fun markNotificationRead(context: Context, id: Long, cookie: String): Boolean {
- if (id <= 0) {
- L.d { "Invalid notification id $id for marking as read" }
- return false
- }
- return schedule(
- context, FrostRequestCommands.NOTIF_READ,
- prepareMarkNotificationRead(id, cookie)
- )
- }
-
- fun propagate(context: Context, intent: Intent?) {
- val extras = intent?.extras ?: return
- val command = FrostRequestCommands[intent] ?: return
- intent.removeExtra(ARG_COMMAND) // reset
- L.d { "Propagating command ${command.name}" }
- val builder = command.propagate(extras)
- schedule(context, command, builder)
- }
-
- private fun schedule(
- context: Context,
- command: FrostRequestCommands,
- bundleBuilder: PersistableBundle.() -> Unit
- ): Boolean {
- val scheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
- val serviceComponent = ComponentName(context, FrostRequestService::class.java)
- val bundle = PersistableBundle()
- bundle.bundleBuilder()
- bundle.putString(ARG_COMMAND, command.name)
-
- if (bundle.getCookie().isNullOrBlank()) {
- L.e { "Scheduled frost request with empty cookie" }
- return false
- }
-
- val builder = JobInfo.Builder(REQUEST_SERVICE_BASE + command.ordinal, serviceComponent)
- .setMinimumLatency(0L)
- .setExtras(bundle)
- .setOverrideDeadline(2000L)
- .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
- val result = scheduler.schedule(builder.build())
- if (result <= 0) {
- L.eThrow("FrostRequestService scheduler failed for ${command.name}")
- return false
- }
- L.d { "Scheduled ${command.name}" }
- return true
- }
-}
-
-class FrostRequestService : BaseJobService() {
-
- override fun onStartJob(params: JobParameters?): Boolean {
- super.onStartJob(params)
- if (!Prefs.authRequests) {
- L.i { "Auth requests disabled; skipping request service" }
- return false
- }
- val bundle = params?.extras
- if (bundle == null) {
- L.eThrow("Launched ${this::class.java.simpleName} without param data")
- return false
- }
- val cookie = bundle.getCookie()
- if (cookie.isBlank()) {
- L.eThrow("Launched ${this::class.java.simpleName} without cookie")
- return false
- }
- val command = FrostRequestCommands[bundle]
- if (command == null) {
- L.eThrow("Launched ${this::class.java.simpleName} without command")
- return false
- }
- launch(Dispatchers.IO) {
- try {
- val auth = fbAuth.fetch(cookie).await()
- command.invoke(auth, bundle)
- L.d {
- "Finished frost service for ${command.name} in ${System.currentTimeMillis() - startTime} ms"
- }
- } catch (e: Exception) {
- L.e(e) { "Failed frost service for ${command.name} in ${System.currentTimeMillis() - startTime} ms" }
- } finally {
- jobFinished(params, false)
- }
- }
- return true
- }
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt
index a0a8117f..ba5b839b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt
@@ -79,13 +79,6 @@ fun SettingsActivity.getBehaviourPrefs(): KPrefAdapterBuilder.() -> Unit = {
}
}
- checkbox(R.string.native_ui, Prefs::nativeUi, {
- Prefs.nativeUi = it
- shouldRestartMain()
- }) {
- descRes = R.string.native_ui_desc
- }
-
checkbox(R.string.exit_confirmation, Prefs::exitConfirmation, { Prefs.exitConfirmation = it }) {
descRes = R.string.exit_confirmation_desc
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt
index 5647584e..9814fd76 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt
@@ -35,10 +35,6 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = {
// Experimental content starts here ------------------
- checkbox(R.string.auth_requests, Prefs::authRequests, { Prefs.authRequests = it }) {
- descRes = R.string.auth_requests_desc
- }
-
// Experimental content ends here --------------------
checkbox(R.string.verbose_logging, Prefs::verboseLogging, {
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 e2fac291..389cb6b7 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt
@@ -84,4 +84,4 @@ fun KauLoggerExtension.test(message: () -> Any?) {
if (BuildConfig.DEBUG) {
d { "Test1234 ${message()}" }
}
-} \ No newline at end of file
+}
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 522e1733..eb8e4b35 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
@@ -191,10 +191,6 @@ object Prefs : KPref() {
var showCreateFab: Boolean by kpref("show_create_fab", true)
- var authRequests: Boolean by kpref("web_requests", false)
-
- var nativeUi: Boolean by kpref("native_ui", true)
-
inline val mainActivityLayout: MainActivityLayout
get() = MainActivityLayout(mainActivityLayoutType)