aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2019-05-01 17:05:22 -0700
committerGitHub <noreply@github.com>2019-05-01 17:05:22 -0700
commite7a499f6314f8d6345b19c3e221f3cd9cd176d4f (patch)
treea19cbd9b60a218cdc3370ea83e565fd8ab086881
parentda93672c2ed6b54e0e7119a6b55715185112df3e (diff)
parent547bf6f932b56a4f66e9eb1d9f175e7db4e4512e (diff)
downloadfrost-e7a499f6314f8d6345b19c3e221f3cd9cd176d4f.tar.gz
frost-e7a499f6314f8d6345b19c3e221f3cd9cd176d4f.tar.bz2
frost-e7a499f6314f8d6345b19c3e221f3cd9cd176d4f.zip
Merge pull request #1416 from AllanWang/misc
Misc
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt11
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt1
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt4
-rw-r--r--app/src/main/res/xml/frost_changelog.xml3
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt10
-rw-r--r--app/src/web/scss/core/_core_text.scss2
-rw-r--r--app/src/web/ts/click_a.ts93
-rw-r--r--app/src/web/ts/context_a.ts33
-rw-r--r--gradle.properties8
11 files changed, 120 insertions, 56 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
index 41c6ff4b..0c762b41 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
@@ -45,7 +45,9 @@ import com.raizlabs.android.dbflow.config.DatabaseConfig
import com.raizlabs.android.dbflow.config.FlowConfig
import com.raizlabs.android.dbflow.config.FlowManager
import com.raizlabs.android.dbflow.runtime.ContentResolverNotifier
-import org.koin.android.ext.android.startKoin
+import org.koin.android.ext.koin.androidContext
+import org.koin.android.ext.koin.androidLogger
+import org.koin.core.context.startKoin
import java.util.Random
import kotlin.reflect.KClass
@@ -134,7 +136,12 @@ class FrostApp : Application() {
L.d { "Activity ${activity.localClassName} created" }
}
})
- startKoin(this, listOf(FrostDatabase.module(this)))
+ startKoin {
+ if (BuildConfig.DEBUG)
+ androidLogger()
+ androidContext(this@FrostApp)
+ modules(FrostDatabase.module(this@FrostApp))
+ }
}
private fun initBugsnag() {
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 67372e23..cd5fce02 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt
@@ -21,8 +21,8 @@ import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.pitchedapps.frost.BuildConfig
-import org.koin.dsl.module.module
-import org.koin.standalone.StandAloneContext
+import org.koin.core.context.GlobalContext
+import org.koin.dsl.module
interface FrostPrivateDao {
fun cookieDao(): CookieDao
@@ -101,6 +101,6 @@ class FrostDatabase(private val privateDb: FrostPrivateDatabase, private val pub
* Get from koin
* For the most part, you can retrieve directly from other koin components
*/
- fun get(): FrostDatabase = StandAloneContext.getKoin().koinContext.get()
+ fun get(): FrostDatabase = GlobalContext.get().koin.get()
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
index 76ffd8cd..557980af 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
@@ -186,7 +186,8 @@ fun MaterialDialog.Builder.theme(): MaterialDialog.Builder {
}
fun Activity.setFrostTheme(forceTransparent: Boolean = false) {
- val isTransparent = (Color.alpha(Prefs.bgColor) != 255) || (Color.alpha(Prefs.headerColor) != 255) || forceTransparent
+ val isTransparent =
+ (Color.alpha(Prefs.bgColor) != 255) || (Color.alpha(Prefs.headerColor) != 255) || forceTransparent
if (Prefs.bgColor.isColorDark)
setTheme(if (isTransparent) R.style.FrostTheme_Transparent else R.style.FrostTheme)
else
@@ -357,7 +358,7 @@ val dependentSegments = arrayOf(
)
inline val String?.isExplicitIntent
- get() = this != null && startsWith("intent://")
+ get() = this != null && (startsWith("intent://") || startsWith("market://"))
fun Context.frostChangelog() = showChangelog(R.xml.frost_changelog, Prefs.textColor) {
theme()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
index 81ade98f..b06208a6 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
@@ -75,7 +75,6 @@ fun FrostWebView.requestWebOverlay(url: String): Boolean {
}
if (!Prefs.overlayEnabled) return false
if (context is WebOverlayActivityBase) {
- L.v { "Check web request from overlay" }
val shouldUseDesktop = url.formattedFbUrl.shouldUseDesktopAgent
//already overlay; manage user agent
if (userAgentString != USER_AGENT_DESKTOP && shouldUseDesktop) {
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 594da00a..66176aba 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt
@@ -47,8 +47,8 @@ import com.pitchedapps.frost.services.NotificationContent
import com.pitchedapps.frost.services.NotificationType
import com.pitchedapps.frost.utils.Prefs
import com.pitchedapps.frost.utils.toReadableTime
-import org.koin.standalone.KoinComponent
-import org.koin.standalone.inject
+import org.koin.core.KoinComponent
+import org.koin.core.inject
class NotificationWidget : AppWidgetProvider() {
diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml
index 560b1111..93124f75 100644
--- a/app/src/main/res/xml/frost_changelog.xml
+++ b/app/src/main/res/xml/frost_changelog.xml
@@ -9,7 +9,8 @@
<version title="v2.3.0" />
<item text="Converted internals of Facebook data storage; auto migration will only work from 2.2.x to 2.3.x" />
<item text="Added notification widget" />
- <item text="" />
+ <item text="Update theme" />
+ <item text="Update translations" />
<item text="" />
<item text="" />
<item text="" />
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt
index e93f507c..5cde7323 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt
@@ -246,6 +246,8 @@ class CoroutineTest {
}
}
+ class TestException(msg: String) : RuntimeException(msg)
+
@Test
fun exceptionChecks() {
val mainTag = "main-test"
@@ -257,7 +259,7 @@ class CoroutineTest {
val job = SupervisorJob()
val flyweight = Flyweight<Int, Int>(GlobalScope, 200L) {
- throw java.lang.RuntimeException("Flyweight exception")
+ throw TestException("Flyweight exception")
}
suspend fun crash(): Boolean = withContext(Dispatchers.IO) {
@@ -266,7 +268,7 @@ class CoroutineTest {
flyweight.fetch(0).await()
}
true
- } catch (e: java.lang.Exception) {
+ } catch (e: TestException) {
false
}
}
@@ -282,10 +284,6 @@ class CoroutineTest {
println("B")
channel.offer(1)
}
-// launch {
-// delay(2000)
-// job.cancel()
-// }
}
}
}
diff --git a/app/src/web/scss/core/_core_text.scss b/app/src/web/scss/core/_core_text.scss
index 63622610..2142ef73 100644
--- a/app/src/web/scss/core/_core_text.scss
+++ b/app/src/web/scss/core/_core_text.scss
@@ -19,7 +19,7 @@ textarea:not([style*="color: rgb"]), ._24pi, ._4en9, ._1kb, ._5p7j, ._2klz, ._57
div.sharerSelector, .footer, ._4pv_, ._1dbp, ._3kad, ._20zc, ._2i5v, ._2i5w,
a, ._5fpq, ._4gux, ._3bg5 ._52x1, ._3bg5 ._52x2, ._6dsj ._3gin, ._hdn._hdn,
.mentions-input:not([style*="color: rgb"]), .mentions-placeholder:not([style*="color: rgb"]),
-.largeStatusBox .placeHolder, .fcw, ._2rgt, ._67i4 ._5hu6 ._59tt,
+.largeStatusBox .placeHolder, .fcw, ._2rgt, ._67i4 ._5hu6 ._59tt, ._2bu3, ._2bu4,
._5-7t, .fcl, ._4qas, .thread-title, .title, ._46pa, ._336p, ._1rrd, ._2om4,
._3m1m, ._2om2, ._5n_e, .appListExplanation, ._5yt8, ._8he, ._2luw, ._5rgs,
h1, h2, h3, h4, h5, h6 {
diff --git a/app/src/web/ts/click_a.ts b/app/src/web/ts/click_a.ts
index 5023610e..8d1d545b 100644
--- a/app/src/web/ts/click_a.ts
+++ b/app/src/web/ts/click_a.ts
@@ -1,34 +1,81 @@
(function () {
let prevented = false;
+ /**
+ * Go up at most [depth] times, to retrieve a parent matching the provided predicate
+ * If one is found, it is returned immediately.
+ * Otherwise, null is returned.
+ */
+ function _parentEl(el: HTMLElement, depth: number, predicate: (el: HTMLElement) => boolean): HTMLElement | null {
+ for (let i = 0; i < depth + 1; i++) {
+ if (predicate(el)) {
+ return el
+ }
+ const parent = el.parentElement;
+ if (!parent) {
+ return null
+ }
+ el = parent
+ }
+ return null
+ }
+
+ /**
+ * Attempts to find a url entry at most [depth] away
+ * A url is found if the element has tag 'A', and the url isn't blank
+ */
+ function _parentUrl(el: HTMLElement, depth: number): string | null {
+ const element = _parentEl(el, depth, (el) => el.tagName === 'A');
+ if (!element) {
+ return null;
+ }
+ const url = element.getAttribute('href');
+ if (!url || url === '#') {
+ return null;
+ }
+ return url
+ }
+
+ /**
+ * Given event and target, return true if handled and false otherwise.
+ */
+ type EventHandler = (e: Event, target: HTMLElement) => Boolean
+
+ const _frostGeneral: EventHandler = (e, target) => {
+ // Notifications are two layers under
+ const url = _parentUrl(target, 2);
+ return Frost.loadUrl(url);
+ };
+
+ const _frostLaunchpadClick: EventHandler = (e, target) => {
+ if (!_parentEl(target, 6, (el) => el.id === 'launchpad')) {
+ return false
+ }
+ console.log('Clicked launchpad');
+ const url = _parentUrl(target, 5);
+ return Frost.loadUrl(url);
+ };
+
+ const handlers: EventHandler[] = [_frostLaunchpadClick, _frostGeneral];
+
const _frostAClick = (e: Event) => {
- // check for valid target
+ if (prevented) {
+ console.log("Click intercept prevented");
+ return
+ }
+ /*
+ * Commonality; check for valid target
+ */
const target = e.target || e.currentTarget || e.srcElement;
- if (!(target instanceof Element)) {
+ if (!(target instanceof HTMLElement)) {
console.log("No element found");
return
}
- let element: Element = target;
- // Notifications are two layers under
- for (let i = 0; i < 2; i++) {
- if (element.tagName !== 'A') {
- element = <Element>element.parentElement;
- }
- }
- if (element.tagName === 'A') {
- if (!prevented) {
- const url = element.getAttribute('href');
- if (!url || url === '#') {
- return
- }
- console.log(`Click intercept ${url}`);
- // If Frost is injected, check if loading the url through an overlay works
- if (Frost.loadUrl(url)) {
- e.stopPropagation();
- e.preventDefault();
- }
- } else {
- console.log("Click intercept prevented")
+ for (const h of handlers) {
+ if (h(e, target)) {
+ e.stopPropagation();
+ e.preventDefault();
+ return
}
}
};
diff --git a/app/src/web/ts/context_a.ts b/app/src/web/ts/context_a.ts
index 5eec7611..b9549f3f 100644
--- a/app/src/web/ts/context_a.ts
+++ b/app/src/web/ts/context_a.ts
@@ -7,6 +7,25 @@
let longClick = false;
/**
+ * Go up at most [depth] times, to retrieve a parent matching the provided predicate
+ * If one is found, it is returned immediately.
+ * Otherwise, null is returned.
+ */
+ function _parentEl(el: HTMLElement, depth: number, predicate: (el: HTMLElement) => boolean): HTMLElement | null {
+ for (let i = 0; i < depth + 1; i++) {
+ if (predicate(el)) {
+ return el
+ }
+ const parent = el.parentElement;
+ if (!parent) {
+ return null
+ }
+ el = parent
+ }
+ return null
+ }
+
+ /**
* Given event and target, return true if handled and false otherwise.
*/
type EventHandler = (e: Event, target: HTMLElement) => Boolean
@@ -55,16 +74,8 @@
* Opens image activity for posts with just one image
*/
const _frostImage: EventHandler = (e, target) => {
- let element: Element = target;
- // Notifications are two layers under
- for (let i = 0; i < 2; i++) {
- if (element.tagName !== 'A') {
- element = <Element>element.parentElement;
- } else {
- break
- }
- }
- if (element.tagName !== 'A') {
+ const element = _parentEl(target, 2, (el) => el.tagName === 'A');
+ if (!element) {
return false;
}
const url = element.getAttribute('href');
@@ -92,7 +103,7 @@
return true;
};
- const handlers = [_frostImage, _frostCopyComment, _frostCopyPost];
+ const handlers: EventHandler[] = [_frostImage, _frostCopyComment, _frostCopyPost];
const _frostAContext = (e: Event) => {
Frost.longClick(true);
diff --git a/gradle.properties b/gradle.properties
index 86e6040a..84d8a461 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -17,7 +17,7 @@ APP_ID=Frost
APP_GROUP=com.pitchedapps
KAU=4.0.0
-KOTLIN=1.3.21
+KOTLIN=1.3.31
# https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google
ANDROID_GRADLE=3.3.2
@@ -41,7 +41,7 @@ DBFLOW=4.2.4
# https://github.com/brianwernick/ExoMedia/releases
EXOMEDIA=4.3.0
# https://github.com/InsertKoinIO/koin/blob/master/CHANGELOG.md
-KOIN=1.0.2
+KOIN=2.0.0-rc-2
# https://github.com/mockk/mockk/releases
MOCKK=1.9.3
# https://mvnrepository.com/artifact/androidx.core/core-ktx?repo=google
@@ -56,10 +56,10 @@ LEAK_CANARY=1.6.2
# https://github.com/zsmb13/MaterialDrawerKt/releases
MATERIAL_DRAWER_KT=2.0.1
# https://github.com/square/okhttp/releases
-OKHTTP=3.14.0
-# http://robolectric.org/getting-started/
+OKHTTP=3.14.1
# https://developer.android.com/jetpack/androidx/releases/room
ROOM=2.1.0-alpha04
+# http://robolectric.org/getting-started/
ROBOELECTRIC=4.2
# https://github.com/davemorrissey/subsampling-scale-image-view#quick-start
SCALE_IMAGE_VIEW=3.10.0