diff options
Diffstat (limited to 'app/src')
46 files changed, 344 insertions, 188 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt index 4461be71..e2ccb8e5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt @@ -127,7 +127,8 @@ class AboutActivity : AboutActivityBase(null, { } } - class AboutLinks : AbstractItem<AboutLinks, AboutLinks.ViewHolder>(), ThemableIItem by ThemableIItemDelegate() { + class AboutLinks : AbstractItem<AboutLinks, AboutLinks.ViewHolder>(), + ThemableIItem by ThemableIItemDelegate() { override fun getViewHolder(v: View): ViewHolder = ViewHolder(v) override fun getType(): Int = R.id.item_about_links @@ -166,22 +167,24 @@ class AboutActivity : AboutActivityBase(null, { CommunityMaterial.Icon2.cmd_slack to { c.startLink(R.string.slack_url) }, CommunityMaterial.Icon2.cmd_xda to { c.startLink(R.string.xda_url) }) - images = (icons.map { (icon, onClick) -> c.drawable(icon) to onClick } + iicons.map { (icon, onClick) -> - icon.toDrawable( - c, - 32 - ) to onClick - }).mapIndexed { i, (icon, onClick) -> - ImageView(c).apply { - layoutParams = ViewGroup.LayoutParams(size, size) - id = 109389 + i - setImageDrawable(icon) - scaleType = ImageView.ScaleType.CENTER - background = context.resolveDrawable(android.R.attr.selectableItemBackgroundBorderless) - setOnClickListener { onClick() } - container.addView(this) + images = + (icons.map { (icon, onClick) -> c.drawable(icon) to onClick } + iicons.map { (icon, onClick) -> + icon.toDrawable( + c, + 32 + ) to onClick + }).mapIndexed { i, (icon, onClick) -> + ImageView(c).apply { + layoutParams = ViewGroup.LayoutParams(size, size) + id = 109389 + i + setImageDrawable(icon) + scaleType = ImageView.ScaleType.CENTER + background = + context.resolveDrawable(android.R.attr.selectableItemBackgroundBorderless) + setOnClickListener { onClick() } + container.addView(this) + } } - } val set = ConstraintSet() set.clone(container) set.createHorizontalChain( diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt index a1b41830..87454c10 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt @@ -91,7 +91,8 @@ class DebugActivity : KauBaseActivity() { } } - val hasScreenshot: Boolean = debug_webview.getScreenshot(File(parent, "screenshot.png")) + val hasScreenshot: Boolean = + debug_webview.getScreenshot(File(parent, "screenshot.png")) val intent = Intent() intent.putExtra(RESULT_URL, debug_webview.url) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt index 94f8d6c1..eeda94d4 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt @@ -137,7 +137,10 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.On fun finish(x: Float, y: Float) { val blue = color(R.color.facebook_blue) - window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) + window.setFlags( + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + ) ripple.ripple(blue, x, y, 600) { postDelayed(1000) { finish() } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt index c3224237..686768cc 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt @@ -52,9 +52,15 @@ class SelectorActivity : BaseActivity() { adapter.add(cookies().map { AccountItem(it) }) adapter.add(AccountItem(null)) // add account adapter.withEventHook(object : ClickEventHook<AccountItem>() { - override fun onBind(viewHolder: RecyclerView.ViewHolder): View? = (viewHolder as? AccountItem.ViewHolder)?.v + override fun onBind(viewHolder: RecyclerView.ViewHolder): View? = + (viewHolder as? AccountItem.ViewHolder)?.v - override fun onClick(v: View, position: Int, fastAdapter: FastAdapter<AccountItem>, item: AccountItem) { + override fun onClick( + v: View, + position: Int, + fastAdapter: FastAdapter<AccountItem>, + item: AccountItem + ) { if (item.cookie == null) this@SelectorActivity.launchNewTask<LoginActivity>() else launch { FbCookie.switchUser(item.cookie) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt index 6ad7d3f2..eae4d717 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt @@ -66,7 +66,8 @@ class TabCustomizerActivity : BaseActivity() { pseudo_toolbar.setBackgroundColor(Prefs.headerColor) - tab_recycler.layoutManager = GridLayoutManager(this, TAB_COUNT, RecyclerView.VERTICAL, false) + tab_recycler.layoutManager = + GridLayoutManager(this, TAB_COUNT, RecyclerView.VERTICAL, false) tab_recycler.adapter = adapter tab_recycler.setHasFixedSize(true) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt b/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt index 73d5c56d..4853e7ff 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt @@ -66,11 +66,18 @@ class FileChooserDelegate : FileChooserContract { val intent = Intent() intent.type = fileChooserParams.acceptTypes.firstOrNull() intent.action = Intent.ACTION_GET_CONTENT - startActivityForResult(Intent.createChooser(intent, string(R.string.pick_image)), MEDIA_CHOOSER_RESULT) + startActivityForResult( + Intent.createChooser(intent, string(R.string.pick_image)), + MEDIA_CHOOSER_RESULT + ) } } - override fun Activity.onActivityResultWeb(requestCode: Int, resultCode: Int, intent: Intent?): Boolean { + override fun Activity.onActivityResultWeb( + requestCode: Int, + resultCode: Int, + intent: Intent? + ): Boolean { L.d { "FileChooser On activity results web $requestCode" } if (requestCode != MEDIA_CHOOSER_RESULT) return false val data = intent?.data diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt index b81ce365..82548396 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt @@ -83,7 +83,11 @@ object CookiesDb { @Parcelize @Table(database = CookiesDb::class, allFields = true, primaryKeyConflict = ConflictAction.REPLACE) -data class CookieModel(@PrimaryKey var id: Long = -1L, var name: String? = null, var cookie: String? = null) : +data class CookieModel( + @PrimaryKey var id: Long = -1L, + var name: String? = null, + var cookie: String? = null +) : BaseModel(), Parcelable { override fun toString(): String = "CookieModel(${hashCode()})" diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt index cd5fce02..5519f6a8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt @@ -59,7 +59,10 @@ interface FrostDao : FrostPrivateDao, FrostPublicDao { /** * Composition of all database interfaces */ -class FrostDatabase(private val privateDb: FrostPrivateDatabase, private val publicDb: FrostPublicDatabase) : +class FrostDatabase( + private val privateDb: FrostPrivateDatabase, + private val publicDb: FrostPublicDatabase +) : FrostDao, FrostPrivateDao by privateDb, FrostPublicDao by publicDb { @@ -71,11 +74,12 @@ class FrostDatabase(private val privateDb: FrostPrivateDatabase, private val pub companion object { - private fun <T : RoomDatabase> RoomDatabase.Builder<T>.frostBuild() = if (BuildConfig.DEBUG) { - fallbackToDestructiveMigration().build() - } else { - build() - } + private fun <T : RoomDatabase> RoomDatabase.Builder<T>.frostBuild() = + if (BuildConfig.DEBUG) { + fallbackToDestructiveMigration().build() + } else { + build() + } fun create(context: Context): FrostDatabase { val privateDb = Room.databaseBuilder( diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/FbTabsDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/FbTabsDb.kt index a704ce82..475d134f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/db/FbTabsDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/db/FbTabsDb.kt @@ -35,4 +35,5 @@ object FbTabsDb { } @Table(database = FbTabsDb::class, allFields = true) -data class FbTabModel(@PrimaryKey var position: Int = -1, var tab: FbItem = FbItem.FEED) : BaseModel() +data class FbTabModel(@PrimaryKey var position: Int = -1, var tab: FbItem = FbItem.FEED) : + BaseModel() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/NotificationDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/NotificationDb.kt index 813c39a3..e89bf46d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/db/NotificationDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/db/NotificationDb.kt @@ -140,14 +140,20 @@ suspend fun NotificationDao.deleteAll() = dao { _deleteAll() } fun NotificationDao.selectNotificationsSync(userId: Long, type: String): List<NotificationContent> = _selectNotifications(userId, type).map { it.toNotifContent() } -suspend fun NotificationDao.selectNotifications(userId: Long, type: String): List<NotificationContent> = dao { +suspend fun NotificationDao.selectNotifications( + userId: Long, + type: String +): List<NotificationContent> = dao { selectNotificationsSync(userId, type) } /** * Returns true if successful, given that there are constraints to the insertion */ -suspend fun NotificationDao.saveNotifications(type: String, notifs: List<NotificationContent>): Boolean = dao { +suspend fun NotificationDao.saveNotifications( + type: String, + notifs: List<NotificationContent> +): Boolean = dao { try { _saveNotifications(type, notifs) true @@ -187,7 +193,11 @@ class NotificationMigration2(modelClass: Class<NotificationModel>) : } } -@Table(database = NotificationDb::class, allFields = true, primaryKeyConflict = ConflictAction.REPLACE) +@Table( + database = NotificationDb::class, + allFields = true, + primaryKeyConflict = ConflictAction.REPLACE +) data class NotificationModel( @PrimaryKey var id: Long = -1L, var epoch: Long = -1L, diff --git a/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt b/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt index 6bb50ccd..8215de03 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt @@ -222,15 +222,16 @@ class OfflineWebsite( } } - suspend fun loadAndZip(name: String, progress: (Int) -> Unit = {}): Boolean = withContext(Dispatchers.IO) { - coroutineScope { - val success = load { progress((it * 0.85f).toInt()) } - if (!success) return@coroutineScope false - val result = zip(name) - progress(100) - return@coroutineScope result + suspend fun loadAndZip(name: String, progress: (Int) -> Unit = {}): Boolean = + withContext(Dispatchers.IO) { + coroutineScope { + val success = load { progress((it * 0.85f).toInt()) } + if (!success) return@coroutineScope false + val result = zip(name) + progress(100) + return@coroutineScope result + } } - } private fun downloadFile(url: String): Boolean { return try { 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 0c1da3a3..b1bb3fb8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt @@ -77,11 +77,12 @@ object FbCookie { } } - private suspend fun CookieManager.setSingleWebCookie(cookie: String): Boolean = suspendCoroutine { cont -> - setCookie(COOKIE_DOMAIN, cookie.trim()) { - cont.resume(it) + private suspend fun CookieManager.setSingleWebCookie(cookie: String): Boolean = + suspendCoroutine { cont -> + setCookie(COOKIE_DOMAIN, cookie.trim()) { + cont.resume(it) + } } - } suspend fun save(id: Long) { L.d { "New cookie found" } 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 82e15111..a09b5d39 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbItem.kt @@ -50,7 +50,12 @@ enum class FbItem( MENU(R.string.menu, GoogleMaterial.Icon.gmd_menu, "settings", ::MenuFragment), 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", + ::NotificationFragment + ), 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"), @@ -77,4 +82,5 @@ enum class FbItem( companion object : EnumCompanion<FbItem>("frost_arg_fb_item", values()) } -fun defaultTabs(): List<FbItem> = listOf(FbItem.FEED, FbItem.MESSAGES, FbItem.NOTIFICATIONS, FbItem.MENU) +fun defaultTabs(): List<FbItem> = + listOf(FbItem.FEED, FbItem.MESSAGES, FbItem.NOTIFICATIONS, FbItem.MENU) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/FrostParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/FrostParser.kt index 6af21259..1240614b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/FrostParser.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/FrostParser.kt @@ -99,7 +99,8 @@ internal fun <T> List<T>.toJsonString(tag: String, indent: Int) = StringBuilder( * T should have a readable toString() function * [redirectToText] dictates whether all data should be converted to text then back to document before parsing */ -internal abstract class FrostParserBase<out T : ParseData>(private val redirectToText: Boolean) : FrostParser<T> { +internal abstract class FrostParserBase<out T : ParseData>(private val redirectToText: Boolean) : + FrostParser<T> { final override fun parse(cookie: String?) = parseFromUrl(cookie, url) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/MessageParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/MessageParser.kt index 00a1432f..3705448a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/MessageParser.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/MessageParser.kt @@ -38,7 +38,8 @@ import org.jsoup.nodes.Element */ object MessageParser : FrostParser<FrostMessages> by MessageParserImpl() { - fun queryUser(cookie: String?, name: String) = parseFromUrl(cookie, "${FbItem.MESSAGES.url}/?q=$name") + fun queryUser(cookie: String?, name: String) = + parseFromUrl(cookie, "${FbItem.MESSAGES.url}/?q=$name") } data class FrostMessages( @@ -120,7 +121,10 @@ private class MessageParserImpl : FrostParserBase<FrostMessages>(true) { override fun parseImpl(doc: Document): FrostMessages? { val threadList = doc.getElementById("threadlist_rows") ?: return null val threads: List<FrostThread> = - threadList.getElementsByAttributeValueMatching("id", ".*${FB_MESSAGE_NOTIF_ID_MATCHER.pattern}.*") + threadList.getElementsByAttributeValueMatching( + "id", + ".*${FB_MESSAGE_NOTIF_ID_MATCHER.pattern}.*" + ) .mapNotNull(this::parseMessage) val seeMore = parseLink(doc.getElementById("see_older_threads")) val extraLinks = threadList.nextElementSibling().select("a") diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/NotifParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/NotifParser.kt index faeaa27c..f9db0a8f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/NotifParser.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/NotifParser.kt @@ -96,7 +96,8 @@ private class NotifParserImpl : FrostParserBase<FrostNotifs>(false) { val notifications = notificationList .getElementsByAttributeValueMatching("id", ".*${FB_NOTIF_ID_MATCHER.pattern}.*") .mapNotNull(this::parseNotif) - val seeMore = parseLink(doc.getElementsByAttributeValue("href", "/notifications.php?more").first()) + val seeMore = + parseLink(doc.getElementsByAttributeValue("href", "/notifications.php?more").first()) return FrostNotifs(notifications, seeMore) } @@ -109,7 +110,8 @@ private class NotifParserImpl : FrostParserBase<FrostNotifs>(false) { ?: System.currentTimeMillis() % FALLBACK_TIME_MOD val img = element.getInnerImgStyle() val timeString = abbr.text() - val content = a.text().replace("\u00a0", " ").removeSuffix(timeString).trim() //remove + val content = + a.text().replace("\u00a0", " ").removeSuffix(timeString).trim() //remove val thumbnail = element.selectFirst("img.thumbnail")?.attr("src") return FrostNotif( id = id, 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 36dff6ff..1b5e8b99 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 @@ -52,18 +52,19 @@ fun RequestAuth.getFullSizedImage(fbid: Long) = frostRequest(::getJsonUrl) { /** * Attempts to get the fbcdn url of the supplied image redirect url */ -suspend fun String.getFullSizedImageUrl(url: String, timeout: Long = 3000): String? = withContext(Dispatchers.IO) { - try { - withTimeout(timeout) { - val redirect = requestBuilder().url(url).get().call() - .execute().body()?.string() ?: return@withTimeout null - FB_REDIRECT_URL_MATCHER.find(redirect)[1]?.formattedFbUrl +suspend fun String.getFullSizedImageUrl(url: String, timeout: Long = 3000): String? = + withContext(Dispatchers.IO) { + try { + withTimeout(timeout) { + val redirect = requestBuilder().url(url).get().call() + .execute().body()?.string() ?: return@withTimeout null + FB_REDIRECT_URL_MATCHER.find(redirect)[1]?.formattedFbUrl + } + } catch (e: Exception) { + L.e(e) { "Failed to load full size image url" } + null } - } catch (e: Exception) { - L.e(e) { "Failed to load full size image url" } - null } -} /** * Request loader for a potentially hd version of a url @@ -135,7 +136,8 @@ class HdImageFetcher(private val model: HdImageMaybe) : DataFetcher<InputStream> 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") + 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() @@ -145,7 +147,9 @@ class HdImageFetcher(private val model: HdImageMaybe) : DataFetcher<InputStream> if (result.isSuccess) callback.onDataReady(result.getOrNull()) else - callback.onLoadFailed(result.exceptionOrNull() as? Exception ?: RuntimeException("Failed")) + callback.onLoadFailed( + result.exceptionOrNull() as? Exception ?: RuntimeException("Failed") + ) } override fun cleanup() { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt index 9f2d704c..71c27dd2 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt @@ -50,23 +50,24 @@ abstract class RecyclerFragment<T, Item : IItem<*, *>> : BaseFragment(), Recycle } } - final override suspend fun reload(progress: (Int) -> Unit): Boolean = withContext(Dispatchers.IO) { - val data = try { - reloadImpl(progress) - } catch (e: Exception) { - L.e(e) { "Recycler reload fail $baseUrl" } - null - } - withMainContext { - if (data == null) { - valid = false - false - } else { - adapter.setNewList(data) - true + final override suspend fun reload(progress: (Int) -> Unit): Boolean = + withContext(Dispatchers.IO) { + val data = try { + reloadImpl(progress) + } catch (e: Exception) { + L.e(e) { "Recycler reload fail $baseUrl" } + null + } + withMainContext { + if (data == null) { + valid = false + false + } else { + adapter.setNewList(data) + true + } } } - } protected abstract suspend fun reloadImpl(progress: (Int) -> Unit): List<T>? } @@ -95,7 +96,8 @@ abstract class GenericRecyclerFragment<T, Item : IItem<*, *>> : RecyclerFragment open fun getAdapter(): FastAdapter<IItem<*, *>> = fastAdapter(this.adapter) } -abstract class FrostParserFragment<T : ParseData, Item : IItem<*, *>> : RecyclerFragment<Item, Item>() { +abstract class FrostParserFragment<T : ParseData, Item : IItem<*, *>> : + RecyclerFragment<Item, Item>() { /** * The parser to make this all happen @@ -125,24 +127,25 @@ abstract class FrostParserFragment<T : ParseData, Item : IItem<*, *>> : Recycler */ open fun getAdapter(): FastAdapter<IItem<*, *>> = fastAdapter(this.adapter) - override suspend fun reloadImpl(progress: (Int) -> Unit): List<Item>? = withContext(Dispatchers.IO) { - progress(10) - val cookie = FbCookie.webCookie - val doc = getDoc(cookie) - progress(60) - val response = try { - parser.parse(cookie, doc) - } catch (ignored: Exception) { - null - } - if (response == null) { - L.i { "RecyclerFragment failed for ${baseEnum.name}" } - L._d { "Cookie used: $cookie" } - return@withContext null + override suspend fun reloadImpl(progress: (Int) -> Unit): List<Item>? = + withContext(Dispatchers.IO) { + progress(10) + val cookie = FbCookie.webCookie + val doc = getDoc(cookie) + progress(60) + val response = try { + parser.parse(cookie, doc) + } catch (ignored: Exception) { + null + } + if (response == null) { + L.i { "RecyclerFragment failed for ${baseEnum.name}" } + L._d { "Cookie used: $cookie" } + return@withContext null + } + progress(80) + val items = toItems(response) + progress(97) + return@withContext items } - progress(80) - val items = toItems(response) - progress(97) - return@withContext items - } } 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 d9d518b1..54ea388d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt @@ -71,16 +71,17 @@ class MenuFragment : GenericRecyclerFragment<MenuItemData, IItem<*, *>>() { 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 - } + 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 index d20e8cde..ee0cd94c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/MenuIItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/MenuIItem.kt @@ -80,6 +80,8 @@ class MenuHeaderIItem(val data: MenuHeader) : HeaderIItem( itemId = R.id.item_menu_header ) -class MenuFooterIItem(val data: MenuFooterItem) : TextIItem(data.name, data.url, R.id.item_menu_footer) +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) +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 8b196a64..cfbb928b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt @@ -54,7 +54,10 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) : 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)) + adapter.set( + position, + NotificationIItem(notif.copy(unread = false), item.cookie) + ) } // TODO temp fix. If url is dependent, we cannot load it directly v!!.context.launchWebOverlay(if (notif.url.isIndependent) notif.url else FbItem.NOTIFICATIONS.url) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt index e7efbf2a..a7bde583 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt @@ -52,7 +52,8 @@ enum class CssAssets(val folder: String = THEME_FOLDER) : InjectorContract { */ private val injector = lazyContext { try { - var content = it.assets.open("css/$folder/$file").bufferedReader().use(BufferedReader::readText) + var content = + it.assets.open("css/$folder/$file").bufferedReader().use(BufferedReader::readText) if (this == CUSTOM) { val bt = if (Color.alpha(Prefs.bgColor) == 255) Prefs.bgColor.toRgbaString() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt index a8cd13ae..4c53dcda 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt @@ -26,8 +26,11 @@ import android.webkit.WebView enum class CssHider(vararg val items: String) : InjectorContract { CORE("[data-sigil=m_login_upsell]", "[role=progressbar]"), HEADER( - "#header:not(.mFuturePageHeader):not(.titled)", "#mJewelNav", "[data-sigil=MTopBlueBarHeader]", - "#header-notices", "[data-sigil*=m-promo-jewel-header]" + "#header:not(.mFuturePageHeader):not(.titled)", + "#mJewelNav", + "[data-sigil=MTopBlueBarHeader]", + "#header-notices", + "[data-sigil*=m-promo-jewel-header]" ), ADS( "article[data-xt*=sponsor]", diff --git a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt index afa8df35..d760d416 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt @@ -47,7 +47,9 @@ class IntroFragmentTheme : BaseIntroFragment(R.layout.intro_theme) { intro_theme_glass.setThemeClick(Theme.GLASS) val currentTheme = Prefs.theme - 1 if (currentTheme in 0..3) - themeList.forEachIndexed { index, v -> v.scaleXY = if (index == currentTheme) 1.6f else 0.8f } + themeList.forEachIndexed { index, v -> + v.scaleXY = if (index == currentTheme) 1.6f else 0.8f + } } private fun View.setThemeClick(theme: Theme) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt b/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt index 56acfc11..084cd5e6 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt @@ -67,7 +67,8 @@ class Flyweight<K, V>( completeExceptionally(result.exceptionOrNull()!!) } - private val errHandler = CoroutineExceptionHandler { _, throwable -> L.d { "FbAuth failed ${throwable.message}" } } + private val errHandler = + CoroutineExceptionHandler { _, throwable -> L.d { "FbAuth failed ${throwable.message}" } } init { job = diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt index 1d983f14..95726974 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -84,32 +84,33 @@ class NotificationService : BaseJobService() { return true } - private suspend fun sendNotifications(params: JobParameters?): Unit = withContext(Dispatchers.Default) { - val currentId = Prefs.userId - val cookies = cookieDao.selectAll() - yield() - val jobId = params?.extras?.getInt(NOTIFICATION_PARAM_ID, -1) ?: -1 - var notifCount = 0 - for (cookie in cookies) { + private suspend fun sendNotifications(params: JobParameters?): Unit = + withContext(Dispatchers.Default) { + val currentId = Prefs.userId + val cookies = cookieDao.selectAll() yield() - val current = cookie.id == currentId - if (Prefs.notificationsGeneral && - (current || Prefs.notificationAllAccounts) - ) - notifCount += fetch(jobId, NotificationType.GENERAL, cookie) - if (Prefs.notificationsInstantMessages && - (current || Prefs.notificationsImAllAccounts) - ) - notifCount += fetch(jobId, NotificationType.MESSAGE, cookie) - } + val jobId = params?.extras?.getInt(NOTIFICATION_PARAM_ID, -1) ?: -1 + var notifCount = 0 + for (cookie in cookies) { + yield() + val current = cookie.id == currentId + if (Prefs.notificationsGeneral && + (current || Prefs.notificationAllAccounts) + ) + notifCount += fetch(jobId, NotificationType.GENERAL, cookie) + if (Prefs.notificationsInstantMessages && + (current || Prefs.notificationsImAllAccounts) + ) + notifCount += fetch(jobId, NotificationType.MESSAGE, cookie) + } - L.i { "Sent $notifCount notifications" } - if (notifCount == 0 && jobId == NOTIFICATION_JOB_NOW) - generalNotification(665, R.string.no_new_notifications, BuildConfig.DEBUG) - if (notifCount > 0) { - NotificationWidget.forceUpdate(this@NotificationService) + L.i { "Sent $notifCount notifications" } + if (notifCount == 0 && jobId == NOTIFICATION_JOB_NOW) + generalNotification(665, R.string.no_new_notifications, BuildConfig.DEBUG) + if (notifCount > 0) { + NotificationWidget.forceUpdate(this@NotificationService) + } } - } /** * Implemented fetch to also notify when an error occurs diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt index 7327d098..8a8893e5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationUtils.kt @@ -58,7 +58,10 @@ fun setupNotificationChannels(c: Context) { } @RequiresApi(Build.VERSION_CODES.O) -private fun NotificationManager.createNotificationChannel(id: String, name: String): NotificationChannel { +private fun NotificationManager.createNotificationChannel( + id: String, + name: String +): NotificationChannel { val channel = NotificationChannel( id, name, NotificationManager.IMPORTANCE_DEFAULT @@ -85,7 +88,11 @@ fun Context.frostNotification(id: String) = * Delegates to channels if Android O and up * Otherwise uses our provided preferences */ -fun NotificationCompat.Builder.setFrostAlert(context: Context, enable: Boolean, ringtone: String): NotificationCompat.Builder { +fun NotificationCompat.Builder.setFrostAlert( + context: Context, + enable: Boolean, + ringtone: String +): NotificationCompat.Builder { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { setGroupAlertBehavior( if (enable) NotificationCompat.GROUP_ALERT_CHILDREN diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt index 718b2dbb..4391b3ca 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt @@ -133,7 +133,10 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { header(R.string.global_customization) - text(R.string.main_activity_layout, Prefs::mainActivityLayoutType, { Prefs.mainActivityLayoutType = it }) { + text( + R.string.main_activity_layout, + Prefs::mainActivityLayoutType, + { Prefs.mainActivityLayoutType = it }) { textGetter = { string(Prefs.mainActivityLayout.titleRes) } onClick = { materialDialog { 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 31a31238..ba5b839b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt @@ -21,7 +21,6 @@ import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.facebook.FB_URL_BASE import com.pitchedapps.frost.utils.Prefs -import com.pitchedapps.frost.utils.REQUEST_REFRESH import com.pitchedapps.frost.utils.launchWebOverlay /** diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt index ea50a57b..8017997b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt @@ -60,7 +60,8 @@ fun SettingsActivity.getDebugPrefs(): KPrefAdapterBuilder.() -> Unit = { plainText(R.string.debug_web) { descRes = R.string.debug_web_desc - onClick = { this@getDebugPrefs.startActivityForResult<DebugActivity>(ACTIVITY_REQUEST_DEBUG) } + onClick = + { this@getDebugPrefs.startActivityForResult<DebugActivity>(ACTIVITY_REQUEST_DEBUG) } } plainText(R.string.debug_parsers) { 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 41a60594..7aac7526 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt @@ -34,7 +34,10 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = { descRes = R.string.experimental_disclaimer_info } - checkbox(R.string.experimental_by_default, Showcase::experimentalDefault, { Showcase.experimentalDefault = it }) { + checkbox( + R.string.experimental_by_default, + Showcase::experimentalDefault, + { Showcase.experimentalDefault = it }) { descRes = R.string.experimental_by_default_desc } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt index 40ff071e..4ef76b3b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt @@ -48,13 +48,20 @@ import kotlinx.coroutines.launch @SuppressLint("InlinedApi") fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = { - text(R.string.notification_frequency, Prefs::notificationFreq, { Prefs.notificationFreq = it }) { + text( + R.string.notification_frequency, + Prefs::notificationFreq, + { Prefs.notificationFreq = it }) { val options = longArrayOf(15, 30, 60, 120, 180, 300, 1440, 2880) - val texts = options.map { if (it <= 0) string(R.string.no_notifications) else minuteToText(it) } + val texts = + options.map { if (it <= 0) string(R.string.no_notifications) else minuteToText(it) } onClick = { materialDialog { title(R.string.notification_frequency) - listItemsSingleChoice(items = texts, initialSelection = options.indexOf(item.pref)) { _, index, _ -> + listItemsSingleChoice( + items = texts, + initialSelection = options.indexOf(item.pref) + ) { _, index, _ -> item.pref = options[index] scheduleNotifications(item.pref) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt index db901073..4ececc8b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt @@ -53,7 +53,8 @@ object BiometricUtils { @Suppress("DEPRECATION") fun isSupported(context: Context): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false - val fingerprintManager = context.getSystemService(FingerprintManager::class.java) ?: return false + val fingerprintManager = + context.getSystemService(FingerprintManager::class.java) ?: return false return fingerprintManager.isHardwareDetected && fingerprintManager.hasEnrolledFingerprints() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/TimeUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/TimeUtils.kt index c0feab1e..6156badb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/TimeUtils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/TimeUtils.kt @@ -39,8 +39,18 @@ fun Long.toReadableTime(context: Context): String { val timeFormatter = SimpleDateFormat.getTimeInstance(DateFormat.SHORT) val time = timeFormatter.format(Date(this)) val day = when { - cal >= Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -1) } -> context.string(R.string.today) - cal >= Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -2) } -> context.string(R.string.yesterday) + cal >= Calendar.getInstance().apply { + add( + Calendar.DAY_OF_MONTH, + -1 + ) + } -> context.string(R.string.today) + cal >= Calendar.getInstance().apply { + add( + Calendar.DAY_OF_MONTH, + -2 + ) + } -> context.string(R.string.yesterday) else -> { val dayFormatter = SimpleDateFormat("MMM dd", Locale.getDefault()) dayFormatter.format(Date(this)) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt index 0a3be830..7fdd485d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt @@ -33,7 +33,8 @@ import com.pitchedapps.frost.facebook.formattedFbUrl fun Context.showWebContextMenu(wc: WebContext) { if (wc.isEmpty) return var title = wc.url ?: string(R.string.menu) - title = title.substring(title.indexOf("m/") + 1) //just so if defaults to 0 in case it's not .com/ + title = + title.substring(title.indexOf("m/") + 1) //just so if defaults to 0 in case it's not .com/ if (title.length > 100) title = title.substring(0, 100) + '\u2026' val menuItems = WebContextType.values @@ -63,7 +64,10 @@ enum class WebContextType( val constraint: (wc: WebContext) -> Boolean, val onClick: (c: Context, wc: WebContext) -> Unit ) { - OPEN_LINK(R.string.open_link, { it.hasUrl }, { c, wc -> c.launchWebOverlay(wc.unformattedUrl!!) }), + OPEN_LINK( + R.string.open_link, + { it.hasUrl }, + { c, wc -> c.launchWebOverlay(wc.unformattedUrl!!) }), COPY_LINK(R.string.copy_link, { it.hasUrl }, { c, wc -> c.copyToClipboard(wc.url) }), COPY_TEXT(R.string.copy_text, { it.hasText }, { c, wc -> c.copyToClipboard(wc.text) }), SHARE_LINK(R.string.share_link, { it.hasUrl }, { c, wc -> c.shareText(wc.url) }), diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt index 51a7a8e9..9f2b8a5d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt @@ -42,9 +42,13 @@ class BadgedIcon @JvmOverloads constructor( init { inflate(context, R.layout.view_badged_icon, this) - val badgeColor = Prefs.mainActivityLayout.backgroundColor().withAlpha(255).colorToForeground(0.2f) + val badgeColor = + Prefs.mainActivityLayout.backgroundColor().withAlpha(255).colorToForeground(0.2f) val badgeBackground = - GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(badgeColor, badgeColor)) + GradientDrawable( + GradientDrawable.Orientation.BOTTOM_TOP, + intArrayOf(badgeColor, badgeColor) + ) badgeBackground.cornerRadius = 13.dpToPx.toFloat() badge_text.background = badgeBackground badge_text.setTextColor(Prefs.mainActivityLayout.iconColor()) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt index 97be8951..5e82f0e9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt @@ -96,7 +96,8 @@ class FrostRecyclerView @JvmOverloads constructor( * Otherwise scroll to top */ override fun onTabClicked() { - val firstPosition = (layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() + val firstPosition = + (layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() if (firstPosition == 0) reloadBase(true) else scrollToTop() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt index 4d88ad3d..8d433c9e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt @@ -68,14 +68,19 @@ class FrostVideoViewer @JvmOverloads constructor( * This is under the assumption that the container allows for overlays, * such as a FrameLayout */ - fun showVideo(url: String, repeat: Boolean, contract: FrostVideoContainerContract): FrostVideoViewer { + fun showVideo( + url: String, + repeat: Boolean, + contract: FrostVideoContainerContract + ): FrostVideoViewer { val container = contract.videoContainer val videoViewer = FrostVideoViewer(container.context) container.addView(videoViewer) videoViewer.bringToFront() videoViewer.setVideo(url, repeat) videoViewer.video.containerContract = contract - videoViewer.video.onFinishedListener = { container.removeView(videoViewer); contract.onVideoFinished() } + videoViewer.video.onFinishedListener = + { container.removeView(videoViewer); contract.onVideoFinished() } return videoViewer } } @@ -101,7 +106,8 @@ class FrostVideoViewer @JvmOverloads constructor( when (it.itemId) { R.id.action_pip -> video.isExpanded = false R.id.action_download -> context.ctxCoroutine.launchMain { - val cookie = FrostDatabase.get().cookieDao().currentCookie() ?: return@launchMain + val cookie = + FrostDatabase.get().cookieDao().currentCookie() ?: return@launchMain context.frostDownload(cookie, video.videoUri) } } @@ -162,7 +168,8 @@ class FrostVideoViewer @JvmOverloads constructor( } fun updateLocation() { - viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + viewTreeObserver.addOnGlobalLayoutListener(object : + ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { video.updateLocation() viewTreeObserver.removeOnGlobalLayoutListener(this) @@ -172,7 +179,9 @@ class FrostVideoViewer @JvmOverloads constructor( override fun onControlsShown() { if (video.isExpanded) - video_toolbar.fadeIn(duration = CONTROL_ANIMATION_DURATION, onStart = { video_toolbar.visible() }) + video_toolbar.fadeIn( + duration = CONTROL_ANIMATION_DURATION, + onStart = { video_toolbar.visible() }) } override fun onControlsHidden() { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/KPrefTextSeekbar.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/KPrefTextSeekbar.kt index 7f0d792a..e018b6d8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/KPrefTextSeekbar.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/KPrefTextSeekbar.kt @@ -50,7 +50,10 @@ class KPrefTextSeekbar(builder: KPrefSeekbarContract) : KPrefSeekbar(builder) { descOriginalSize = holder.desc?.textSize ?: 1f holder.desc?.layoutParams builder.toText = { - holder.desc?.setTextSize(TypedValue.COMPLEX_UNIT_PX, descOriginalSize * it.toFloat() / 100) + holder.desc?.setTextSize( + TypedValue.COMPLEX_UNIT_PX, + descOriginalSize * it.toFloat() / 100 + ) "$it%" } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt index e63fcc21..02c60288 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt @@ -58,7 +58,8 @@ class Keywords @JvmOverloads constructor( editText.tint(Prefs.textColor) addIcon.setImageDrawable(GoogleMaterial.Icon.gmd_add.keywordDrawable(context)) addIcon.setOnClickListener { - if (editText.text.isNullOrEmpty()) editText.error = context.string(R.string.empty_keyword) + if (editText.text.isNullOrEmpty()) editText.error = + context.string(R.string.empty_keyword) else { adapter.add(0, KeywordItem(editText.text.toString())) editText.text?.clear() @@ -71,7 +72,12 @@ class Keywords @JvmOverloads constructor( override fun onBind(viewHolder: RecyclerView.ViewHolder): View? = (viewHolder as? KeywordItem.ViewHolder)?.delete - override fun onClick(v: View, position: Int, fastAdapter: FastAdapter<KeywordItem>, item: KeywordItem) { + override fun onClick( + v: View, + position: Int, + fastAdapter: FastAdapter<KeywordItem>, + item: KeywordItem + ) { adapter.remove(position) } }) @@ -82,7 +88,8 @@ class Keywords @JvmOverloads constructor( } } -private fun IIcon.keywordDrawable(context: Context): Drawable = toDrawable(context, 20, Prefs.textColor) +private fun IIcon.keywordDrawable(context: Context): Drawable = + toDrawable(context, 20, Prefs.textColor) class KeywordItem(val keyword: String) : AbstractItem<KeywordItem, KeywordItem.ViewHolder>() { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt index 5c7c58f1..9e9c2340 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt @@ -83,7 +83,13 @@ class SwipeRefreshLayout @JvmOverloads constructor(context: Context, attrs: Attr return super.onInterceptTouchEvent(ev) } - override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) { + override fun onNestedScroll( + target: View, + dxConsumed: Int, + dyConsumed: Int, + dxUnconsumed: Int, + dyUnconsumed: Int + ) { if (preventRefresh) { /* * Ignoring offsetInWindow since diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt index da90e7e5..9577aeb0 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt @@ -73,7 +73,10 @@ class FrostChromeClient(web: FrostWebView) : WebChromeClient() { return activity != null } - override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) { + override fun onGeolocationPermissionsShowPrompt( + origin: String, + callback: GeolocationPermissions.Callback + ) { L.i { "Requesting geolocation" } context.kauRequestPermissions(PERMISSION_ACCESS_FINE_LOCATION) { granted, _ -> L.i { "Geolocation response received; ${if (granted) "granted" else "denied"}" } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt index bd696b02..ab910ebc 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt @@ -76,4 +76,5 @@ fun WebResourceResponse?.filter(filter: Boolean): WebResourceResponse? = this fun WebResourceResponse?.filterCss(request: WebResourceRequest): WebResourceResponse? = filter(request) { it.endsWith(".css") } -fun WebResourceResponse?.filterImage(request: WebResourceRequest): WebResourceResponse? = filter(request.isImage) +fun WebResourceResponse?.filterImage(request: WebResourceRequest): WebResourceResponse? = + filter(request.isImage) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt index 79c6d5ba..09796b15 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt @@ -62,16 +62,17 @@ class LoginWebView @JvmOverloads constructor( webChromeClient = LoginChromeClient() } - suspend fun loadLogin(progressCallback: (Int) -> Unit): CompletableDeferred<CookieEntity> = coroutineScope { - this@LoginWebView.progressCallback = progressCallback - L.d { "Begin loading login" } - launchMain { - FbCookie.reset() - setupWebview() - loadUrl(FB_LOGIN_URL) + suspend fun loadLogin(progressCallback: (Int) -> Unit): CompletableDeferred<CookieEntity> = + coroutineScope { + this@LoginWebView.progressCallback = progressCallback + L.d { "Begin loading login" } + launchMain { + FbCookie.reset() + setupWebview() + loadUrl(FB_LOGIN_URL) + } + completable } - completable - } private inner class LoginClient : BaseWebViewClient() { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt b/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt index 66176aba..f660383f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt @@ -52,7 +52,11 @@ import org.koin.core.inject class NotificationWidget : AppWidgetProvider() { - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { + override fun onUpdate( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: IntArray + ) { super.onUpdate(context, appWidgetManager, appWidgetIds) val type = NotificationType.GENERAL val userId = Prefs.userId @@ -87,7 +91,8 @@ class NotificationWidget : AppWidgetProvider() { companion object { fun forceUpdate(context: Context) { val manager = AppWidgetManager.getInstance(context) - val ids = manager.getAppWidgetIds(ComponentName(context, NotificationWidget::class.java)) + val ids = + manager.getAppWidgetIds(ComponentName(context, NotificationWidget::class.java)) val intent = Intent().apply { action = AppWidgetManager.ACTION_APPWIDGET_UPDATE putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids) @@ -109,7 +114,8 @@ private fun RemoteViews.setBackgroundColor(@IdRes viewId: Int, @ColorInt color: */ private fun RemoteViews.setIcon(@IdRes viewId: Int, context: Context, @DrawableRes res: Int, @ColorInt color: Int) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val icon = Icon.createWithResource(context, res).setTint(color).setTintMode(PorterDuff.Mode.SRC_IN) + val icon = + Icon.createWithResource(context, res).setTint(color).setTintMode(PorterDuff.Mode.SRC_IN) setImageViewIcon(viewId, icon) } else { val bitmap = BitmapFactory.decodeResource(context.resources, res) @@ -128,7 +134,8 @@ private fun RemoteViews.setIcon(@IdRes viewId: Int, context: Context, @DrawableR } class NotificationWidgetService : RemoteViewsService() { - override fun onGetViewFactory(intent: Intent): RemoteViewsFactory = NotificationWidgetDataProvider(this, intent) + override fun onGetViewFactory(intent: Intent): RemoteViewsFactory = + NotificationWidgetDataProvider(this, intent) companion object { fun createIntent(context: Context, type: NotificationType, userId: Long): Intent = @@ -138,7 +145,8 @@ class NotificationWidgetService : RemoteViewsService() { } } -class NotificationWidgetDataProvider(val context: Context, val intent: Intent) : RemoteViewsService.RemoteViewsFactory, +class NotificationWidgetDataProvider(val context: Context, val intent: Intent) : + RemoteViewsService.RemoteViewsFactory, KoinComponent { private val notifDao: NotificationDao by inject() @@ -179,7 +187,8 @@ class NotificationWidgetDataProvider(val context: Context, val intent: Intent) : views.setTextColor(R.id.item_date, Prefs.textColor.withAlpha(150)) views.setTextViewText(R.id.item_date, notif.timestamp.toReadableTime(context)) - val avatar = glide.load(notif.profileUrl).transform(FrostGlide.circleCrop).submit(avatarSize, avatarSize).get() + val avatar = glide.load(notif.profileUrl).transform(FrostGlide.circleCrop) + .submit(avatarSize, avatarSize).get() views.setImageViewBitmap(R.id.item_avatar, avatar) views.setOnClickFillInIntent(R.id.item_frame, type.putContentExtra(Intent(), notif)) return views diff --git a/app/src/main/play/en-US/whatsnew b/app/src/main/play/en-US/whatsnew index a9aab7e3..df5c33a5 100644 --- a/app/src/main/play/en-US/whatsnew +++ b/app/src/main/play/en-US/whatsnew @@ -3,4 +3,5 @@ v2.3.2 * Disable auto feed refresh by default and add setting to re-enable it * Update theme * Disable bugsnag completely when opting out of analytics -* Filter urls before sending to other apps
\ No newline at end of file +* Filter urls before sending to other apps +* Allow hiding main fab (see settings > newsfeed)
\ No newline at end of file |